随笔集
Day 2016-6-26
@property 完成的事情:自动生成并且实现setter 和getter 方法,创建_属性,如果重写了setter 和getter方法,那么就不会自动创建_属性。 如果加上readonly修饰符,那么系统只会帮你创建getter方法和_属性,如果再重写getter方法,那么系统也不会自动创建_属性,只能自己手动加上_属性。即使说使用了readonly,虽然不能直接使用setter,但是还是可以使用kvc进行赋值setvalue forKeyPath
设置状态栏样式,如果控制器属于导航控制器,那么只能到导航控制器中实现prefer..style方法,在改控制器中实现无效。
Day 2016-8-18
控制器返回的时候恢复导航控制器的样式,在viewwilldisappear方法中去写,在viewdidload方法中写无效
如果push的view背景色是透明的,那么导航控制器从上一个控制器的view 切换到这一个控制器的view时候,颜色重叠,会有一种卡顿的错觉,解决方法,给这一控制器的view设置背景色(实际就是那样的,卡顿只是错觉)。
Day 2016-9-3
autolayout 适配技术下,在viewdidload中,self.view 的frame 已经是当前手机屏幕的大小,但是没有autolayoutSubVews,所以子控件大frame还是storyboard上的状态.。 而且由于view的加载周期是先viewdidload -->......-->layoutsubViews ,所以在viewdidload 修改子控件的frame 是没有作用的,修改约束是有效果的
通过代码创建viewcontroller,view controller.view.frame是手机的屏幕大小
dispatch_async(dispatch_get_main_queue(), ^{
[_scrollview setContentOffset:CGPointMake((CGFloat)page * _pageWidth, 0) animated:YES];
}); 由于设置偏移量动画,所以当后面需要使用scrollView的时候,scrollview 的偏移量可能还没有修改过来,所以把设置放到追队列里面,这样后面使用scrollview的操作(只限在主线程执行这个UI操作)都要在设置偏移量完成之后才能执行,scrollview的偏移量已经修改
Day 2016-9-6:
如果uitablevlewcell 的控制大小不是想用的效果,滑动之后又正常了,应该是受到xib auto resizing的影响,设置auto resizing为none
timer (CADisplayLink) 直接置为nil, 事件是不会停止的,置为nil之前必须要invalidate。
Day 2016-9-8:
gitIgnore的作用:每次提交不会将个人的项目设置信息(末次打开的文件,调试断点等)提交到服务器
iOS 7之前会对图片进行渲染,如果要保持图片原样,就要设置origional,但是iOS7之后不用了
iOS7 之前设置tin color 对图片无效,只对蚊子有效。bartincolor 背景色
tine color 选中图片和文字的颜色
iOS 7之后就不鼓励在viewdidload方法中设置frame ,在viewwillappear设置
cell子控件加约束的时候,不能都没有高度约束,(eg:imageView + label)
Day 2016-9-18
自定义专场动画时候不能在转场类进行延时操作,否则编译失败,"commmad failed due to signal :segmentation fault :11"
dispatch_after(3, dispatch_get_main_queue(), {
print(containerView.subViews.count)
})
Day 2016-9-29
Zing Zbar 等二维码操作三方库不能使用在项目中,这两个三方库只支持32位,不支持64位,而苹果苹果要求必须支持64位,所以可能上传不了appstore
Day 2016-10-8
// 这个问题iOS7就出现了,只要scrollView是其父视图上的第一个子视图,且navigationBar不隐藏的情况下,添加到scrollView里的视图,都会默认下移64个像素。 导致scrollview里面的内容向下偏移了64 添加此方法 从导航栏下开始计算
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
Day 2016-10-10
UISrollView (包含tableView,集合试图)都有一个UIScrollViewPanGestureRecognizer,如果要给它们加上pan手势,方法名不能是handlePan,因为内置UIScrollViewPanGestureRecognize手势的响应事件也是handlePan ,如果重写了这个方法,那么scrollView将不能滚动
Day 2015-10-17
首先就是关于pod的那部分内容需要纳入git管理, pod文件需要纳入git管理的只需要两个文件, Podfile和Podfile.lock.,其余文件忽略。使用git的时候,如果勾选添加gitIgnore文件,那么gitIgnore文件默认是忽略掉pod的所以pod管理的三方库是不受git版本控制的,如果项目中使用的三方库过多,建议忽略掉pod,防止服务器资源过多,备份项目消耗时间资源过多,每次checkout的时候update一下pod就行,如果项目中使用的三方库不多,建议不要忽略pod,同时也要update pod,修改.gitIgnore文件后要重启xcode,这样就不用每次checkout需要update pod 。 修改完.ignore文件或者在xcodeupdate pod 时候,都最好重启一下xcode,否则可能没效果 cocopods 和 git 共用问题
登录:成功之后,服务器返回用户对应的加密token,本地只保存token,不保存帐号和密码
xocde 8不支持pch,也不鼓励使用pct
Day 2016-16-10-10
在Xcode8通过sb 添加子控件,并且在sb上设置约束,则在viewdidload中打印子控件的frame,vc.View 的frame是手机屏幕的大小, 而所有子控件的frame是(0,0,1000,1000)
而在Xcode8以下中,在viewdidload中显示的frame是在sb中子控件的frame(未必是最终显示的frame,因为还没有经过layoutsubviews)
Day2016-11-15
tableview(uiscrollview?) 导航条下的自动偏移64复现:作为self.view的第一个subView就回出现这种情况,如果不是第一个subView,那么不会出现这种情况
Day2016-11-16
layoutSubviews在以下情况下会被调用:
1、init初始化不会触发layoutSubviews
2、addSubview会触发layoutSubviews
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化
4、滚动一个UIScrollView会触发layoutSubviews
5、旋转Screen会触发父UIView上的layoutSubviews事件
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件
=============
创建view 的时候,无论调用initWithFrame, 还是init ,走的都是都是initWithFrame,不传frame参数,全部是0而已。然后在setFrame(该类重写这个方法的话,走这个类的,否则走父类的)
Day 2016-11-30
编译bug01
编译bug02
Day 2016-12- 6
1. 创建view的时候,构造函数中传入frame,并且调用super.init(frame) ,这句代码执行过之后,frame 并没有立刻设置上
2.cellForRow --> canEdit --> actions 这是tableview的代理方法三个方法执行的属性,但是在canEdit的时候,通过indexPath访问cell 是nil
day2016-12-12
在view类里面重写layoutsubViews,修改子view的frame,会引起死循环?????
通过纯代码设置集合试图的header,不加layout.headerReferenceSize = CGSize(width: width, height: 30) 返回header的代理方法不会执行
view的frame的改变会触发drawRect, 如果在创建的时候没有传参frame,drawRect不会执行
Day 2017-01-16
view.bounds x 并不会一直等于0 ,eg SpActionEditViewController.spModeSCrollView
(复现:viewDidLoad中添加testView1,在layoutsubView中设置testView1 的frame = scrollView的bounds, touch begin事件中添加testView2,并且设置testView的frame, scrollView的contentOffset.x,此时打印scrollView的bounds.x 不等于0,)
scrollview的Bounds的x, y = 其偏移量
Day 2017-01-18
通过xib或者sb加载一个view的时候,required init?(coder aDecoder: NSCoder) ,view下的subView并没有创建,nil, awakefromNib ,view的subView创建成功
但是sb加载自身的子控件的时候,好像也是nil , 需要再次验证
Day 2017-01-23
有一些view可以不设置大小约束,只需要设置位置约束,如UIButton,UILabel, 以UILabel为例,如果不设置他的宽度高度约束,那么他的宽度高度会随着本文的内容改变而改变,会触发父view的layoutSubviews方法,那么这个Label就会自动回到约束的位置,如果想要在代码里面改他的位置,并且不会自动改变,那么设置他的宽度(高度根据情况)或者代码修改位置约束,
Day 2017-2-7
ios7之后,推出[viewcontroller prefersStatusBarHidden] 和[viewcontroller preferredStatusBarStyle] 来控制每个页面状态栏的显示隐藏样式,iOS9之后废弃了application.setStatusBarHidden(true, with: .fade),
如果要控制的控制器没有在UINavigationController下,那么可以直接在需要的控制器中直接重写[viewcontroller prefersStatusBarHidden] 和[viewcontroller preferredStatusBarStyle],
如果要控制器的控制器在UINavigationController下,需要在导航控制中重写[viewcontroller prefersStatusBarHidden] 和[viewcontroller preferredStatusBarStyle]
override var prefersStatusBarHidden: Bool {
return topViewController!.prefersStatusBarHidden
// if topViewController!.isKind(of: NSClassFromString("状态栏.需要单独控制的页面类名")!) {
// return true
// }
// return false
}
override var preferredStatusBarStyle: UIStatusBarStyle {
// return topViewController!.preferredStatusBarStyle
if topViewController!.isKind(of: NSClassFromString("状态栏.需要单独控制的页面类名")!) {
return .lightContent
}
return .default
}
Day2017-2-8
尽量避免将UIVisualEffectView对象的alpha值设置为小于1.0的值,因为创建半透明的视图会导致系统在离屏渲染时去对UIVisualEffectView对象及所有的相关的子视图做混合操作。这不但消耗CPU/GPU,也可能会导致许多效果显示不正确或者根本不显示。
Day2017-2-22
查看代码行数
find . "(" -name "*.m" -or -name "*.mm" -or -name "*.cpp" -or -name "*.h" -or -name "*.rss" -or -name "*.xib" ")" -print | xargs wc -l
collectionView莫宁奇妙自动偏移,collection view.layoutifnneed
iOS10 之前和之后 collectionview的区别
9.UICollectionViewCell的的优化
在iOS 10 之前,UICollectionView上面如果有大量cell,当用户活动很快的时候,整个UICollectionView的卡顿会很明显,为什么会造成这样的问题,这里涉及到了iOS 系统的重用机制,当cell准备加载进屏幕的时候,整个cell都已经加载完成,等待在屏幕外面了,也就是整整一行cell都已经加载完毕,这就是造成卡顿的主要原因,专业术语叫做:掉帧.
要想让用户感觉不到卡顿,我们的app必须帧率达到60帧/秒,也就是说每帧16毫秒要刷新一次.
iOS 10 之前UICollectionViewCell的生命周期是这样的:
1.用户滑动屏幕,屏幕外有一个cell准备加载进来,把cell从reusr队列拿出来,然后调用prepareForReuse方法,在这个方法里面,可以重置cell的状态,加载新的数据;
2.继续滑动,就会调用cellForItemAtIndexPath方法,在这个方法里面给cell赋值模型,然后返回给系统;
3.当cell马上进去屏幕的时候,就会调用willDisplayCell方法,在这个方法里面我们还可以修改cell,为进入屏幕做最后的准备工作;
4.执行完willDisplayCell方法后,cell就进去屏幕了.当cell完全离开屏幕以后,会调用didEndDisplayingCell方法.
iOS 10 UICollectionViewCell的生命周期是这样的:
1.用户滑动屏幕,屏幕外有一个cell准备加载进来,把cell从reusr队列拿出来,然后调用prepareForReuse方法,在这里当cell还没有进去屏幕的时候,就已经提前调用这个方法了,对比之前的区别是之前是cell的上边缘马上进去屏幕的时候就会调用该方法,而iOS 10 提前到cell还在屏幕外面的时候就调用;
2.在cellForItemAtIndexPath中创建cell,填充数据,刷新状态等操作,相比于之前也提前了;
3.用户继续滑动的话,当cell马上就需要显示的时候我们再调用willDisplayCell方法,原则就是:何时需要显示,何时再去调用willDisplayCell方法;
4.当cell完全离开屏幕以后,会调用didEndDisplayingCell方法,跟之前一样,cell会进入重用队列.
在iOS 10 之前,cell只能从重用队列里面取出,再走一遍生命周期,并调用cellForItemAtIndexPath创建或者生成一个cell.
在iOS 10 中,系统会cell保存一段时间,也就是说当用户把cell滑出屏幕以后,如果又滑动回来,cell不用再走一遍生命周期了,只需要调用willDisplayCell方法就可以重新出现在屏幕中了.
iOS 10 中,系统是一个一个加载cell的,二以前是一行一行加载的,这样就可以提升很多性能;
iOS 10 新增加的Pre-Fetching预加载
这个是为了降低UICollectionViewCell在加载的时候所花费的时间,在 iOS 10 中,除了数据源协议和代理协议外,新增加了一个UICollectionViewDataSourcePrefetching协议,这个协议里面定义了两个方法:
- (void)collectionView:(UICollectionView *)collectionView prefetchItemsAtIndexPaths:(NSArray *)indexPaths NS_AVAILABLE_IOS(10_0);
- (void)collectionView:(UICollectionView *)collectionView cancelPrefetchingForItemsAtIndexPaths:(NSArray *)indexPaths NS_AVAILABLE_IOS(10_0);
在ColletionView prefetchItemsAt indexPaths这个方法是异步预加载数据的,当中的indexPaths数组是有序的,就是item接收数据的顺序;
CollectionView cancelPrefetcingForItemsAt indexPaths这个方法是可选的,可以用来处理在滑动中取消或者降低提前加载数据的优先级.
注意:这个协议并不能代替之前读取数据的方法,仅仅是辅助加载数据.
Pre-Fetching预加载对UITableViewCell同样适用.
Day2017-2-24
无论在任何情况下,改变约束都要调用layoutifneed ,确保frame 正确及时改过来
通过navigationBar.isTranslucent = fasle 设置导航条的颜色,会使导航条设置图片的两个方法失效,解决办法 设置navigationBar.isTranslucent = true
Day2017-3-2
warning: attempt .. view controller which's view is not ... 原因是: 这个这个控制器A的view还没有出来,或者被新push、modal的控制器的view盖住了, 要让A的view影响一些就会报这个错误,解决方法
视情况而定: 1. 放到viewdidappear执行(如果需求是进到这个A之后,需要立刻进行一些操作)
2. 出现情况A没有销毁,不是当前显示的控制器(有新push的或者modal的),又创建了一个B,B和A是同一个类的对象,本意是让B响应一些时间,但是A还没有销毁,只是没有显示出来,所以A响应了事件,但是A的view没有显示出来,所以报错了这个警告,导致不能出现正确的现象,解决方法:彻底干掉A,实在不行,换window
Day2017-3-10
instruments -> coreAnimation -> 检测fps
view.layer.corneradius = 5 ,view.cliptobounds // 降低了5个fps
透明度对fps的改变只有一两个fps(测试demo时cell, 如果直接将为0,影响很大,这个测试demo是集合视图)
给cell加上blurView ,fps直接降到20左右
圆角性能离屏渲染// 关于圆角性能,注意:关于执行缓存的layer,应该是父layer,用被切圆角的layer执行缓存代码,fps反而降了二十多
setShadowImage 要和setbackgroundImage 一起使用,否则无效
Day2017-4-19
更新tableview的时候,最好全部更新,局部更新会crash,而且数据表明全部更新更高校,节省资源
Day2017-4-24
timer 会对target有一个强引用,以控制器为例,如果在pop或者dismiss之前没有干掉这个timer,则这个控制器不能被释放
在开发账号后台创建bundle id 提示 “An App ID with Identifier 'com.myqubic.qubic' is not available. Please enter a different string” 多半是xcode free 账号调试自动创建了这个bundle id, 只能换一个新的
Day2017-5-9
// 复用池中没有可用的header, 所以一下代码会创建新的header,并不是正在显示的headr,并且这个header没有添加到集合视图上,
// 复用池中没有可用的header, 所以一下代码会创建新的header,并不是正在显示的headr,并且这个header没有添加到集合视图上,
// 会出现问题: 比如tap 手势失灵
// let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader,
// withReuseIdentifier: "SceneInfoCollectionHeaderView",
// for: IndexPath(row: 0,
// section: 0)) as! SceneInfoCollectionHeaderView
// let header = self.collectionView(self.collectionView, viewForSupplementaryElementOfKind: UICollectionElementKindSectionHeader, at: IndexPath(row: 0, section: 0)) as! SceneInfoCollectionHeaderView