1、表格上滑则导航栏消失,下滑则导航栏出现,自带动画。
self.navigationController.hidesBarsOnSwipe = YES;
2、导航栏默认的模糊背景是因为系统自动设置了背景图片,下面代码可以清空背景图片,让导航栏变成透明状
[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
3、导航栏下方有一根像素为1的线,下面代码可以清空它
self.navigationController.navigationBar.shadowImage = [[UIImage alloc] init]
4、自定义窗口UIWindow视图,默认状态下其是隐藏状态,必须手动设置为不隐藏才能显示(主窗口的创建除外)
UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; window.hidden = NO;
5、iphone自带顶端下拉底部上拉状态消失后会发出应用程序进入活跃状态的通知UIApplicationDidBecomeActiveNotification
6、[NSDate date]方法获取的是系统当前时间,若用户手动修改系统时间,则该方法返回值会发生变化
7、定时器NSTimerCADisplayLink均会强引用target本身,若其为target属性时需要注意循环引用,设置为nil可打破循环
8、UIAlertController事件回调有延迟大概0.5s,若其附带输入框,则键盘会在事件回调执行结束后才收起,效果很差。只能自定义视图解决
9、表格视图cell高度缓存用NSCache,注意最好别用indexPath作为key,因为下拉刷新时必须自己将所有缓存清空,使缓存失效。上拉可不必
10、我所碰到过的内存泄露情况,即控制器不销毁
a、block循环引用
b、定时器对self的强引用
c、视图添加动画,同时写了scaleAnimation.delegate = self; scaleAnimation.removedOnCompletion = NO;
原因:动画代理对控制器强引用,而动画完成后又没有从图层树移除,循环引用。
加后面那句代码原因:在viewdidload方法中添加动画,若不写这句代码则动画不会执行,可以采用GCD延迟如0.1s再执行动画避免加这句代码。
也可加这句代码,但是当动画完成后移除动画图层。
11、视图的frame.size和bounds.size不同的情况:
a、视图transform有旋转或缩放时
b、图片在scrollView中缩放时
12、swift中addtarget多参数方法:
btn.addTarget(self, action: "function:parameter2:parameter3:", forControlEvents:.TouchDown)
func function(parameter1: Int, parameter2: Int, parameter3: String) {}
即函数名:第二个参数:第三个参数:,注意,按钮点击事件参数类型不能为上面所写的String,可以为NSString,Int,NSArray等其他类型,原因不明
13、打破block循环引用方式:
a、__weak弱引用。常用方式,缺点,由于不对外面对象进行强引用,block执行时该对象可能已经被释放
b、__blcok修饰变量,执行block后将其置nil。优点:强引用外部对象,保证其生命周期。缺点:必须执行block才能避免内存泄露
blk_k blk; { id arr = [NSMutableArray array]; __block id blockArr = arr; blk = ^(id obj){ [blockArr addObject:obj]; blockArr = nil; }; } blk([NSObject new]);
14、服务器返回字段有时会是<NULL>,对应OC中的NSNull对象,与nil不同,比如将其赋值给label.text会崩溃。
个人认为区别:null是一个NSNull类型的单例对象,有具体变化的类存地址,对其发送消息会崩溃。nil内存地址始终是0x0,发送消息不崩溃
15、一个UI对象用transform旋转180度时,总是顺时针旋转,无法通过设置-M_PI的方式让其逆时针旋转。采用下面方法可讲其顺时针->逆时针->顺时针依次旋转。原理:就近原则
static NSInteger flag = 1; flag *= -1; CGFloat angle = M_PI + 0.00001 * flag; [UIView animateWithDuration:2 animations:^{ self.redView.transform = CGAffineTransformRotate(self.redView.transform,angle); }];
16、Instruments
a、时间分析器Time Profiler:用来检测CPU的使用情况,查询某个方法消耗的CPU时间,找出CPU性能瓶颈
b、Core Animation :滑动时的FPS,颜色等
b1、Color Blended Layers:基于渲染程度对屏幕的混合区域进行绿到红色的高亮,由于混合色,对GPU性能有很大影响
b2、Color Offscreen-Rendered Yellow:离屏渲染黄色高亮,很可能需要用shadowPath或shouldRasterize优化
c、OpenGL ES驱动:GPU的利用率,性能瓶颈
c1、Renderer Utilization: 若大于50%,可能是离屏渲染或过度重绘,需要优化
c2、Tiler Utilization: 若大于50%,图层几何结构限制,如太多图层被占用
17、
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; if (url) {[[UIApplication sharedApplication] openURL:url]; }
上面代码会自动打开app关联的设置位置,比如你的app有消息推送,地图等,当用户关闭了访问权限时,这些功能则无法使用,可以在使用时弹出提示框提示用户打开权限,再调用该方法直接跳转到相应位置设置
18、图片解压:用 imageNamed:从 bundle 里加载不会立刻解压。而是在赋值给 UIImageView 的 image 或者 layer 的 contents 或者画到一个 core graphic context 里才会解压。对大图片必要时可采用后台draw方法解压,后再赋值的方式减轻解压时CPU压力,避免卡顿
19、JS和OC交互方式: 拦截协议、JavaScriptCore、三方框架WebViewJavaScriptBridge、WKWebView
20、项目优化点
a、内存: 1.图片读取方式(imageNamed:有内存缓存,imageWithContentFile没有内存缓存)、2.表格cell复用、3.自动释放池、4.dealloc打印查看控制器和视图是否销毁
b、用户体验:1.AFN和提示框组合封装,设置提示框延时出现时间,网络优良时不出现、2.push进界面,避免网络未返回时界面太难看,或者网络一返回界面出现向下移动等,采用蒙蔽优化、3.屏幕适配,防止输入框被键盘挡住、4.UIAlertController点击按钮系统反应会延迟约0.5s,无法解决,自定义视图解决
c、性能优化:1.大量IO操作如从沙盒读取大量图片考虑线程解决、2.大图片注意显示那一刻才会解压,耗费CPU,可以考虑后台cos2D解压,再设置、3.表格中有大量定时器时,定时器可以运行在后台线程,注意定时器复用,注意开启runloop、4.UIimageview尺寸最好跟图片大小一致,动态拉伸耗费性能、5.表格视图中cell上面,最好别设置动画、透明度、圆角、阴影等,可以用Instruments测试下FPS,若过低可以用上面的Instruments分析方法优化、7.尽量别重写drawRect方法,会引发离屏渲染,可以用UIBerzePath和CAShapeLayer画图、8.性能优化利器,缓存,缓存,缓存、9.避免频繁创建销毁视图,可以用懒加载,不需要时removeFromSuperView,需要时加上、10.避免无效网络请求,退出视图取消网络请求,同一个网络请求连续多次发送(如玩赚宝购买页面输入购买金额,实时网络请求计算收益)取消掉上一个网络请求,避免前一个网络请求返回延后使数据错乱
21 、我碰到过的AppStore被拒绝情况
a、app中设置了更新版本选项
b、开启后台定位模式,但app描述中没有添加这句话:“后台定位对电池有损耗。。。”
c、广告轮播图中有Applewatch字样
加急审核技巧:当没有严重bug时,可以说集成的支付功能未做加密等处理,需要马上更新。苹果比较重视安全,很可能会通过审核
22、sskeychain知识点:
在iOS中每个APP 都有属于自己的Keychain,最常用就是保存用户的账户和密码,就是记住密码,放在这里很安全(苹果负责帮我们加密再存起来,如果出了问题怪他咯!),假如用NSUserDefault 保存这些秘密数据,生成的plist文件(就放在那个Library/Preferences 下)容易被拿到,而且还要自己做加密。
特性:1.当app删除了,又再次重新安装,这个保险柜里的信息还存在
2.安全!作为小白的我并不知道它实际上是存在哪里的。
// 删除以前保存的所有账号和密码 ,参数service服务名(这个方便对账号密码进行分类)
NSArray *accounts = [SSKeychain accountsForService:kSSToolkitMyPswdServiceName];
for (NSDictionary *dictionary in accounts) {
NSString *account = [dictionary objectForKey:@"acct"];
[SSKeychain deletePasswordForService:kSSToolkitMyPswdServiceName account:account];
}
23、ios7系统异常(ios8以上不会出现)
a、定时器每秒调用一个方法,在方法内部用[btn setTitle: forState:]给按钮设置一个不断变化的标题,不会生效。采用btn.titleLabel.text = @"“解决
b、xib封装视图时,在视图内部重写layoutSubviews方法,里面设置self.width和self.height的值会崩溃。解决方法:外部设置宽高,或内部别的地方设置宽高,若宽高等于屏幕宽高,且xib是豆腐块类型时,不用设置,会自动匹配
c、xib中,对按钮,使用控制面板属性User Defined Runtime Attributes设置圆角、切割等,拷贝该按钮到另外的xib中,程序崩溃。解决方法,删除运行时设置(后面重现时又不出现了,原因不明白。。。)
24、APNs
a、ios8以前推送内容大小限制在256字节,之后提升到2k。2015年发布新版APNs协议,提升到4k
b、旧版APNs:APNs不能保证分发消息的服务器(比如第三方SDK的服务器)socket维持连接,如果socket通道上没有消息往来,socket会被路由器中断。且服务器分发消息到APNs成功后没有回应,失败后才有error并关闭该socket,因此无法知道服务器是否成功将消息分发到APNs。以前做聊天类APP,有用推送来做的,为了知道消息是否发送成功,故意每10条消息后发送一条错误消息(如用错的token),如果没有回应就表明已经中断了socket链接,上面的10条消息就另外处理。
c、新版APNs:支持返回状态码,服务器发送消息到APNs成功返回200,失败返回error。内容大小到4k。可通过心跳包检测当前socket是否可用,并维持该链接。
d、目前存在问题:APNs向你推送4条消息,但你的设备网络差,在APNs那里下线了,这时你的设备的推送列表上有4个任务列表,合理情况是当你的设备网络好时全部推送给你,但APNs只会保留最后一条消息推送给你,并告诉你一共有4条消息,丢失了另外3条(原因可能是APNs的存储-转发能力不够)。尽管这样,APNs仍然无法保证这4条消息一定能至少推送1条给你。假若能收到一条,一般是询问服务器看你有多少条未读消息(技术手段可能是用当前消息数组数量跟服务器返回的消息数做对比得知有多少条消息未收到)。现在的SDK能保证消息都推送到APNs(根据返回状态码,若推送失败,重发),但APNs无法保证推送到用户。
25、系统弹框和键盘的冲突
问题:键盘在屏幕上时,若弹出系统提示框如alertview,系统会自动退下键盘,拿到窗口来显示alertview,若点击alertView跳转到另外一个页面,系统仍旧会还原键盘的初始状态,使页面出现一闪而过的键盘视图,很难看。可以先完全退出键盘,在弹出系统提示框避免该问题。
26、启动广告实现方式
a、实时下载图片显示,适用于图片变化不是很频繁的场景
b、先显示上一次缓存的图片,这一次将图片从服务器获取并缓存,以便下一次使用。
问题点:针对根控制器不固定的场景,在显示广告的时候获取到需要加载的根控制器,保存,当广告完毕后切换根控制器。当广告过程中点击了图片,则先切换根控制器,再push到广告详情页面。
27、appstore相关
a、构建版本时,苹果使用的是项目中的build号作为key,即不能上传两份build一样的版本。但版本号version可以相同
b、appstore下架后,只是将app从appstore的搜索列表中移除,让别人搜索不到。只要取消下架,APP又会重新上架
c、加急审核跟提交版本是两个独立的操作,通过appid关联两个操作。例子:对某个app进行加急后,取消该app的审核状态,重新打包上传,即使版本号改变,依然是在加急状态
28、JPUSH若无法推送成功,选择开启日志输出,比如日志提示说证书原因导致JPUSh无法使用,恰好早些天苹果个人账号后台这些证书有变动,重新生成证书,传到JPUSH后台即成功。注意,将证书删除再重新生成新的证书上传,不会影响线上版本的推送。
29、友盟默认拿的是xcode中的bulid号作为版本统计,而不是想当然的version号
30、对图片很多的页面,例如微信空间等,可采用显示小图片,当点击图片浏览时再下载大图片。若直接使用大图片,当有很多图片时,会造成CPU使用率太高,比如藏家APP刚开始就使用的大图,导致CPU很容易达到100%,iPhone4上很容易闪退。还有,从相册拿出图片是ALAsset类型的,当将其解压转换为UIImage时会卡住主线程,需要注意。有一个跑马灯视图,由于内部使用非法动画造成循环调用,也就是动画死循环一直执行,造成CPU超过100%(多核可能超过)发热严重
31、播放视频用MPmovieplayercontroller或者AVPlayer,当网络不佳缓冲时,都不知道何时缓冲完毕(可能是因为何时缓冲完毕不好定义),我是采取随机一个5-10s的数字,让缓冲这个时间后再调用播放的方法。MPmovieplayercontroller当取消全屏时,通知MPMoviePlayerWillExitFullscreenNotification监听不到,AVPlayer观察者观察不到playbackLikelyToKeepUp(缓冲足够的BOOL属性)的变化。
32、UIPageControl,默认子视图都是UIView类型,当用KVC设置了pageImage和currentPageImage属性后,子视图会变为UIImageView类型。当设置UIPageControl的currentPage时,系统内部是先拿到对应的子视图,再切换子视图对应的图片。经过验证,有很小的可能,UIPageControl的子视图仍然是UIView类型,这时候设置currentPage时,拿到的是UIView并且给它设置UIImage,引发崩溃。所以,如果需要设置系统UIPageControl样式,最后自定义。而非用KVC
33、极光推送,若要求针对某一个版本比如2.0.2做推送,可以后台做,前端做法是绑定tag或别名,但是sdk2.1.9之前是不支持特殊符号,比如.号的,于是采用去掉.号如202的绑定方式。
目标人群设置是多选,可以根据registeration id(具体手机的id),别名,tag等多重选择选定人群。
附加字段会设置到推送的字典里面去,一个为key一个为value,在项目中对其进行处理
34、其他
NSURLRProtocol缓存web内容,监听一切url请求(WKWebView除外)
layer.mask,涂层mask有妙用
CAShapeLayer配合UIBeriPath做动画
栅栏化(大意是将要cell缓存成一张图片显示,提升表格性能,Core Animation书上有)
SDWebImage播放gif图片时内存容易爆掉,缺陷在gif图片拆分成多张帧图片时存储在一个数组中,该数组导致内存变大。YYAnimationView(YYKit框架)不会这样。思路大概是开启CADisplayLink,不断存储下一帧需要播放的图片并清除掉已经播放完毕的图片。SDWebImage和YYWebImage为了性能优化,都是缓存的图片数据解压后的data,此对大图片容易造成内存爆炸,有个属性可以禁用图片解压操作,或者可以限制内存缓存,或者限制内存缓存大小等。。。
内存泄漏:block,delegate没用weak,C、CF语言框架,工具类方法传入了控制器的view,而方法内部强引用了控制器(注意保证工具类方法view属性为weak即可),。 一般会在控制器销毁时观察dealloc方法判断是否有内存泄漏。可以考虑做个简易框架,原理:监测导航栏的pop方法,该方法内部延后一段时间(比如2s),断言该控制器为nil,否则未销毁程序被打断
cookies和session,前者客户端,会增大http头的大小,保存少量信息,如浏览器账号密码等,安全等级低。后者服务端,但是需要客户端配合保存sessionId,安全等级高。这两个东西大体是相同的,作用:增加网络访问速度。比如app加载一个web页面,非首次加载明显变快
本地缓存如何在服务器内容修改后及时更新?Last-Modified 或者 Etag,标示服务器内容是否更改,未更改则返回特定状态码而非数据,否则直接返回数据。因为请求等幂等原因,POST请求无法被缓存。
数字签名原理详解:http://blog.jobbole.com/107930/
http请求头中KeepAlive的作用就是在第一次创建连接时,服务器会把这个tcp连接保持一段时间(服务器端会有一个keepaliveTime的最大时间,超过时间就断开连接)。缺点,长链接消耗服务端内存
网络请求DNS解析缓存,配置HOST文件绕过DNS解析,网关。。。
FMDB时,数据库嵌套操作会导致死锁。
tableView中cell上有个文本框,文本框内容变化时调用tableView的reloadData会导致键盘自动消失。此时可用beginUpdates和endUpdates替代刷新操作
CAAnimation的delegate属性是strong,原因
1、动画是异步的,动画完成后动画线程销毁,delegate属性清空,不会产生内存泄露
2、若不用strong,则若动画过程中控制器销毁,而动画代理方法中引用了控制器,程序可能崩溃
尽量不要设置removedOnCompletion = false ,这样动画完成后代理并不会被清空,配合CAAnimationDelegate会带来循环运用的问题,如果需要动画停留在最后的状态,可以直接设置View的center属性在动画结束的位置Point
线程间通信:
1、基于端口的输入源: NSPort 的方法- (BOOL)sendBeforeDate:(NSDate *)limitDate msgid:(NSUInteger)msgID components:(nullable NSMutableArray *)components from:(nullable NSPort *)receivePort reserved:(NSUInteger)headerSpaceReserved;
2、[self performSelector:<#(nonnull SEL)#> onThread:<#(nonnull NSThread *)#> withObject:<#(nullable id)#> waitUntilDone:<#(BOOL)#>],缺点是执行线程方法时若线程已经销毁,则崩溃
3、自定义输入源:使用CGRunLoopSourceRef
相关详细文章地址:http://www.jianshu.com/p/4d5b6fc33519
38、 输入中文时限制字符长度
- (void)textViewDidChange:(UITextView *)textView{
NSString *toBeString = textView.text;
NSString *language = textView.textInputMode.primaryLanguage;
if ([language isEqualToString:@"zh-Hans"]) {
UITextRange *selectedRange = textView.markedTextRange;
// selectedRange为空,说明拼音已经转换为中文
if (!selectedRange && toBeString.length > 5) {
textView.text = [toBeString substringToIndex:5];
}
}else if(toBeString.length > 5){
textView.text = [toBeString substringToIndex:5];
}
}
39.Array 的深复制
指针的复制
dataArray3=[dataArray2 mutableCopy];
知识对dataArray2 进行了深复制,数组中的内容仅仅是指针的复制。
单层深复制
dataArray3=[[NSMutableArray alloc]initWithArray:dataArray2 copyItems:YES];
dataArray2进行本身和内容的深复制。单仅仅是内容的第一层
完全深复制
dataArray3 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:dataArray2]];
不管多少层都可以进行了深复制
40.MLeaksFinder 检查内存泄露
41.有些偶尔会出现的bug原因猜测
a、有些代码是有执行顺序的,而网络请求返回时间不定导致
b、线程问题。如多线程异步队列任务执行结果顺序不一定导致
c、dispatch_group_t由于请求可能的失败导致的组进出次数不一致导致崩溃
d、服务器线程问题。比如同时日程重构,同时发送两个请求,但是服务器最终访问的是一个方法,线程错乱导致回调结果反了
42.fmdb优化
精简sql语句,比如表的连接操作,小的表放到左边,总之让过滤条件先过滤掉尽可能多的数据
fmdb默认缓存是关闭的,开启
默认执行一条sql开启关闭一次事物。批量操作时,手动开启事物,很多sql执行完毕再提交或回滚事物
fmdb存储数组对象。可以一张表,则数组对象归档成nsdata,对象之间用逗号分开,把数组对象当成字符串存储
coredata,有一种自定义存储类型Transformable,可以存储数组,也是利用归档原理
也可以两张表存储,但是那样管理麻烦