iOS-Swift面试总结(1)
问题归纳
1.如何在OC中调用swift的文件?
步骤:直接托swift文件 --> 建立桥接头文件 --> target --> building
offset.png
setting--> 输入product --> Packaging --> Project ModuleName
--> SwiftModule --> 在桥接头文件里加入头文件#import "SwiftModule-
swift.h"
作用: 此头文件中就包含了所有.swift的文件
15.几种持久化存储的区别:plist、NSUserDefault、归档(coder)、数据库
plist文件
property list 属性列表文件,文件的内容只能是 NSString NSNumber NSDate NSData NSArray NSDictionary类的对象内容,不能保存其他类型数据。
作用: 对一些登陆注册信息或者程序的配置信息(小数据)进行持久化存储。归档
归档(也称对象序列化,对象持久化存储)就是用某种打包格式将对象保存到本地的文件,以便以后读回该对象的内容;解档(也称归档/读档)就是把归档的对象文件,读成原来的对象的过程。
NSUserDefaults
NSUserDefaults适合存储轻量级的本地数据,比如要保存一个登陆界面的数据,用户名、密码之类的,个人觉得使用NSUserDefaults是首选。下次再登陆的时候就可以直接从NSUserDefaults里面读取上次登陆的信息。
数据库
数据库管理系统(Database Management System)是一种操纵和管理数据库的大型软件,用于建立、使用和维护数据库,简称..DBMS。它对数据库进行统一的管理和控制,以保证数据库的安全性和完整性。
15.1. sqlite和CoreData的区别
a. 使用方便性。一个成熟的工程中一定是对数据持久化进行了封装的,因此底层使用的到底是core data还是sqlite,不应该被业务逻辑开发者关心。因此,即使习惯写SQL查询的人,也应该避免在业务逻辑中直接编写SQL语句。
b. 存储性能,在写入性能上,因为都是使用的sqlite格式作为磁盘存储格式,因此其性能是一样的。
c. 查询性能,core data因为要兼容多种后端格式,因此查询时,其可用的语句比直接使用sqlite少,因此有些fetch实际上不是在sqlite中执行的。
d. core data的一个比较大的痛点是多人合作开发的时候,管理coredata的模型需要很小心,尤其是合并的时候,它的data model是XML格式的,手动resolve比较烦心。
e. core data还有其他sql所不具备的优点,比如对undo的支持,多个context实现sketchbook类似的功能。为ManagedObject优化的row cash等。
f. 另外core data是支持多线程的,但需要thread confinement的方式实现,使用了多线程之后可以最大化的防止阻塞主线程。
16.响应者链
解答:
子控件/子视图的响应事件响应顺序:UIApplication --> window --> controller(控制器) --> 父控件(父视图)--> 子控件/子视图(第一响应者)
注意:其一父类不响应就会拦截17.GCD
回答:
dispatch_get_global_queue 后台执行
dispatch_get_main_queue 主线程执行
dispatch_once_t 一次性执行
dispatch_time_t 延迟执行dispatch_group_async 并行执行
dispatch_group_notify 并行执行后汇总18.UITableView的复用机制
复用机制:
UITableView首先加载一屏幕(假设UITableView的大小是整个屏幕的大小)所需要的UITableViewCell,具体个数要根据每个cell的高度而定,总之肯定要铺满整个屏幕,更准确说当前加载的cell的高度要大于屏幕高度。然后你往上滑动,想要查看更多的内容,那么肯定需要一个新的cell放在已经存在内容的下边。这时候先不去生成,而是先去UITableView自己的一个资源池里去获取。这个资源池里放了已经生成的而且能用的cell。如果资源池是空的话才会主动生成一个新的cell。那么这个资源池里的cell又来自哪里呢?当你滑动时视图是,位于最顶部的cell会相应的往上滑动,直到它彻底消失在屏幕上,消失的cell去了哪里呢?你肯定想到了,是的,它被UITableView放到资源池里了。其他cell也是这样,只要一滑出屏幕就放入资源池。这样,有进有出,总共需要大约一屏幕多一两个的cell就够了。相对于1000来说节省的资源就是指数级啊,完美解决了性能问题
注意:
设置 Cell 的存在差异性的那些属性(包括样式和内容)时,有了 if 最好就要有 else,要显式的覆盖所有可能性。
设置 Cell 的存在差异性的那些属性时,代码要放在初始化代码块的外部
优化:
- 通过正确的设置 reuseIdentifier 来重用 Cell。
- 尽量减少不必要的透明 View。
- 尽量避免渐变效果、图片拉伸和离屏渲染。
- 当不同的行的高度不一样时,尽量缓存它们的高度值。
- 如果Cell 展示的内容来自网络,确保用异步加载的方式来获取数据,并且缓存服务器的 response。
使用 shadowPath 来设置阴影效果。- 尽量减少 subview 的数量,对于 subview 较多并且样式多变的 Cell,可以考虑用异步绘制或重写drawRect。
- 尽量优化 - [UITableView tableView:cellForRowAtIndexPath:]
方法中的处理逻辑,如果确实要做一些处理,可以考虑做一次,缓存结果。- 选择合适的数据结构来承载数据,不同的数据结构对不同操作的开销是存在差异的。
对于 rowHeight、sectionFooterHeight、sectionHeaderHeight 尽量使用常量。19.UITableView的优化
- 复用问题
- 尽量避免使用动画
- 在图片数量多的情况下,使用异步加载,并做缓存
- 自定义cell的时候直接绘制drawRect(几乎没人用)
20.内存管理
swift中使用的是ARC(自动管理)内存管理技术
oc中使用的是MRC(手动管理)和ARC(自动管理)的内存管理技术
ARC是IOS5推出的新功能,通过ARC,可以自动的管理内存。在ARC模式下,只要没有强指针(强引用)指向对象,对象就会被释放。在ARC模式下,不允许使用retain、release、retainCount等方法。并且,如果使用dealloc方法时,不允许调用[super dealloc]方法。
ARC模式下的property变量修饰词为strong、weak,相当于MRC模式下的retain、assign。strong :代替retain,缺省关键词,代表强引用。weak:代替assign,声明了一个可以自动设置nil的弱引用,但是比assign多一个功能,指针指向的地址被释放之后,指针本身也会自动被释放。
注意
在ARC的项目中,对MRC的文件可以添加编译选项-fno-objc-arc的标识;
在MRC的项目中对ARC的文件可以添加编译选项 -fobjc-arc的标识。21.代理和通知的区别
代理:1个对象只能告诉另1个对象发生了什么事
通知:1个对象可以告诉N个对象发生了什么事22.在做友盟分享之前需要做哪些准备工作
01 最基本配置
下载友盟SDK导入到工程中,按照说明导入三方库
设置授权
AppDelegate中 //设置友盟的AppKey(友盟基础SDK授权) [UMSocialData setAppKey:@"578c894ae0f55a30f30008d3"]; //设置如果检测到当前用户没有安装我集成的分享平台,直接隐藏平台 //这里面需要隐藏的可以自己加 [UMSocialConfig hiddenNotInstallPlatforms:@[UMShareToQQ, UMShareToQzone, UMShareToWechatSession, UMShareToWechatTimeline]]; //要在Application中调用一下这个方法(添加系统回调) - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { BOOL result = [UMSocialSnsService handleOpenURL:url]; if (result == FALSE) { //调用其他SDK,例如支付宝SDK等 } return result; }
02 手动集成微信
苹果自带集成的只有新浪微博和腾讯微博,其它的微信,QQ之类的需要自己导入
导入微信的Wechat
//设置微信AppId、appSecret,分享url(先用友盟的)( AppDelegate中) [UMSocialWechatHandler setWXAppId:@"wxd930ea5d5a258f4f" appSecret:@"db426a9829e4b49a0dcac7b4162da6b6" url:@"http://www.umeng.com/social"]; 并在info的URL Types中添加 URL Schemes (就是:wxd930ea5d5a258f4f)
03 点击分享的写法
- (IBAction)clickShareBtn:(UIButton *)sender { [UMSocialSnsService presentSnsIconSheetView:self appKey:nil shareText:@"电视通" shareImage:[UIImage imageNamed:@"test_t108"] shareToSnsNames:@[UMShareToTencent,UMShareToWechatSession,UMShareToQQ] delegate:self]; } 在当前控制器遵守协议方法 @interface ViewController ()<UMSocialUIDelegate> //实现一个代理方法 -(void)didFinishGetUMSocialDataInViewController:(UMSocialResponseEntity *)response { if (response.responseCode == UMSResponseCodeSuccess) { NSLog(@"分享成功"); } }
04 配置info.plist文件的跳转key(配置这个应用才能跳转到分享平台)
步骤:点击info -> open as -> Source Code 在最后的</dict> </plist> 前面添加 <key>LSApplicationQueriesSchemes</key>(这个直接在友盟那边有的) //下面是整个key <key>LSApplicationQueriesSchemes</key> <array> <!-- 微信 URL Scheme 白名单--> <string>wechat</string> <string>weixin</string> <!-- 新浪微博 URL Scheme 白名单--> <string>sinaweibohd</string> <string>sinaweibo</string> <string>sinaweibosso</string> <string>weibosdk</string> <string>weibosdk2.5</string> <!-- QQ、Qzone URL Scheme 白名单--> <string>mqqapi</string> <string>mqq</string> <string>mqqOpensdkSSoLogin</string> <string>mqqconnect</string> <string>mqqopensdkdataline</string> <string>mqqopensdkgrouptribeshare</string> <string>mqqopensdkfriend</string> <string>mqqopensdkapi</string> <string>mqqopensdkapiV2</string> <string>mqqopensdkapiV3</string> <string>mqzoneopensdk</string> <string>wtloginmqq</string> <string>wtloginmqq2</string> <string>mqqwpa</string> <string>mqzone</string> <string>mqzonev2</string> <string>mqzoneshare</string> <string>wtloginqzone</string> <string>mqzonewx</string> <string>mqzoneopensdkapiV2</string> <string>mqzoneopensdkapi19</string> <string>mqzoneopensdkapi</string> <string>mqqbrowser</string> <string>mttbrowser</string> <!-- 支付宝 URL Scheme 白名单--> <string>alipay</string> <string>alipayshare</string> <!-- 人人 URL Scheme 白名单--> <string>renrenios</string> <string>renrenapi</string> <string>renren</string> <string>renreniphone</string> <!-- 来往 URL Scheme 白名单--> <string>laiwangsso</string> <!-- 易信 URL Scheme 白名单--> <string>yixin</string> <string>yixinopenapi</string> <!-- instagram URL Scheme 白名单--> <string>instagram</string> <!-- whatsapp URL Scheme 白名单--> <string>whatsapp</string> <!-- line URL Scheme 白名单--> <string>line</string> <!-- Facebook URL Scheme 白名单--> <string>fbapi</string> <string>fb-messenger-api</string> <string>fbauth2</string> <string>fbshareextension</string> </array> // 然后在info -> open as -> proprety plist 中查看 #完成以上四个步骤就已经可以进行微信分享了,要真机测试分享出来的内容是我自己写的。但是来源会显示友盟自己在微信上申请的应用名
05 手动集成新浪微博
1.导入SinaSSO ,要导入一个依赖库:ImageIO 2. AppDelegate中 导入新浪头文件#import "UMSocialSinaSSOHandler.h" 3.//配置新浪 //第一个参数为新浪appkey,第二个参数为新浪secret,第三个参数是新浪微博回调地址,这里必须要和你在新浪微博后台设置的回调地址一致。 [UMSocialSinaSSOHandler openNewSinaSSOWithAppKey:@"3921700954" secret:@"04b48b094faeb16683c32669824ebdad" RedirectURL:@"http://sns.whalecloud.com/sina2/callback"]; 4.在info中加URL Types 新浪的URL Schemes 是 wb 加上 appkey wb3921700954 5.要想分享到新浪微博必须加下面的东东 # Build Settings -> 搜索 other link -> 在 Other Linker Flags 中添加 -ObjC (注意O和C是大写的)
06 手动集成QQ
1.一样先导入QQ的框架:TencentOpenAPI 2.获得授权 [UMSocialQQHandler setQQWithAppId:@"100424468" appKey:@"c7394704798a158208a74ab60104f0ba" url:@"http://www.umeng.com/social"]; 3.配置URL schemes(从分享平台跳转回当前应用) QQ:需要配置两个 3.1 :“QQ”+腾讯QQ互联应用appId转换成十六进制(不足8位前面补0),例如“QQ05FC5B14” 3.2:"tencent"+腾讯QQ互联应用appId,例如“tencent100424468
07 三方登录
1.三方登录就好办了,直接在登录平台按钮的方法里将友盟写的各个平台的代码复制过来就好 2.注意有些三方平台是需要获得登录权限的(一般就是要收费,如微信) 3.我们在打印信息中就可以拿到用户三方平台的昵称,账号,头像等公共信息做一个快捷登录
23.友盟分享SDK的集成步骤
同上
24.自定义分享面板的步骤
25.cocoa Pods实际上帮你了做了哪些配置
26.高德地图SDK在使用之前需要做哪些准备工作
27.高德地图SDK,定位SDK的集成步骤
28.什么是线程
线程,有时被称作轻量级进程,是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针,寄存器集合和堆栈组成。通常意义上,一个进程由多个线程组成,各个线程之间共享程序内存空间和一些进程级资源。
线程的访问非常自由,它可以访问进程内存里所有数据,甚至包括其他线程的堆栈,但实际运用中线程也有自己的私有存储空间包括:栈,线程局部存储,寄存器。
线程至少有三个状态:运行,就绪,等待。改变线程优先级一般有三种方式:用户指定优先级,根据等待状态的频繁程度改变优先级,长时间得不到执行。线程主动放弃执行:等待事件,主动放弃。
29.线程和进程的区别
- 一个程序至少要有进程,一个进程至少要有一个线程.
- 进程:资源分配的最小独立单元,进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
- 线程:进程下的一个分支,是进程的实体,是CPU调度和分派的基本单元,它是比进程更小的能独立运行的基本单位,线程自己基本不拥有系统资源,只拥有一点在运行中必不可少的资源(程序计数器、一组寄存器、栈),但是它可与同属一个进程的其他线程共享进程所拥有的全部资源。
- 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
- 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。
- 但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
30.系统创建多线程的方式有哪几种,分别是什么,各自的优点
多线程的概念: 情况下,UI的操作都是在主线程中进行的,如果涉及到文件的下载、图片的加载、音视频的播放等耗时操作时,在主线程中直接进行的话,会造成主界面假死(主线程堵塞),所有可以使用多线程处理耗时操作,重新开辟新的子线程,用于处理耗时操作,操作完成之后回到主线程刷新UI
分类:
同步串行:不开新线程 任务依次执行
同步并行:不开启新线程 任务依次执行
异步串行:开启新线程 任务依次同时执行
异步并行:开启新线程 多个任务同时执行
无论是串行还是并行,在同一个线程中同步执行任务,都是按照顺序一个一个执行,等待队列中的任务全部执行完成之后再接着执行
异步执行任务,所有任务同时执行,不会做任何等待31.分别在什么情境下使用GCD和NSOperation
32.在实际项目中,什么时候会用到多线程,有什么作用
在实际项目中,进行大量计算的操作就在异步线程中执行,需要刷新界面或者UI的时候就需要回到主线程中执行
33.在使用多线程的过程中遇到过什么问题
34.viewWillAppear viewDidLoad drawRect 他们的调用顺序
viewDidLoad --> drawRect --> viewWillApper
35.APN的推送机制
36.苹果原生推送和极光推送的区别(极光推送相对于苹果原生推送有哪些优点)
37.APNS在推送的过程中会设计到那几个方面
38.开发者账号有哪几种?
- 个人开发者账号: 99$,个人开发者账号只能有一个开发者,通过他开发的应用可以上架到App Store,每个账号限定100台设备,每年需要续费一次
- 公司开发者账号:99$,公司开发者账号可以允许有多个开发者,在申请开发者账号之前需要先申请一个邓白氏编码,然后再申请开发者账号,通过他开发的应用可以上架到App Store,每个账号的设备同样是100台,每年需要续费
- 企业开发者账号:299$,企业开发者账号可以允许多个开发者,在申请开发者账号之前需要先申请一个邓白氏编码,然后再去申请开发者账号,通过他开发的应用不能上架到App Store ,主要是为了内部使用。(需要打包才能上架),设备最多可以达到1000台
- 教育开发者账号:免费,在申请的时候需要上传由国家颁布的学院营业执照
39.支付宝、微信、银联SDK的集成步骤
40.支付宝、微信、银联支付的流程
支付宝的支付流程:
1.客户端生成订单
2.调起支付宝客户端或者网页发送订单
3.收到支付宝支付完成的结果,处理结果
微信的支付流程
1.用户在商户APP中选择商品,提交订单,选择微信支付。
2.商户后台收到用户支付单,调用微信支付统一下单接口。
3.统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay
4.商户APP调起微信支付。
5.商户后台接收支付通知。
6.商户后台查询支付结果。
银联支付的流程:
1.客户端向公司服务器发起请求(上传订单)公司服务器将订单请求推送到银联服务器
2.银联服务器审核通过之后生成交易流水号返回到公司服务器
3.客户端通过交易流水号向银联服务器发起支付请求41.支付完成之后的结果
1. 支付成功 2. 支付失败 余额不足 网络问题 用户取消支 在实际项目中,支付宝支付会跟公司自己的服务器交互 支付宝支付有客户端和h5支付两种方式,会自当判断手机客户端是否安装有支付宝客户端