文章目录
  1. 1. 文档更新说明
  2. 2. 背景
    1. 2.1. UI相关
      1. 2.1.1. scrollView.contentOffect莫名等于-64
      2. 2.1.2. 设置控制器backBarButtonItem或者leftBarButtonItem无效
      3. 2.1.3. 使用addObserver监听视图的frame无效果
      4. 2.1.4. TabBarController与NavigationController谁嵌套谁?
      5. 2.1.5. iOS8中CollectionView加载速度异常慢
      6. 2.1.6. 多个CollectionView出现EXC_BAD_ACCESS
      7. 2.1.7. CollectionView的Cell中添加按钮无法响应事件
      8. 2.1.8. 代码设置UIButton.titleLaebl.title无效果
      9. 2.1.9. 为Scrollview中设置上下左右约束后提示ambiguous
      10. 2.1.10. 如何让设置约束的视图们执行动画?
      11. 2.1.11. 在interface界面里找不到Cell视图的contentView属性
      12. 2.1.12. 有时候无法在导航栏上摆放BarButtonItem
      13. 2.1.13. 如何在interface界面里和代码里设置导航栏的样式
      14. 2.1.14. 如何用代码写视图的宽高约束
      15. 2.1.15. 继承UIImageView的子类,drawRect:方法不被调用
      16. 2.1.16. 自定义toolBar上的UIBarButtonItem
      17. 2.1.17. 如何让重写的视图子类也支持直接在Xib,Storyboard中填写参数预览显示效果
      18. 2.1.18. 如何优雅地往TableView上添加无网络图片标记或者加载指示器
      19. 2.1.19. 如何去除TableView中多余的分割线
      20. 2.1.20. 让一个模态视图透明部分显示成上一个界面
      21. 2.1.21. 多用百分比实现自动布局
      22. 2.1.22. SearchBar底部有一条黑边
      23. 2.1.23. 定制SearchBar取消按钮颜色,输入框光标颜色
    2. 2.2. 数据相关
      1. 2.2.1. 系统自带的字典与JSON互转
      2. 2.2.2. 对象属性中有NSTimer对象,导致对象无法被释放的可能原因
      3. 2.2.3. 为什么NSDate显示的日期和设置的日期不同?
      4. 2.2.4. 使用信号量进行异步操作同步等待
      5. 2.2.5. 使用MJextension将字典转成json字符串需要注意的地方
      6. 2.2.6. CoreData报错:The model used to open the store is incompatible with the one used to create the store
      7. 2.2.7. 读取用户通讯录与审核问题
      8. 2.2.8. 如何读取本地json文件

文档更新说明

  • 第10次更新 2016年08月19日
  • 第9次更新 2016年08月04日
  • 第8次更新 2016年05月23日
  • 第7次更新 2016年05月10日
  • 第6次更新 2016年05月04日
  • 第5次更新 2016年04月25日
  • 第4次更新 2016年04月18日
  • 第3次更新 2016年04月13日
  • 第2次更新 2016年03月31日
  • 首次更新 2016年03月30日

背景

  记录我在iOS开发路上遇到的坑.

UI相关

scrollView.contentOffect莫名等于-64

  当控制器的view属性是scrollView类型,或者控制器view属性的第一个子视图是scrollView类型,或者控制器view属性的第一个子视图下面的首个子视图是scrollView属性的,控制器会自动给scrollView插入一个conentOffect = -64.(其他没列举出来的情况也可能出现,具体情况具体分析.-64其实就是状态栏和导航栏的高度,没导航栏的话就只有状态栏的偏移了).
  解决方案: 设置控制器automaticallyAdjustsScrollViewInsets = NO,另外如果导航栏不透明,还需要再设置extendedLayoutIncludesOpaqueBars = YES

1
2
//控制器view属性第一个子视图是wkWebView时
[self.view addSubview:self.webView];
1
2
3
//控制器view属性第一个子视图非scrollView类型时,控制器不会自动插入-64
[self.view addSubview:[[UIView alloc] init]];
[self.view addSubview:self.webView];

设置控制器backBarButtonItem或者leftBarButtonItem无效

  被NavigationController使用push显示的控制器,在控制器里面使用self. navigationController. navigationItem. leftBarButtonItem 或者使用self. navigationController. navigationItem. backBarButtonItem 去设置顶部返回按钮的内容,结果总是不起作用,连按钮的标题的改不了.
  解决方案:要在控制器内使用self.navigationItem.leftBarButtonItem才是正确的.参考下图

使用addObserver监听视图的frame无效果

  A视图拥有子视图B,视图B使用约束让其与A的frame一样.使用- (void)addObserver:(NSObject )anObserver forKeyPath:(NSString )keyPath options:(NSKeyValueObservingOptions)options context:(void )context 方法监听B的frame,然后改变A的frame,这个时候B视图虽然会随着A视图frame变化而变化,但是并不会触发监听事件- (void)observeValueForKeyPath:(NSString )keyPath ofObject:(id)object change:(NSDictionary )change context:(void )context
  解决方案:由于没有直接设置B的frame所以导致无法触发监听,可以直接监听A的frame就能触发监听事件了,另外这个坑我在实际开发中遇到,不知是不是规则如此还是另有原因

TabBarController与NavigationController谁嵌套谁?

  到底是TabBarController里面的每一个tiem页面都嵌套一个NavigationController,还是NavigationController嵌套TabBarController?这个问题对于确实值得讨论,需要结合实际需求选择.选择不妥当会虽然能实现同样的功能,但是不方便代码的设计.(下面简称tab,nav)
  解决方案:一个tab嵌套一个nav,nav push一个视图的时候如果将被push的视图设置为hideBottomBarOnPush的话,效果就是微信那样,圧入的视图会覆盖底部的tab按钮.而nav嵌套tab,然后push一个视图的话,不需要设置hideBottomBarOnPush效果也是微信那样.不过后者的话一会所有页面的navigationBar都是同一个.这里需要根据实际需求选择嵌套的方式.如果,不同页面有着不同的navigationBar,那就需要tab嵌套nav,相反则是nav嵌套tab.

iOS8中CollectionView加载速度异常慢

  如果在iOS8中,CollectionView 的Cell使用特殊字体就会导致这个问题,iOS9则无异常.
  解决方案:不使用特殊字体或者对字体做其他处理(暂时未使用到)

多个CollectionView出现EXC_BAD_ACCESS

  如果界面上使用多个CollectionView,同时引用同一个CollectionView的UICollectionViewLayout,则会出现这个错误.
  解决方案:为每一个CollectionView对象分配一个独立的Layout对象

CollectionView的Cell中添加按钮无法响应事件

  在xib文件中直接对CollectionViewCell添加一个按钮等界面元素,可能会发现,按钮无法点击,看上去Cell上的元素就像是一张图片一样,无法产生任何事件响应.
  解决方案:这是因为直接添加到cell上的元素,将会被cell的contentView视图覆盖住,所以无法做任何响应.正确的做法是,任何元素都不要直接添加到cell上,而是添加到cell.contentView上

代码设置UIButton.titleLaebl.title无效果

  直接在代码中设置UIButton.titleLabel.text,但是并没有任何效果.
  解决方案:设置按钮上的问题,需要结合官方文档里说的.因为按钮有多种状态,比如未选中,高亮,选中等,所以需要用setTitle:forState:设置文字.另外按钮的其他属性可能也需要用类似方法设置,具体参考官方文档

为Scrollview中设置上下左右约束后提示ambiguous

  有一个View,里面有一个scrollView,scrollView里面有一个按钮,为按钮设置top,宽高,leading约束.为scrollView设置了上下左右的约束后,仍然Xcode提示ScrollView has ambiguous scrollable content height.原因就是UIScrollView有一个contentSize属性.虽然按钮设置了宽,高,top,leading约束,但是仍然无法让系统确定contentSize的尺寸.
  解决方案:scrollView里的元素的约束必须全面,这样scrollView才能确定contentSize的尺寸.例如scrollView里面的元素必须设置上下左右宽高,这样才能让scrollView确定好内部的contentSize

如何让设置约束的视图们执行动画?

  举一个简单的例子如图,View视图有红,蓝两个子视图.蓝色视图约束为top,leading,hight,width.红色视图约束也和蓝色类型一样.现在想要一个这样的动画效果:当蓝色视图的高度变小时,红色视图在蓝色视图缩小过程向上移动.我尝试了直接给蓝色视图设置一个frame.size.height = 0的动画效果,结果是蓝色视图随便执行了动画,但是红色视图无任何变化.这里对于设置过约束的视图要产生动画效果需要用到另一种方法.
  解决方案:想要让约束在动画过程中一直生效,需要使用layoutIfNeeded这个方法,具体用法看最后代码.需要注意的是,如果没有达到预想的效果,肯定是约束没设置好,例如同时设置了视图的上下然后再变化高度,这样就无效果了

1
2
3
4
5
6
7
- (IBAction)move:(id)sender {
//设置蓝色视图height约束为10
self.heightConstraint.constant = 10;
[UIView animateWithDuration:3 animations:^{
[self.view layoutIfNeeded];
}];
}

在interface界面里找不到Cell视图的contentView属性

  有时候在xib或者storyboard文件中设置Cell视图的时候,却发现找不到contentView了,原因就是视图对象本身不是一个Cell视图,而是一个UIView视图.
  解决方案:从对象库面板里面拉取一个Cell视图替换掉UIView视图即可

有时候无法在导航栏上摆放BarButtonItem

  导航栏比较特殊,例如直接从对象库面板拉取一个NavigatinController,rootViewController默认是一个tableViewController,这时候是无法直接在导航栏添加BarButtonItem的.
  解决方案:需要将BarButtonItem摆放在Navigation Item上,而Navigation Item则需要放在navigation bar上

如何在interface界面里和代码里设置导航栏的样式

  在不熟悉的情况下,设置了效果往往无效,比如颜色等.
  下面总结一下导航栏的设置方法(注意,navigationController.navigationBar在viewDidLoad是nil,只有在控制器触发viewWillAppear方法后才有值)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
设置标题颜色,需要设置Title Color.
设置所有item颜色则需要设置View Tint属性,设置的item颜色会在push一个视图后,变成新视图的Bar Button item的默认颜色.
如果要设置整个Bar的背景颜色,需要设置Bar Tint属性.
下面总结一下用代码设置导航栏相关颜色和按钮的方法.
(1)设置导航栏标题颜色self.navigationController.navigationBar.titleTextAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor whiteColor],
UITextAttributeTextColor];
或者 self.navigationController.navigationBar.titleTextAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor whiteColor],
NSForegroundColorAttributeName, nil];
(2)设置导航栏背景颜色self.navigationController.navigationBar.barTintColor
(3)设置导航栏上面的bar button items文字颜色self.navigationController.navigationBar.tintColor;单独对item进行设置则是self.navigationItem.leftBarButtonItem.tintColor
(4)设置导航栏上的按钮,需要设置Root视图控制器的navigationItem属性,而不是直接设置导航控制器!因为导航控制后最终的item是会取值Root视图控制器的
* 注意,navigationController.navigationBar在viewDidLoad是nil,只有在控制器触发viewWillAppear方法后才有值

如何用代码写视图的宽高约束

  代码写约束一般用如下方法

1
2
3
4
5
6
7
+ (instancetype)constraintWithItem:(id)view1
attribute:(NSLayoutAttribute)attr1
relatedBy:(NSLayoutRelation)relation
toItem:(id)view2
attribute:(NSLayoutAttribute)attr2
multiplier:(CGFloat)multiplier
constant:(CGFloat)c

其中有一个问题,就是宽高约束这种参考对象就只有自己了,那么如何写呢?

  解决方案:

1
[self.userContactInfoView addConstraint:[NSLayoutConstraint constraintWithItem:self.userContactInfoView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:100]];

继承UIImageView的子类,drawRect:方法不被调用

  开发文档对这个问题进行了详细说明,为了提高ImageView的渲染效率,系统用的是另外的方式渲染视图,不是通过drawRect:方法来进行的.
  解决方案:根据文档的提示,不要继承UIImageView去实现展示图片的功能,如果有必要自定义展示图片功能的,那么实现UIView子类吧

自定义toolBar上的UIBarButtonItem

  UIBarButtonItem提供了创建UIBarButtonSystemItem的方法,也提供创建自定义视图的方法 - initWithCustomView:,所以想要完全自定义UIBarButtonItem,则可以使用创建自定义视图的方法,先生成一个按钮,自定义按钮,最后在通过initWithCustomView将按钮转化成UIBarButtonItem.
  实现方案:先做一个UIButton,可以添加图片文字,可以用EdgeInsets属性设置图片文字的偏移,然后使用- (instancetype)initWithCustomView:(UIView *)customView方法把按钮转成UIBarButtonItem,再把item以数组的形式加到 toolbarItems 就可以了.加到toolbar的item会自动有左右空隙,系统会自动摆放item到toolbar的y轴居中位置,只需要设置UIButton的width和height就可以了,点击事件也需要在UIButton上面加.

如何让重写的视图子类也支持直接在Xib,Storyboard中填写参数预览显示效果

  这个问题,应该是需要Xcode的支持,原理就是在类中加上一些能让xcode识别到的特殊标记.
  实现方案:具体的标记方法参考这个链接预览自定义视图子类

如何优雅地往TableView上添加无网络图片标记或者加载指示器

  这个问题还是比较有意思的,因为tableView上面会有很多cell,如果直接往tableView上添加的话,添加的视图会被cell覆盖,如果没有cell但是有分割线的时候,一样会被分割线覆盖.
  解决方案:1.等到cell都加载完了你再圧入自定义视图(比如在viewDidAppear:(BOOL)animated方法里面添加hud.或者在didload方法中延迟0.5s加载);2.自定义视图加入到tableView的父视图中,例如如果是tableView控制器,可以把自定义视图加入到控制器的view

如何去除TableView中多余的分割线

  因为tableView中的Cell只能设置显示或者不显示,显示的时候则满屏都显示,尽管Cell的数量还不够一瓶.
  解决方案:去除多余分割线主要有几种思路,一种是设置tableView不显示分割线,然后在Cell中用一个高度为1像素的UIView,放在Cell的底部作为分割线,这样可以随心所欲地修改分割线的模样.另一种则是实现- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section这个方法,然后在最后一个section里面返回一个[[UIView alloc] init],接着在- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section里面,返回高度0.5f,这样多余的分割线就不会显示出来了.(这种方法,最后一个Cell下面是没有分割线的).

让一个模态视图透明部分显示成上一个界面

  简单地将模态视图的背景颜色设置成透明,会直接看到黑色背景.
  解决方案:除了将视图设置成透明背景颜色之外,还需要设置另一个属性vc.modalPresentationStyle = UIModalPresentationOverCurrentContext,告诉系统要呈现视图栈中下一个视图.

多用百分比实现自动布局

  做第一个APP的时候,用自动布局时,大部分是使用相对某一个视图的top,bottom,trailing,leading有多少个点这种方式来实现,后来发现在6p上效果跟5s实在差太多了,导致每次遇到6p就要动态调节一下这个具体值,再后来我就想到了肯定有百分比布局的方法,所以现在会结合百分比布局和具体值布局两种方式来实现了.
  解决方案:这里我就不重复描述解决方案了.推荐一篇我参考过的文章AutoLayout 百分比布局

SearchBar底部有一条黑边

  为SearchBar设置了tintColor后,底部可能有一条黑线,这个具体原因也不清楚了,解决方案也比较取巧.
  解决方案:设置searchController.searchBar.layer.borderWidth = 1;searchController.searchBar.layer.borderColor为想要的颜色,从而替换掉黑边.

定制SearchBar取消按钮颜色,输入框光标颜色

  SearchBar比较特殊,系统并没有提供直接的设置接口.这里可以使用一种全局设置的方式重新定制它们的颜色.
  解决方案:参考下方代码

1
2
3
4
searchController.searchBar.tintColor = [UIColor lightGrayColor];
[[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil]
setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor whiteColor],NSForegroundColorAttributeName,nil] forState:UIControlStateNormal];

数据相关

系统自带的字典与JSON互转

  系统本身就系统了两者互转的API,可能不是很明显所以很多人都用了第三方库了.当然第三方库用起来比较方便.
  解决方案:字典JSON互转,比较麻烦.

1
2
3
4
5
6
7
//字典转JSON字符串
NSMutableDictionary *jsonDic = [[NSMutableDictionary alloc] init];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDic options:0 error:nil];
NSLog(@"%@",[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);
//JSON字符串转字典
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];

对象属性中有NSTimer对象,导致对象无法被释放的可能原因

  初始化NSTimer对象时一般需要设置一个target,如果这个target是A对象,然后这个定时器又被A对象的属性强引用,就会出现引用循环问题了.一定要等到调用timer的invalidate方法后才能解除循环引用.参考下面代码应该更加清晰.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@interface A : NSObject
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation A
//执行下面的代码后,self持有对timer的引用,timer也持有对self的引用,产生引用循环了,系统无法自动释放他们了.
- (void)startFireDateTimerFor {
NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:1];
self.timer = [[NSTimer alloc] initWithFireDate:fireDate
interval:1.0f
target:self
selector:@selector(countedTimerFire:)
userInfo:nil
repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.codeTimer forMode:NSDefaultRunLoopMode];
}
@end

  解决方案:在不需要A对象了或者不需要timer的地方,调用timer的invalidate,例如A是一个ViewController,那么就在ViewController将要disappear的时候调用invalidate

为什么NSDate显示的日期和设置的日期不同?

  给NSDate初始化一个指定时间,或者用[NSdate date]获取当前时间,不管你的设备是什么时区,使用NSLog打印出来的都是格林标准时间.那么何如打印出本地时间?如何获取当前时区的年月日等参数呢?
  解决方案:iOS中的NSDate时区问题.如果是通过字符串生成NSDate的,默认字符串就是参照设备时区再转换的.得到的NSdate可以看成是一个记录了时间戳的对象,如果要从NSDate里面获取到实际的年月日,一种是打印成字符串的,则需要使用descriptionWithLocale:,明确选择一个时区(例如[NSLocale currentLocale])再打印,否则就是显示默认的Greenwich Mean Time (GMT)了.另一种是要获取到年月日的,可以使用日历对象.[NSCalendar currentCalendar],这个实例化出来的就是一个本地日历,不需要再设置成本地时区.然后结合- (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDate:(NSDate *)date方法,就可以获取到一个完整的日期组件对象了.

使用信号量进行异步操作同步等待

  有时候某些操作是异步进行的,但是我们需要获取到数据才能进行下一步操作,这个时候可以使用信号量进行同步等待.
  解决方案:先创建一个信号量,在调用异步代码后进行等待信号量,在异步方法中最末尾部分发送信号量,详细代码如下:

1
2
3
4
5
6
7
8
9
10
//创建一个semaphore
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
//--异步代码--
//发送一个信号
dispatch_semaphore_signal(sema);
//--异步代码结束--
//等待信号
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

注意:在AFNetworking中无法使用信号量实现同步操作.使用信号量到了wait部分,主线程进入等待状态,所以网络数据接受到后也无法再通过主线程进入回调.所以无法触发回调中的释放信号量方法,导致程序永久卡死.

使用MJextension将字典转成json字符串需要注意的地方

  如果post给服务的数据是经过参数签名,那么就需要特别留意了.因为使用MJextension将模型(模型中有属性是数组类型)转换成字典,在将字典post给服务器的过程中字典会被AFNetWorking(假设是使用这个第三方库)转换成json字符串,同时去除多余的空格.而我们在做参数签名的时候如果将字典转成json字符串的规则跟AFNetWorking不同,则很可能转换出来的json字符串中数组部分会有多余的空格,从而导致参数签名失败.
  解决方案:使用MJExtension,遇到模型转字典时,如果字典有数组的,建议把数组先转成json字符串,然后再存回字典,这样在对字典里的内容做参数签名时才不容易出错;否则可能会出现参数签名跟实际上post的内容不一致从而导致签名错误.

CoreData报错:The model used to open the store is incompatible with the one used to create the store

  出现这个错误很可能是因为新增了xcdatamodeld文件,但是新增的文件没有被打包进APP里.
  解决方案:把APP删了,Product -> Clean一下项目,重新安装即可

读取用户通讯录与审核问题

  Apple提供了读取操作用户通讯录的接口,但是审核的时候非常严格,一不小心就因为这问题被拒绝了.
  解决方案:读取用户通讯录的时候,需要弹窗写明读取通讯录之后要干嘛用,而且在提交APP审核的时候需要提供一份隐私政策(也就是在APP资料哪里的隐私URL写上地址,这个会显示在商店APP界面的下面.如下图)

如何读取本地json文件

  json在OC里面对应的数据结构就是NSDictionary,那本地的json文件是用NSDictionary的相关类方法读取到的?其实不是,如果直接用NSDictionary的类方法读取得的一定是nil了.NSDictionary 有两个类方法用户初始化对象,分别是+ dictionaryWithContentsOfURL:和 + dictionaryWithContentsOfFile:,但是这两个方法使用来读取plist文件的,如果读取本地json文件,应该先把json转成字符串,再将字符串转成NSData,最后将NSData转成SDictionary.
  解决方案:具体代码如下:

1
2
3
4
NSString *jsonString = [NSString stringWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"region" withExtension:@"json"] encoding:NSUTF8StringEncoding error:nil];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *regionDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
//也可以使用 + dictionaryWithContentsOfFile:方法.

注意:URL实质上就是file:///开头的路径(file:///private/var/mobile/Containers/Bundle/Application/F09363E1-7F9F-4315-A3F2-4F08E6092E0A/LiveStone.app/region.json),而path则是从磁盘根目录开始的目录路径(/private/var/mobile/Containers/Bundle/Application/F09363E1-7F9F-4315-A3F2-4F08E6092E0A/LiveStone.app/region.json)

文章目录
  1. 1. 文档更新说明
  2. 2. 背景
    1. 2.1. UI相关
      1. 2.1.1. scrollView.contentOffect莫名等于-64
      2. 2.1.2. 设置控制器backBarButtonItem或者leftBarButtonItem无效
      3. 2.1.3. 使用addObserver监听视图的frame无效果
      4. 2.1.4. TabBarController与NavigationController谁嵌套谁?
      5. 2.1.5. iOS8中CollectionView加载速度异常慢
      6. 2.1.6. 多个CollectionView出现EXC_BAD_ACCESS
      7. 2.1.7. CollectionView的Cell中添加按钮无法响应事件
      8. 2.1.8. 代码设置UIButton.titleLaebl.title无效果
      9. 2.1.9. 为Scrollview中设置上下左右约束后提示ambiguous
      10. 2.1.10. 如何让设置约束的视图们执行动画?
      11. 2.1.11. 在interface界面里找不到Cell视图的contentView属性
      12. 2.1.12. 有时候无法在导航栏上摆放BarButtonItem
      13. 2.1.13. 如何在interface界面里和代码里设置导航栏的样式
      14. 2.1.14. 如何用代码写视图的宽高约束
      15. 2.1.15. 继承UIImageView的子类,drawRect:方法不被调用
      16. 2.1.16. 自定义toolBar上的UIBarButtonItem
      17. 2.1.17. 如何让重写的视图子类也支持直接在Xib,Storyboard中填写参数预览显示效果
      18. 2.1.18. 如何优雅地往TableView上添加无网络图片标记或者加载指示器
      19. 2.1.19. 如何去除TableView中多余的分割线
      20. 2.1.20. 让一个模态视图透明部分显示成上一个界面
      21. 2.1.21. 多用百分比实现自动布局
      22. 2.1.22. SearchBar底部有一条黑边
      23. 2.1.23. 定制SearchBar取消按钮颜色,输入框光标颜色
    2. 2.2. 数据相关
      1. 2.2.1. 系统自带的字典与JSON互转
      2. 2.2.2. 对象属性中有NSTimer对象,导致对象无法被释放的可能原因
      3. 2.2.3. 为什么NSDate显示的日期和设置的日期不同?
      4. 2.2.4. 使用信号量进行异步操作同步等待
      5. 2.2.5. 使用MJextension将字典转成json字符串需要注意的地方
      6. 2.2.6. CoreData报错:The model used to open the store is incompatible with the one used to create the store
      7. 2.2.7. 读取用户通讯录与审核问题
      8. 2.2.8. 如何读取本地json文件