PS: 文章是从垃圾箱找出来的,之前误删了,看有些问题还是挺好的,所以再次发布出来。
Block在哪个内存区?
block块的存储位置(block入口的地址)可能存放在3个地方
- 全局区
- 不引用栈区的变量(如局部变量)和堆区的变量(如用alloc创建的对象)时,此时block存放在代码区
- 堆区
- 访问了堆区的变量,此时block存在于堆区
栈区(MRC)
- 访问了栈区的变量,此时block存在于栈区,在ARC情况下自动拷贝到堆区
注:ARC情况下会自动拷贝到堆区、因此ARC下只有两个地方:全局区和堆区
如何实现深拷贝?
- 1、基本数据类型直接可以实现深拷贝
- 2、自定义数据类型需要实现NSCoping协议,并调用 copyWithZone:这个方法
手写冒泡排序算法
OC语言
NSMutableArray *nums = @[@2,@34,@8,@23,@5,@54,@333,@9].mutableCopy;
for (int i = 0; i < nums.count; i++) {
for (int j = 0; j < nums.count - i - 1; j++) {
if (nums[j] > nums[j+1]) {
NSNumber *temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
NSLog(@"%@",nums);
// 打印结果
(
2,
5,
8,
9,
23,
34,
54,
333
)
C 语言
int nums[7] = {10,8,5,27,6,22,90};
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 7 - i - 1; j++) {
if (nums[j] > nums[j+1]) {
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
for (int i = 0; i < 7; i++) {
printf("%d ",nums[i]);
}
MVC 和 MVVM 区别及各自的优缺点?
MVC:
作为老牌架构, 优点在于将业务场景按展示数据类型划分出多个模块, 每个模块中的C层负责业务逻辑和业务展示, 而M和V应该是互相隔离的以做重用, 另外每个模块处理得当也可以作为重用单元. 拆分在于解耦, 顺便做了减负, 隔离在于重用, 提升开发效率. 缺点是没有区分业务逻辑和业务展示, 对单元测试不友好.
MVVM:
作为集大成者, 通过数据绑定做数据更新, 减少了大量的代码工作, 同时优化了代码逻辑, 只是学习成本有点高, 对新手不够友好.
MVVM 优点:
- 1、由于展示逻辑被抽取到了 ViewModel 中,所以 View 中的代码将会变得非常轻量级;
- 2、由于 ViewModel 中的代码是与 UI 无关的,所以它具有良好的可测试性;
- 3、对于一个封装了大量业务逻辑的 Model 来说,改变它可能会比较困难,并且存在一定的风险。在这种场景下,ViewModel 可以作为 Model 的适配器使用,从而避免对 Model 进行较大的改动。
MVVM+RAC 结合使用实现双向绑定
通过KVO和RAC的RACSignal实现双向绑定
详见个人博客:
iOS-ReactiveCocoa(RAC)的高级使用之视图与模型的双向绑定
单利的几种实现方式
1、自己创建
+(instancetype)sharedSingleton
{
static id instance = nil;
@synchronized (self) {
if (!instance) {
instance = [[self alloc] init];
}
}
return instance;
}
2、通过GCD的dispatch_once创建(推荐)
+(instancetype)sharedSingleton
{
static id instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
Swift 与 Objective-c的区别
- 1、强语言,更加严谨,每写一行代码系统都会自动检测是否有错误,这样就减少了运行后出错的可能;
- 2、代码简洁,文件减少,语法简洁已读
- 3、有命名空间
- 4、性能更好,可以理解为没有C的OC,舍去了C,编译过程比OC少了一层
- 5、没有了宏定义,摒弃了OC大量使用宏的弊端
- 6、……自行补充吧,很多细节有变化,比如:懒加载,单例
Swift 中的@objc
的作用
- 在 Swift 代码中,使用@objc修饰后的类型,可以直接供 Objective-C 调用
- Swift 为了效率禁用了 Objective-C 中有的动态特性,通过 @objc 关键字来使用动态特性
一个视图,旋转45度,frame和bounds如何变化?
frame会发生改变,而且变大,bounds不变
子视图旋转45度后:
WKWebView与H5交互,遇到的问题(项目中印象深的一个问题之一)?
用WKWebView与H5交互的时候,交互不成功,alert( )方法不被调用!不管是通过原声的交互方法,还是第三方,都不提示alert(),以为无法进行交互!最后发现WKWebView不支持JS的弹窗,需要自己实现对应方法,才可以显示alert弹窗。
KVO的底层实现?
Runtime
当你观察一个对象时,一个新的类会动态被创建。这个类继承自该对象的原本的类,并重写了被观察属性的 setter 方法。自然,重写的 setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象值的更改。最后把这个对象的 isa 指针 ( isa 指针告诉 Runtime 系统这个对象的类是什么 ) 指向这个新创建的子类,对象就神奇的变成了新创建的子类的实例。
出现crash的情况有哪些?项目中遇到的哪些crash?
数组越界、野指针、数组插入空对象、拷贝自定义对象、类型不匹配、方法找不到……
一个类,实现了多个分类,实现了父类的同一个方法,执行顺序?
方法只会执行一次,谁第一个实现的分类,执行谁的分类方法实现
同一个线程,发出通知,自己的类中有一个观察者,其他类也有观察者,他们的执行顺序?
谁先注册,谁先执行
SDWebImage内部实现过程
- 1、先把placeholderImage显示,然后 SDWebImageManager 根据 URL 开始处理图片;
2、SDWebImageManager 从缓存查找图片是否已经下载;
- 先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,前端展示图片
- 如果内存缓存中没有,根据 URLKey 在硬盘缓存目录下尝试读取图片文件
3、如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片;
- 4、下载完成,回调给需要的地方展示图片;
- 5、将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。
属性中的 copy 和 strong
- 在平时定义属性的时候,对于NSString 和 block 我们经常用 copy 来修饰
- 数组和字典等类型用 strong 来修饰;
- 当使用 copy 修饰属性的时候,属性的setter方法会调用[object copy]产生新的对象,
- 这样,当原object对象的值发生改变时,并不影响新对象值;
// 定义NSString
@property(nonatomic, copy) NSString *name;
// 当调用上面的copy的时候,等价于下面的代码
- (void)setName:(NSString *)name {
if (_name != name) {
[_name release];
_name = [name copy];
}
}
当使用 strong 修饰属性的时候,属性的setter方法会直接强引用该对象,
这样,当原object对象的值发生改变时,新对象的属性也改变;
例如:我们平时使用strong修饰的NSMutableArray,这个可变数组在当前文件中只有一个,而且是可变的;
/** 数组 */
@property(nonatomic,strong)NSMutableArray *array;
`
`
`
// 当调用上面的strong的时候,等价于下面的代码
-(void)setArray:(NSMutableArray *)array{
_array = array;
}
GCD的具体运用
- 同步/异步 + 串行/并发队列的组合
- 延迟执行(dispatch_after)
- 只执行一次(dispatch_once)
- 快速遍历(dispatch_apply)
- 创建线程群组
开启多条线程,去执行群组中的任务,当群组内的三个任务执行完毕后,再去执行notify里面的任务
- 创建屏障线程队列
会优先执行屏障前面的任务,当屏障前的所有任务执行完毕后,再去执行后面的任务
- 创建屏障线程队列