iOS总结

作者: 苹果上的小豌豆 | 来源:发表于2018-03-26 10:11 被阅读0次

1.说下线程和进程的区别。

线程是CPU独立运行和独立调度的基本单位(可以理解为一个进程中执行的代码片段)。

 进程是资源分配的基本单位(进程是一块包含了某些资源的内存区域)。

进程有独立的地址空间,一个进程崩溃后,在保护模式的影响下不会对其他进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等同于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程是线程的容器,真正完成代码执行的线程,而进程则作为线程的执行环境。一个程序至少包含一个进程,一个进程至少包含一个线程,一个进程中的所有线程共享当前进程所拥有的资源。

2.了解哪些设计模式

设计模式大概分成三类:

1.创建型:单例设计模式、抽象工厂设计模式

2.结构型:MVC 模式、装饰器模式、适配器模式、外观模式、组合模式

3.行为型:责任链设计模式、观察者设计模式,备忘录设计模式、命令设计模式

单例设计模式有如下特点:

1.单例设计模式确保对于一个给定的类只有一个实例存在,这个实例有一个全局唯一的访问点。

2.它通常采用延迟加载的方式在第一次用到实例的时候再去创建它。

[NSUserDefaults standardUserDefaults], [UIApplication sharedApplication], [UIScreen mainScreen], [NSFileManager defaultManager],所有的这些方法都返回一个单例对象

单例模式实现步骤:

1.声明一个静态变量去保存类的实例,确保它在类中的全局可用性。

2.声明一个静态变量dispatch_once_t ,它确保初始化器代码只执行一次

3.使用Grand Central Dispatch(GCD)执行初始化LibraryAPI变量的block.这  正是单例模式的关键:一旦类已经被初始化,初始化器永远不会再被调用。

下一次你调用sharedInstance的时候,dispatch_once块中的代码将不会执行(因为它已经被执行了一次),你将得到原先已经初始化好的实例。

3.MVVM

很简单,处理视图展示逻辑,ViewModel负责将数据业务层提供的数据转化为界面展示所需的VO。其与View一一对应,没有View就没有ViewModel

4.即时通讯

环信SDK,腾讯的融云SDK。

5.支付

1.支付宝

创建应用和KEY支付宝支付创建

新版之后只需要导入两个文件就可以解决了,文件如下:

AlipaySDK.framework

AlipaySDK.bundle

一般前端客户端只需要传递给后台价格 和商品ID,请求后台服务器接口。后台在将价格等参数一一对应返回给 前端订单信息orderInfo,md5Sign,orderSign,out_trade_no。四个参数。第一步根据订单信息orderInfo + 自己与后台定义的key用MD5加密。加密得到的值是否和参数md5Sign相同。如果相同,则订单信息加密正确。

将商品信息拼接成字符串 signStr = orderSign .encodeString

最后生成一个orderInfo + sign =  signStr +  sign_type = RSA

启动支付宝

[[AlipaySDK defaultService] payOrder:orderString fromScheme:[self qw_appScheme] callback:^(NSDictionary *resultDic) {    }];

2.微信支付

商户系统和微信支付系统主要交互说明:

步骤1:用户在商户APP中选择商品,提交订单,选择微信支付。

步骤2:商户后台收到用户支付单,调用微信支付统一下单接口。点击打开链接

步骤3:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay

步骤4:商户APP调起微信支付。点击打开链接

步骤5:商户后台接收支付通知。点击打开链接

步骤6:商户后台查询支付结果。点击打开链接

(一般这些商户信息都交给后台操作)

3.苹果内购

可参考苹果内购

6.使用了第三方库, 有看他们是怎么实现的吗?

SD、YY、AFN、MJ

1.入口 setImageWithURL:placeholderImage:options:会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片。查找是否缓存了图片。先从内存缓存中查找,没有再从硬盘查找,根据URLKey在硬盘缓存目录读取。否则回调 imageCache:didNotFindImageForKey:userInfo:下载图片。共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。

2.MJ刷新原理iOS-MJRefresh框架底层实现原理利用scrollView在滚动,就会调用这个代理方法。UIEdgeInsetsinset =self.tableView.contentInset;  inset.top+=self.header.height;self.tableView.contentInset = inset;


7.遇到tableView卡顿嘛?会造成卡顿的原因大致有哪些

1.最常用的就是cell的重用, 注册重用标识符

如果不重用cell时,每当一个cell显示到屏幕上时,就会重新创建一个新的cell;

如果有很多数据的时候,就会堆积很多cell。

如果重用cell,为cell创建一个ID,每当需要显示cell 的时候,都会先去缓冲池中寻找可循环利用的cell,如果没有再重新创建cell

2.避免cell的重新布局

cell的布局填充等操作 比较耗时,一般创建时就布局好

如可以将cell单独放到一个自定义类,初始化时就布局好

3.提前计算并缓存cell的属性及内容

当我们创建cell的数据源方法时,编译器并不是先创建cell 再定cell的高度

而是先根据内容一次确定每一个cell的高度,高度确定后,再创建要显示的cell,滚动时,每当cell进入凭虚都会计算高度,提前估算高度告诉编译器,编译器知道高度后,紧接着就会创建cell,这时再调用高度的具体计算方法,这样可以方式浪费时间去计算显示以外的cell

4.减少cell中控件的数量

尽量使cell得布局大致相同,不同风格的cell可以使用不用的重用标识符,初始化时添加控件,

不适用的可以先隐藏

5.不要使用ClearColor,无背景色,透明度也不要设置为0

渲染耗时比较长

6.使用局部更新

如果只是更新某组的话,使用reloadSection进行局部更新

7.加载网络数据,下载图片,使用异步加载,并缓存

8.少使用addView 给cell动态添加view

9.按需加载cell,cell滚动很快时,只加载范围内的cell

10.不要实现无用的代理方法,tableView只遵守两个协议

11.缓存行高:estimatedHeightForRow不能和HeightForRow里面的layoutIfNeed同时存在,这两者同时存在才会出现“窜动”的bug。所以我的建议是:只要是固定行高就写预估行高来减少行高调用次数提升性能。如果是动态行高就不要写预估方法了,用一个行高的缓存字典来减少代码的调用次数即可

12.不要做多余的绘制工作。在实现drawRect:的时候,它的rect参数就是需要绘制的区域,这个区域之外的不需要进行绘制。例如上例中,就可以用CGRectIntersectsRect、CGRectIntersection或CGRectContainsRect判断是否需要绘制image和text,然后再调用绘制方法。

13.预渲染图像。当新的图像出现时,仍然会有短暂的停顿现象。解决的办法就是在bitmap context里先将其画一遍,导出成UIImage对象,然后再绘制到屏幕;

14.使用正确的数据结构来存储数据。


8.编译过程做了哪些事情


Objective和Swift。二者都是编译语言,换句话说都是需要编译才能执行的。二者的编译都是依赖于Clang + LLVM. OC和Swift因为原理上大同小异。

9.字典大致实现原理


NSDictionary(字典)是使用hash表来实现key和value之间的映射和存储的

方法:- (void)setObject:(id)anObject forKey:(id)aKey;

Objective-C中的字典NSDictionary底层其实是一个哈希表

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

哈希概念:哈希表的本质是一个数组,数组中每一个元素称为一个箱子(bin),箱子中存放的是键值对。

10.加密方式

1.排序验签加密  

//生成sign   主接口+ time+version+ tp + sign

+ (NSString *)getSignAndSignDict:(NSMutableDictionary *)dict

{

    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:dict];

    [dic setValue:QWVersion forKey:@"version"];

    [dic setValue:[QWCommonFunc time] forKey:@"timeStamp"];

    [dic setValue:QWPt forKey:@"pt"];

    [dic setValue:QWImei forKey:@"imei"];

    NSString *singstr = [self sortDicToString:dic];

    return singstr;

}

//排序验签

+ (NSString *) sortDicToString:(NSMutableDictionary *)dic{

    //排序

    NSMutableArray *stringArray = [NSMutableArray arrayWithArray:dic.allKeys];

    QWLog(@"%@",stringArray);

    [stringArray sortUsingComparator: ^NSComparisonResult (NSString *str1, NSString *str2) {

        return [str1 compare:str2];

    }];

    QWLog(@"%@",stringArray);

    //验签

    NSString *md5StrPre = @"";

    for (int i = 0; i < [stringArray count]; i++) {

        NSString *key = [stringArray objectAtIndex:i];

        md5StrPre = [md5StrPre stringByAppendingString:[dic objectForKey:key]];

    }

    NSString *getKey = QWKey;

    md5StrPre = [md5StrPre stringByAppendingString:getKey];

    NSString *md5Str = [QWCommonFunc md5:md5StrPre];

    return md5Str;

}

2.head头加密

let manager = AFHTTPSessionManager.init()

            let secretKey  = ""

            let accessKey  = ""

            let t    : String  = BaseConfig.shared.t.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? " "

            let randomStr    : String  = BaseConfig.shared.randomStr.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? " "

            let baseString = secretKey + randomStr + t

            let sign = baseString.MD5()

            manager.responseSerializer = AFJSONResponseSerializer.init(readingOptions: .mutableContainers)

            manager.requestSerializer  = AFJSONRequestSerializer.init(writingOptions: .prettyPrinted)

            manager.requestSerializer.timeoutInterval = 7

            manager.requestSerializer.setValue(sign, forHTTPHeaderField: "api-signature")

            manager.requestSerializer.setValue(randomStr, forHTTPHeaderField: "api-echostr")

            manager.requestSerializer.setValue(t, forHTTPHeaderField: "api-timestamp")

            manager.requestSerializer.setValue(accessKey, forHTTPHeaderField: "api-access-key")

            let contentTypes: Set = ["application/json", "text/json", "text/javascript","text/html", "application/x-javascript","audio/mpeg"]

            manager.responseSerializer.acceptableContentTypes = contentTypes

3.AES加密

加密的过程: 字典 --> json字符串 --> base64加密后的字符串 --> AES加密后base64再加密 --> 输出加密后的字符串

解密的过程 : 与加密过程相反  ,输入参数 : base64String  base64编码的字符串 ; key  密钥

AES的加密模式为  AES128 + ECB + NoPadding

相关文章

网友评论

      本文标题:iOS总结

      本文链接:https://www.haomeiwen.com/subject/caalqftx.html