图片缩放解决的图片位置跑偏的问题_東東
图片变形的抗锯齿处理方法
iOS 9系统策略更新,使用微信SDK的开发者注意升级
解决点击状态栏时ScrollView自动滚动到初始位置失效办法
iOS 警告收录及科学快速的消除方法
1. GHUnit 安装编译报错:
情况描述: 在iPhone 5及以下机型正常,其它的iPhone机型在模拟器或真机报如下这种architecture 某种型号 找不到的error.
异常原因: GHUnit 只支持armv7 的架构.
解决方案: 修改集成GHUnit的Target的Architectures默认设置(紫色框).
Xcode 的TARGET的Architectures默认设置:
修改后(集成GHUnit的Target)可在所有iPhone机型上正常运行的设置:
2. 使用UIApplication 的statusBarHidden设置状态栏无法隐藏:
[[UIApplication sharedApplication] setStatusBarHidden:_isHiddenStatus];
问题原因: 默认情况下, Apple不希望界面的状态栏经常变更,因为涉及到view 的高度及坐标跟随变更,其建议的设置是使用ViewController 的prefersStatusBarHidden进行设置,这种设置下是一次性的,对应的界面无法再次更改statusBarHidden的设置,而使用UIApplication 的setStatusBarHidden也无法起作用。
解决方法: 关闭ViewController对状态栏的是否显示设置的控制.就可使用UIApplication的setStatusBarHidden方法进行任性的设置了。
至于更改后报如下错误:
注: 此BUG,苹果官方说可以忽略这个警告。详情请查看这个链接:https://forums.developer.apple.com/thread/13683
3. 无法调用id objc_msgSend(id self, SEL op, ...) 函数:
例: objc_msgSend(self, @selector(test:), @"test");
提示error:Too many arguments to function call, expected 0, have 3
修改Target的Build Settings如下:
将默认的YES 改成NO即可.
4. 当App支持多个方向时,手机的方向旋转后状态栏消失
问题原因: 在手机旋转后状态栏被隐藏了。
解决方案:将状态栏设置为不隐藏,有2种方式,如问题2 所述:
#1. 在info.plist默认设置下(info.plist文件的View controller-based status bar appearance 属性默认设置下是没有的,系统默认该值是YES, ) 或设置View controller-based status bar appearance 为 YES 情况下,在需要旋转操作的ViewController里增加如下代码:
#2. 使用UIApplication 设置状态栏不隐藏,需info.plist增加View controller-based status bar appearance 属性,并设置该值为NO,再添加通知观察设备方向是否旋转,旋转则在触发的方法里设置状态栏不隐藏,如下代码:
5. 使用storyboard 或xib 创建的scrollView无法滑动显示其中的子视图
7. UICollectionViewCell 使用Storyboard时,cell 不会进 - (instancetype)initWithFrame:(CGRect)frame 来创建,可重写- (instancetype)initWithCoder:(NSCoder *)aDecoder 或- (void)awakeFromNib 来对cell 进行其它操作,cell 的大小布局是通过 UICollectionViewFlowLayout 来定义的,如果在- (instancetype)initWithCoder:(NSCoder *)aDecoder 或- (void)awakeFromNib这里对cell 的frame进行重写,但布局时仍会不起作用。只能通过UICollectionViewFlowLayout 来定义。
8. 使用Storyboard/ XIB ,在ScrollView中布局子视图时注意:
1. Label设置字体颜色不要用attributed 属性进行设置,会导致进入该节目缓慢3s以上。
2. TextView在布局时,想像TextField输入placeholder 内容会导致进入界面缓慢3s以上。(不输入的话,单纯的添加textView会让安装程序后初次进入界面缓慢1s左右,后续再次进入该界面就不会)
9. 需要在后台长久运行程序实现:
方式一:
// AppDelegate.h文件
@property (nonatomic, assign) UIBackgroundTaskIdentifier backgroundUpdateTask;
// AppDelegate.m 文件
- (void)applicationDidEnterBackground:(UIApplication *)application {
[self beingBackgroundUpdateTask];
// 在这里加上需要长久运行的代码
[self endBackgroundUpdateTask];
}
- (void)beingBackgroundUpdateTask {
self.backgroundUpdateTask = [[UIApplication shareApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];}];
}
- (void)endBackgroundUpdateTask {
[[UIApplication shareApplication] endBackgroundTask:self.backgroundUpdateTask];
self.backgroundUpdateTask = UIBackgroundTaskInvalid;
}
方式二:
- (void)applicationDidEnterBackground:(UIApplication *)application {
// 开启后台任务,让程序保持运行状态
[application beginBackgroundTaskWithExpirationHandler:nil];
}
然后在plist 文件里添加required background modes ,在更加后台运行的类型选择模式。
10. 使用xib 或Storyboard布局的UIScrollView 控件,系统会根据布局设置它的contentsize, 但要取得它初始化后的contentsize,需在viewWillAppear之后的viewDidAppear(updateViewConstraints也可以,其是在viewWillAppear之后viewDidAppear之前) 及之后才可以取到(viewDidLoad或viewWillAppear内取得contentsize是零) .
11. 点击一个ScrollView中的UITableView中cell的,期望被选中的cell根据选中的状态做出Action.但正常点击cell,cell无反应,需选中cell并保持一段时间,cell 才对选中动作做反馈。造成此类情况,scrollView有点击手势动作,将UITableView的点击动作给拦截了。
12. 使用IB 时,有时UITextView需根据输入的内容调整它以及它的父视图的大小。使用
13. 导航器下的转场动画,系统默认时滑动屏幕左边缘返回上一级界面,若出现以下情况则无法滑动返回上一级:
1)导航栏UINavigationBar 隐藏了,系统默认的左划返回上一级无效。
2)自定义了导航栏的上一级界面的转场动画,在下一级界面无法使用系统默认的左划返回上一级界面,如 A 界面 Push B界面,使用了自定义转场动画,这时 B 使用系统的左边缘手势返回A无反应。若B想使用系统的左边缘滑动返回则需 :
self.navigationController.delegate = self; // 这样就又可以使用系统左边缘滑动返回了,不过正常的方式该控制器需遵循 UINavigationControllerDelegate,这样就不会提示该类没遵循协议了。
14. 控制器的转场动画,A present B 的跳转方法里必须设置B.transitioningDelegate = A,否则 A present B 的转场动画无效。若A 为导航控制器的rootViewController,但是A 又自定义了控制器的转场动画(present/dismass),需注意转场动画里通过viewControllerForKey的对应key本应为A的控制器会变成是UINavigationController,这时需要A = navi.viewControllers[0] 再获取A,然后才能对A进行相关的动画设置及其它A的操作,否则的话程序会由于navigationController不识别A的相关属性/方法而蹦。
15. dispatch_group_async 结合 dispatch_group_notify 的作用同 dispatch_barrier_async的区别 ?
dispatch_group_notify 的效果是前面的dispatch_group_async 中block的代码执行完再执行它block中的代码,但注意这里是指执行代码,而block 中的操作如有异步请求返回的话,如在block中有异步的网络请求,则不能保证在请求返回结果后再执行notify中的操作。即只保证代码的执行顺序。
16. 关于view的初始化或布局显示的API 调用顺序
16.1 在InterfaceBuilder 使用自定义的View 控件时,添加UIView控件,并将view的控件类名改为自定义的类名, 但这样做创建的视图是没有根据代码中自定义进行生成视图的,而是一个空白view,可通过重写awakeFromNib或layoutSubviews,增加自定义View的设置。此过程需注意:
1)awakeFromNib: 1.1 该方法下的frame为IB中的frame,并非是根据不同手机自适应后显示的大小,如storyboard下主view的宽高:600,600 ,所以在设置控件时没注意的话,常常会出现看不到。若要区当前手机屏幕大小可通过[UIScreen mainScreen].bounds.size。
2)layoutSubviews:2.1 重写该方法,增加自定义视图设置时,不会出现awakeFromNib中的视图的frame是IB的状况。2.2 awakeFromNib: 中设置的自定义View为初始化对象后就会默认执行。而在layoutSubviews中设置的自定义view,可通过layoutIfNeeded 或 setNeedsLayout 进行手动触发调用layoutSubviews设置自定义View .需注意在控制器的viewWillAppear后系统会让各子视图调用layoutSubviews,需避免多次调用layoutSubviews而多次创建及由于对象创建和被调用的顺序不同而设置无效(多次调用的原因有多种,如使用IB勾选了AutoLayout,就会导致在生成view时到显示调用2次)。如:
如下所示的JumpStarView自定义View(使用IB创建),其在layoutSubViews中定义了该自定义view.在控制器使用layoutIfNeeded触发layoutSubviews再进行其属性设置。
自定义View:在ViewController中调用该种自定义的view时,其初始化过程:从IB创建的自定义View,其使用initWithCoder:初始化,并在awakeFromNib之前完成IB中与此View关的IBOutlet和IBAction的等链接;ViewController会在viewWillAppear后让其子view都调用updateConstraints然后再调用ViewController的updateConstraints,约束更新后,各子view再layoutSubViews->drawRect ,最后控制器viewDidAppear.即在控制器的viewWillAppear和ViewDidAppear之间会对其各子view的约束更新->布局->绘图,画图完成后再调ViewDidAppear.
awakeFromNib 和 layoutSubviews的使用特点(自定义View方面):awakeFromNib设置的view在创建后就实现,无法手动控制设置,且在该方法内获取的frame为IB中设置的。好处是awakeFromNib设置的view可不用担心多次被调用创建,其设置的属性一般也可正常显示。而 layoutSubviews 提供了手动控制触发自定义view的设置,但需注意被创建和调用的顺序及避免多次创建,还有就是该API中获取的frame为layout之后的所以是即将显示的frame。
16.2 - (void)awakeFromNib 使用该函数从storyboard 文件 生成的 view, 其view的frame初始为storyboard中控件的frame, 若使用SizeClasses,则view 的frame 为在storyboard中的大小,而非最终auto layout后的结果。
16.3 layoutIfNeeded 和 setNeedsLayout:
layoutIfNeeded 会立即调用updateConstraints再调用layoutSubviews,而setNeedsLayout则会取消当前的layout并触发layout在下一次更新中更新。即layoutIfNeeded可立即实现修改后的布局效果,而setNeedsLayout更多的用于优化统一layout更新。
17. 计时器的使用,常会使用到 NSTimer、CADisplayLink、dispatch_source timer, 其中NSTimer 和 CADisplayLink 的默认NSRunLoop会在界面滚蛋时,计时器会停止计时,dispatch_source timer不会,解决NSTimer 和 CADisplayLink问题:
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
18. 父视图Window上有个Tap手势并捆绑个selector,window下的子视图进行点击操作时,其window的手势也会跟着响应,如何阻断不需要的手势响应 ?
19. TableView的cell 默认点击有选中效果的阴影颜色,不需要可通过cell.selectionStyle = UITableViewCellSelectionStyleNone; 进行设置。
20.Cornerstone 无法打开项目,报如下错:
提示 xx.xcodeproj 文件无法解析,打开不了。
解决方法:右击 xx.xcodeproj 查看包内容,可见:
project.pbxproj 文件冲突,如果自己有需要的修改需要保留的话,则需要点击project.pbxproj打开,删除那些<<<< ===== >>>> 这些标示,一般简单粗暴点直接将上面这些框里的文件全删除,然后再同步SVN(确认服务器上是能正常使用的)。
22. 使用StoryBoard拖MKMapView 控件,创建在实例化时会崩,手动代码添加则不会。
23. UICollectionView 的创建若直接使用 initWithFrame会蹦,必须使用initWithFrame:collectionViewLayout 进行实例化,如下:
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
UICollectionView *collectionView= [[UICollectionView alloc] initWithFrame:CGRectMake(0, 30, kFullScreenWidth, 0) collectionViewLayout:layout];
collectionView的layout可直接设置也可通过UICollectionViewDelegateFlowLayout的代理方法中设置。
24. UITableView 若实现了Section索引的代理方法的话,那么其索引的数据源不能为空,
NSMutableArray *sectionKeyMArr = [NSMutableArray arrayWithObject:@""]; // 起码有一个空元素,否则TableView的索引代理方法会蹦.
25. 母View有捆绑手势,其子view若有同类型的手势,则点击到子view执行子view的手势触发的action,若子view无同类的手势,不管子view的userInteractionEnabled是YES或NO,操作会一直往下传递,直到有该类型的手势View终止或都没有而无反应。注:View的上下层也会出现这种情况.这种一个位置有重叠的View的话,并且需要不同状况下显示不同的view.如果这些view是没有相同手势操作的,可简单通过设置view的level层来实现,若view中有操作,那么还是实用hidden来实现可避免不同的view的相同手势操作混淆。
26. iOS 7 在StoryBoard的界面跳转若使用新的跳转kind(如show)将会出现导航栏隐藏。而iOS 7以上的使用旧的push跳转连线则正常,所以Storyboard界面跳转还是使用旧的跳转连线。
27. 创建UITableViewCell时,cell的setSelected方法会调用其super的setSelected:方法,其super的setSelected:会调用setSelected:animated:方法,也就是说创建cell时默认selected方法会调用setSelected:animated方法。而点击UITableView的cell时会调用:setSelected:animated -->
tableView:didDeselectRowAtIndexPath -->setSelected:animated-->didSelectRowAtIndexPath 方法,即先将之前的cell设置不选中,再设置新cell选中,都是每次先调用UITableViewCell的setSelected:animated方法再调动tableView的代理方法。
如需要让UITableView在创建第一次显示时,默认显示一个指定的Cell为选中状态。但是UITableView首次生成时会将每个cell 的selected都默认设成未选中。其在tableView:cellForRowAtIndexPath设置cell.selected 是无用的,系统会再次默认设成NO;
28. 控制器A的其中一childViewController 为B,在B 使用self.navigationController push 到控制器C.那么navigationController的viewControllers应该是[A,C],即C控制器pop出来是到A控制器。而显示是显示A控制器的B子控制器。
29. 第三方登录使用友盟提供的接口返回的数据作为用户标示的有usid和openId,其中qq和微信都有返回的usid和openId且usid和openId相等,新浪微博只有usid返回。
30. for循环的快速枚举修改元素值问题,例如:检查字典dic里的每个value,若value为null则需将其改为@“”,实现:
快速枚举:
for (__strong id value in dic.allValues){ // 系统警告提示,value是__strong的,快速枚举才可以修改。
if ([value isKindOfClass:[NSNULL class]]){
value = @""; // 但重新打印dic,结果是value还是null对象
}
}
一般遍历:
for (int i=0; i < dic.allValues.count; i++){
if ([[cityDic valueForKey:cityDic.allKeys[i]] isKindOfClass:[NSNull class]]){
[cityDic setValue:@"" forKey:cityDic.allKeys[i]]; //注:另NSDictionary由于是不可变的,使用KVC无效程序会蹦,NSMutableDictionary可以。
}
}
31.在xib下自定义View的tableView控件无法添加tableViewCell控件,collectionView同样,但在Storyboard支持.
32.xib设置的或代码自定义的cell (UITableViewCell,UICollectionViewCell)如何在tableView实现复用?cell要复用的前提,首先得能实例化创建cell,然后给这类cell的实例打上复用id,然后复用这些实例cell,不必每次都新实例化cell.所以先注册nib或cell的class,然后就可通过tableview的dequeue方法进行复用。
33. TableView的tableHeaderView的frame改变时,需要重赋值tableView.tableHeaderView = view。否则tableview的内容不会上移/下移做对应的改变。
34.使用Masonry 时,先得将需约束的view加入其父view,
35.设置导航栏透明,其下方的view不被遮挡.当控制器的automaticallyAdjustsScrollViewInsets不起效果时,使用setEdgesForExtendedLayout为UIRectEdgeTop,代码如下:
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]){
[self setEdgesForExtendedLayout:UIRectEdgeTop];
}
36.实现导航栏透明如下,另需要注意在切换控制器时由于导航栏透明,会出现别的控制器需显示的导航栏从右往左推时,还会看到之前界面的导航栏部分(之前是透明的),所以在viewWillAppear和viewWillDisappear内控制导航栏的显示和透明。
[self.navigationController.navigationBar addSubview:self.naviBarView]; // 将需要在导航栏中显示的加入透明的导航栏内
[self.navigationController.navigationBar setBackgroundImage:UIImage.new forBarMetrics:UIBarMetricsDefault]; // 设置透明
[self.navigationController.navigationBar setShadowImage:UIImage.new];
40.UITableView的dequeueReusableCellWithIdentifier:方法获取的cell为系统默认的cell,方法dequeueReusableCellWithIdentifier:forIndexPath:获取自定义cell,该方法使用前得注册自定义cell类或nib,若自定义cell使用dequeueReusableCellWithIdentifier:方法获取到的cell,其设置会为系统默认。dequeueReusableCellWithIdentifier:forIndexPath方法会走cell的initWithFrame:还是?
41.UIScrollView 滑动,需在最后确定是否满足条件触发行为,不可使用scrollViewDidScroll:代理进行判断,该方法是每次滑动代理,并不是最终滑动将会停止的代理,如果使用这个将会在滑动的过程中频繁触发判断,使用scrollViewDidEndDragging:willDecelerate可满足在滑动结束时进行触发判断的要求。
42. 在使用NSKeyedArchiver和NSKeyedUnarchiver时,碰到model归档时数据有保存本地NSUserDefaults,从NSUserDefaults也能获取到data,但对data进行解档unarchiveObjectWithData却解析不了出原model.即unarchiveObjectWithData返回nil.出现此异常不是全部机型,只在部分机型出现,怀疑同机型硬件有关?暂时解决方法 是对解档出的model进行非空判断,若nil则手动model = [Model alloc] init]进行实例,数据丢了没办法了。
43. dispatch_once 单例方法在实例对象没返回前又去获取该单例方法会导致单例方法不可访问可崩。实例:用户数据单例在启动app时解档获取数据model,但出现异常解档出nil时这时用户数据model就得new,并让操作和数据保持一致性,需发通知出去做清除数据操作。但由于通知的接受对象里又有调用该单例方法,所以就会出现单例对象还没返回来,但通知方法里又去调用该单例而导致app崩:
44. Xcode 8.0之后默认新项目只支持iOS8.0之上版本,若建立的项目希望也支持iOS7,怎么处理?
直接在TARGETS的General里的Deployment info手动输入Deployment Target 的值为7.0即可,如图:
45.KVO使用时有哪些坑?
1. 注销KVO坑:
情况一:在dealloc方法里进行removeObserver,父类执行了删除,而子类也有其共同的keypath观察,就会出现重复删除而崩溃。
情况二:本类里无注册Observer或已删除Observer后又执行removeObserver,而出现崩溃;
解决措施: 1. 添加context,区别于子类、父类的观察; 2.通过Bool变量控制本类的观察删除。
2. 父类和子类都有实现KVO,子类中断父类的观察:
情况一:有共同的keyPath,无法区分子类和父类的观察即使有写super observeValueForKeyPath...方法也是被子类截断了父类的super方法调用,增加context区分判断子类父类的观察。
情况二:有context,但无else的父类调用observeValueForKeyPath...方法,父类的观察方法不会被调用(通常先走子类的观察,然后在走父类的观察),增加else的super调用observeValueForKeyPath...方法即可。
所以写KVO时要加context,控制是否添加KVO的变量,和observeValueForKeyPath...方法里添加else的super调用observeValueForKeyPath...方法。
46. 在TableView或CollectionView的点击选中添加动画时,常会遇到动画过程中不可再点击其他cell,如点击cell的动作是跳转控制器的话则可能在由于动画过程中的多次点击而一下多次跳转。这里通常会首先想到在...didSelectItemAtIndexPath...方法里先allowsSelection设为NO,再在动画完成后的回调里把它设为YES.如果这个动画获取SelectedItems不是自己创建的全局变量保存的话而是用indexPathsForSelectedItems方法来获取的,那么TableView或CollectionView会由于allowsSelection为NO而返回SelectedItem为nil,所以这会由于allowsSelection为NO而获取不到当前所选中的cell,点击全部cell都是同一个处理结果,解决措施:
方法一.使用allowsSelection来控制点击,通过变量保存选中的indexPath
方法二.使用userInteractionEnabled来控制整个列表的交互(注意不要影响到除了cell的其它交互,有就不要了).使用indexPathsForSelectedItems来获取选中的indexPath
47. 在NSJSONSerialization解析数据中有浮点类型的数据时会出现解析不准确,解析出来后会跟上多余的小数位,比如 double 87.74会被解析成87.7399999999999,让后台将这种类型数据改为string就可以。
48. App 的LaunchScreen图片更换时,若图片名不改只是换个图,启动时会发现仍是显示旧图,可能是App第一次安装后启动图被系统缓存,若不删除重装的话而是同名更新则会出现这种情况,解决措施是新图片新图片名这样就不会让系统搞错了。
49. 常见崩溃debug: 1. block 循环引用; 2. delegate属性strong形成循环引用;3. NSArray数组越界;3. NSAttributeString 实例化时的string为nil; 4.NSDictionary里的key、value为nil; 5. 访问野指针;6. 多线程; 7. 加载的文件、图片不存在;8.block为nil是被调用;
50. Xcode几个比较常用的debug命令: po、print、bt、clear、list、continue、next、info break、info local、 info var、kill、set;
51. bug日志解析:1. 查看dSYM的UUID是否和日志的一样; 2.解析日志;