iOS开发小技巧
AFNetworking网络请求返回3840错误解决方案
场景:
在日常开发的时候,跟PHP对接接口的时候,可能会有这样的约定,接口正常返回的数据信息或者一些用于提示用户和开发者的错误信息,使用AFNetworking解析成功的时候会以code、mag、data
这种返回:
{
code = 0;
data = <__NSArrayI 0x600000646270>(
10号线,
天通苑,
回龙观,
青年路
)
mag = @"";
}
针对这种情况,只需要判断code
码即可,根据不同的code
码显示不同的信息。
但是,有可能跟PHP对接接口的时候,遇到这总情况,接口正常返回的数据信息如下:

一些用于提示用户和开发者的错误信息会已,都会在error
里面显示,比如:

针对这总情况的时候,怎么去解析error
里面的信息,下面是解决方案:


只需要在failure
里面添加下面的代码。
NSData *data = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
if (data != nil) {
NSString *error = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"error--%@", error); // 就可以获取到错误时返回的body信息。
}
从AFNetworking源码中可以看出,AFNetworkingOperationFailingURLResponseDataErrorKey
这个key
对应着error
里面的useInfo
的data。

修改Xcode自身生成的文件注释

首先右键:
Xcode -->选项-->在Finder中打开-->右键-->显示包内容-->Contents-->Developer-->Platforms-->iPhoneOS.platform-->Developer-->Library-->Xcode-->Templates-->File Templates-->Source-->Cocoa Touch Class.xctemplate


注释就是我们要修改的,注意格式,跟我们创建文件的头部注释是一样的。
这里用到了几个系统的预处理宏定义,包括__FILENAME__
、__PROJECTNAME__
、__FULLUSERNAME__
、__DATE__
和__COPYRIGHT__
,分别表示的是文件名、项目名称、系统用户全称、当前日期和版权声明,这些宏定义可以用在我们修改之后的注释中,然后,自定义注释的格式,退出Xcode重新运行,然后创建新类,我们就会发现新的类文件格式:

忽略不必要的警告⚠️
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
return [target performSelector:action withObject:params];
#pragma clang diagnostic pop
iterm2 安装 powerline

解决方案
pip install powerline-status --user
获取float的前两位小数
当我们直接把 float 转为 NSString 会发现小数点后有很多小数,可以按照需求截取几位小数:
NSString *strDistance = [NSString stringWithFormat:@"%.xf", kilometers]; // x表示具体显示多少位
pop 到指定 ViewController
UINavigationController
有个 Property
,是一个存储所有 push
进 navigationcontroller
的视图的集合,是一个栈结构,当我们要 pop
到某个 ViewController
的时候,直接用 for in
去遍历 viewControllers
即可:
for (UIViewController viewController in self.navigationController.viewControllers) {
if ([viewController isKindOfClass:[AccountManageViewController class]]) {
[self.navigationController popToViewController:viewController animated:YES];
}
}
通过 View 获取 ViewController
为了做到数据与视图的分离,我们一般会将一个页面的局部视图以自定义 UIView
的方式独立出来,如果在该视图中有触发事件(事件处理不需要父视图的上下文),就会遇到在 UIView
中获取 UIViewController
的情况,可以写一个 UIView
的范畴 UIView(UIViewController)
:
#pragma mark - 获取当前view的viewcontroller
+ (UIViewController *)getCurrentViewController:(UIView *) currentView {
for (UIView* next = [currentView superview]; next; next = next.superview) {
UIResponder *nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)nextResponder;
}
}
return nil;
}
为文本加上下划线
基本就是用 NSMutableAttributedString
代替原来的 NSString
,然后为文本长度的 range
内添加一个下划线的属性。
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:button.titleLabel.text];
NSRange strRange = {0,[string length]};
[string addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:strRange];
[button setAttributedTitle:string forState:UIControlStateNormal];
二级页面隐藏 tabbar
一般会在 TabBarController
中设置多个 NavigationController
作为各个 tab
的 ViewController
。我们只要写一个 BaseViewController
,在其中重写 pushViewController:animated
方法,在其中判断是否需要隐藏就行。设置 hidesBottomBarWhenPushed
属性来控制在跳转的时候隐藏。
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (self.viewControllers.count) {
viewController.hidesBottomBarWhenPushed = YES;
}
[super pushViewController:viewController animated:animated];
}
设置Xcode在release下执行静态分析
在Build Settings
选项中的搜索栏中搜索关键字analyze during ‘Build’
,将Release
下面设置为Yes
即可。
iOS cocoapods一些用法备忘
一般我们在Podfile文件中指定在某个特定的scheme下引用某个框架,写法如下:
pod 'PgyUpdate', :configurations => ['Adhoc','AdhocDebug']
pod 'Reveal-iOS-SDK', '1.5.1', :configurations => ['Debug']
可以指定某个自定义框架的地址:
pod 'zucheLib_Category', :git => 'http://10.3.4.127:8888/ios_team/zuchelib_category.git', :tag => ‘0.1.2’
如果在自定义的框架下,我们使用#if DEBUG这种定义模式来区分,那么在默认Pods中是无效的。需要使用以下方法打开Debug的编译配置:
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
if target.name == 'zucheLib_Networking'
target.build_configurations.each do |config|
if config.name != 'Release'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'DEBUG=1']
end
end
end
end
end
如果多个target都需要引用某些公共的Pods类库框架可以使用如下写法:
def shared_pods
platform :ios, '7.0'
inhibit_all_warnings! # 关闭所有警告
#network
pod 'AFNetworking', '~> 3.0'
end
target "XXXXXXX" do
shared_pods
end
UILabel设置行间距并且计算文本高度所占内容
有时候我们在有些文本设计中需要对行间距有一些特殊的要求,那么uilabel是不能直接设置行间距的,那么我们应该如何来设置行间距呢?
设置行间距
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:self.stringData];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:10]; // 调整行间距
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [self.stringData length])];
contentLabel.attributedText = attributedString;
计算带有行间距的文本的高度
- (CGSize)getSizeWithLabelString:(NSString *)text
font:(UIFont *)font
width:(NSInteger)width
lineSpace:(NSInteger)lineSpace {
NSMutableAttributedString *attributedString =
[[NSMutableAttributedString alloc] initWithString:text];
NSMutableParagraphStyle *paragraphStyle =
[[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:lineSpace];
[attributedString addAttribute:NSParagraphStyleAttributeName
value:paragraphStyle
range:NSMakeRange(0, text.length)];
CGSize stringSize =
[text boundingRectWithSize:CGSizeMake(width, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading |
NSStringDrawingTruncatesLastVisibleLine
attributes:@{
NSFontAttributeName : font,
NSParagraphStyleAttributeName : paragraphStyle
} context:nil].size;
return stringSize;
}
iOS动态获取UILabel的高度和宽度
在使用UILabel存放字符串时,经常需要获取label的长宽数据,本文列出了部分常用的计算方法。
1.获取宽度,获取字符串不折行单行显示时所需要的长度:
CGSize titleSize = [aString sizeWithFont:font constrainedToSize:CGSizeMake(MAXFLOAT, 30)];
注:如果想得到宽度的话,size的width应该设为MAXFLOAT。
2.获取高度,获取字符串在指定的size内(宽度超过label的宽度则换行)所需的实际高度:
CGSize titleSize = [aString sizeWithFont:font constrainedToSize:CGSizeMake(label.frame.size.width, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];
注:如果想得到高度的话,size的height应该设为MAXFLOAT。
3.实际编程时,有时需要计算一段文字最后一个字符的位置,并在其后添加图片或其他控件(如info图标),下面代码为计算label中最后一个字符后面一位的位置的方法。
CGSize sz = [label.text sizeWithFont:label.font constrainedToSize:CGSizeMake(MAXFLOAT, 40)];
CGSize linesSz = [label.text sizeWithFont:label.font constrainedToSize:CGSizeMake(label.frame.size.width, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];
if (sz.width <= linesSz.width) { //判断是否折行
lastPoint = CGPointMake(label.frame.origin.x + sz.width, label.frame.origin.y);
} else {
lastPoint = CGPointMake(label.frame.origin.x + (int)sz.width % (int)linesSz.width,linesSz.height - sz.height);
}
ios7以后废弃了以上方法,转而采用下面这种方式来计算:
NSMutableParagraphStyle *pstyle = [[NSMutableParagraphStyle alloc] init];
pstyle.lineBreakMode = NSLineBreakByWordWrapping;
CGSize titleSize = [titleString sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:self.data.titleFontSize],NSParagraphStyleAttributeName:pstyle}];
CGRect titleRect = [titleString boundingRectWithSize:titleSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSParagraphStyleAttributeName: pstyle} context:nil];
执行brew install node

Error:Cannot write to /usr/local/Cellar
解决方法:
Check the permissions:
ls -ld /usr/local/Cellar
Open them up for writing:
sudo chmod a+w /usr/local/Cellar
Xcode插件管理器Alcatraz的安装和使用
一、简单说明
Alcatraz
是一款 Xcode
的插件管理工具,可以用来管理 XCode
的插件、模版以及颜色配置的工具。
二、如何安装
1、github地址:https://github.com/alcatraz/Alcatraz
2、安装方法
方法一:在命令行中输入如下指令:
curl -fsSL https://raw.github.com/alcatraz/Alcatraz/master/Scripts/install.sh | sh
图示:

注意:
在安装的过程中需要先把 XCode
退出,等安装完成之后重新打开 XCode
。等 Alcatraz successfully installed
,表示已经安装成功了。打开之后,会弹窗如下图所示,选择 load bunble
。
方法二:通过上面的 github
地址下载 Alcatraz
并 command +r
运行,完成后 command+q
退出 XCode
重启。
此时打开 XCode
可以检查是否安装成功。

三、如何使用
1、如何使用 Alcatraz
来安装插件
Alcatraz
安装成功后,选择Window->package Manager
,会打开 Alcatraz
的工作窗口。假设我们需要安装的VVDocumenter-Xcode插件,那么在搜索框中直接搜索VVDocumenter-Xcode即可。搜索完成之后界面显示如下。

点击
INSTALL
即可安装该插件,插件安装完成之后。显示如下,INSTALL
按钮变成 REMOVE
按钮。

command+q
把 XCode
退出,重新打开,选择下图中的 load bundle
按钮,到此 VVDocumenter-Xcode 就已经安装好了,可以直接使用。

2、如何使用 Alcatraz
来卸载插件
我们可以通过 Alcatraz
来查看当前 XCode
中集成了哪些插件。如果要卸载相关插件非常简单,点击插件左边的 Remove
按钮即可。

四、如何卸载
命令行输入:
rm -rf ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins/Alcatraz.xcplugin
神器iTools的巧妙使用
这几天,公司项目不怎么忙,然后利用些业余的时间,想仿一个app。下面介绍一下如果获取其他app的图片资源:
步骤
1、在MacX下载iTools软件,并安装,直接在百度上搜也能找到。

2、双击安装iTools,安装陈宫之后,在iTools中点击资源库,如果你连接上你的iPhone,这个按钮就在右上角,若没有连接iPhone,该按钮就在坐下角。


3、左边有网络资源和手机资源,点击网络资源下的苹果应用,在右上角搜索你要仿写的app,点击下载,此时如果你连着iPhone显示的就不是下载而是安装,此时会提示你输入apple id。这里以闲鱼为例:


4、选中下载的软件,然后点击上面的那一排按钮中的导出,保存到桌面上。

在桌面上找到下载好的ipa文件,右键该文件,选择一个解压软件打开该文件,切记不要使用iTunes打开,此时该路径下便会有个文件夹名为项目名称的文件夹。可以导出到桌面然后结归档就好了。

5、把解归档的文件夹进行打开就好了,资源都在里面,随便拿,有时候是乱的需要自己整理。

以上就是总结好的,神器iTools的巧妙使用。
dSYM 文件分析工具
如果项目中使用了友盟统计,对于友盟给出的错误信息统计,比如数组越界却只给出了 -[__NSArrayM objectAtIndex:]: index 50 beyond bounds [0 .. 39] 这类错误信息,如下图所示:

遇到这种问题一般会非常苦恼,也不知道项目中哪一个地方数组越界了。
1、什么是 dSYM 文件
Xcode
编译项目后,我们会看到一个同名的 dSYM
文件,dSYM
是保存 16 进制函数地址映射信息的中转文件,我们调试的 symbols
都会包含在这个文件中,并且每次编译项目的时候都会生成一个新的 dSYM
文件,位于 /Users/<用户名>/Library/Developer/Xcode/Archives
目录下,对于每一个发布版本我们都很有必要保存对应的 Archives
文件。

2、dSYM 文件有什么作用
当我们软件 release
模式打包或上线后,不会像我们在 Xcode
中那样直观的看到用崩溃的错误,这个时候我们就需要分析 crash report
文件了,iOS
设备中会有日志文件保存我们每个应用出错的函数内存地址,通过 Xcode
的 Organizer
可以将 iOS
设备中的 DeviceLog
导出成 crash
文件,这个时候我们就可以通过出错的函数地址去查询 dSYM
文件中程序对应的函数名和文件名。大前提是我们需要有软件版本对应的 dSYM
文件,这也是为什么我们很有必要保存每个发布版本的 Archives
文件了。
3、dSYM工具
下载 dSYM工具
- 从上面图片中,选中任意一个版本的xcarchive文件。
- 将打包发布软件时的xcarchive文件拖入软件窗口内的任意位置(支持多个文件同时拖入,注意:文件名不要包含空格)
- 书错误给出的UUID和工具界面中给出的UUID是否一致。
- 将错误地址输入工具的文本框中,点击分析。

注意:

1、就是每次 upload
发布版本所对应的 Archives
文件,直接拖到 dSYM
分析工具里面。
2、在 dSYM
分析工具里面点击 Archives
文件,UUID
自动填充。

3、打开统计(我们用的友盟统计),输入 Slide Address
。

4、分析,针对项目中的 Base Address
,逐个分析。

5、看到有可能出错的地方,逐个排查。
Charles之http、https配置

一. Charles安装
官网下载安装Charles:https://www.charlesproxy.com/download/
二、http配置
1、查看电脑IP地址
在终端上
ifconfig en4

或者

2、手机http代理配置
手机必须和电脑连接同一个局域网,点击“设置->无线局域网->选择连接的WiFi”,设置http代理:

端口号:8888
注意:端口号随便写。
3、Charles进行http配置


以美团返回的数据为例:

三、https代理配置
https代理配置必须要安装SSL证书
1、在手机上安装SSL证书
点击 Help -> SSL Proxying -> Install Charles Root Certificate on a Mobile Device

点击安装,得到SSL证书安装的地址

在手机Safari浏览器输入地址 chls.pro/ssl,出现证书安装页面,点击安装


2、Charles进行https配置
点击 Proxy -> SSL Proxying Settings...

勾选Enable SSL Proxying,点击Add。以https://api.weibo.cn为例,端口号填写443

