iOS知识点解答

2016-12-03  本文已影响135人  桃逸

随身带上mac与源码进行学习与介绍

参考:
http://www.infocool.net/kb/IOS/201609/185104.html
http://www.infocool.net/kb/IOS/201609/185061.html

属性
函数直接调用与performSelector的区别

本事都是发送消息调用一个方法;
直接调用编译区间如果不存在会报错,performSelector不会报错
performSelector可以调用运行时动态进入的method,但是如果调用不存的selector会报unrecognized selector sent to instance导致crash

isKindOfClass 与 isMemberOfClass的区别

isKIndOfClass 返回一个实例是否是一个类或者其继承类;
isMemberOfClass 返回一个实例是否是一个类,不包括其继承类;

iOS object 原理?

What this says is: any structure which starts with a pointer to a Class
structure can be treated as an objc_object.

一个OC的类其实也是一个对象;

typedef struct objc_class *Class;

@interface NSObject <NSObject> {
    Class isa  OBJC_ISA_AVAILABILITY;
}

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

可以看出,每一个类对象中都有一个方法列表,方法列表中记录着方法的名称,实现及参数类型,其实selector本质就是方法名称,通过这个方法名称就可以再方法列表中找到对应的方法实现;

@property后面可以有哪些修饰符?

readwrite, atomic, assign是默认修饰;
--> 读写属性:readwrite readonly
--> setter属性:assign retain copy weak strong
--> 原子属性:atomic nonatomic
--> getter/setter修饰符:@property (setter=setName, getter=getName) NSString *name;
参考:Apple 官方文档说明

消息转发流程
hitTest / pointInside

先调用hitTest检查窗口是否响应事件,然后调用pointInside检测是否在当前窗口内;

hitTest:withEvent:在内部首先会判断该视图是否能响应触摸事件,如果不能响应,返回nil,表示该视图不响应此触摸事件。然后再调用pointInside:withEvent:(该方法用来判断点击事件发生的位置是否处于当前视图范围内)。如果pointInside:withEvent:返回NO,那么hiteTest:withEvent:也直接返回nil。
如果pointInside:withEvent:返回YES,则向当前视图的所有子视图发送hitTest:withEvent:消息,所有子视图的遍历顺序是从最顶层视图一直到到最底层视图,即从subviews数组的末尾向前遍历。直到有子视图返回非空对象或者全部子视图遍历完毕;

一个触摸事件 多个响应者同时处理该事件
  • (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchBegan---%@", [self class]);
    [super touchesBegan:touches withEvent:event];
    }
怎么用copy关键字?

copy的使用比较智能:
假若一个对象是不可变的,copy返回的是自身,计数器加1;
假若是可变的对象,那么是内存拷贝,返回的是不可变对象;
使用案例:
@property (nonatomic, copy) NSString *pStr;
如果设置这个变量的属性为strong,那么如果外部赋值给它的对象是mutable string,外部mutable string改变的话,这个变量也会跟着变化;此时要使用copy属性,外部mutable string变化也不会影响当前变量;
所以使用NSString属性时候最好声明为copy而不是strong,否则可能外部导致变量内容发生变化;

When you declare a NSString property it is best to use copy instead of strong. In fact this is true for any immutable class that conforms to the NSCopying protocol like NSNumber, NSArray, NSSet and others. All these classes I mentioned also have a mutable version. You want to use copy because your NSString property can be passed either a NSString or a NSMutableString instance. If you’re being passed a NSMutableString instance then that means the value of your string may change behind your back. Let’s consider this example:

如何让自己的类用copy修饰符?如何重写带copy关键字的setter?

重写带copy关键字的setter只需要在setter函数里调用对象的copy即可;
若想要自己所写的对象具有拷贝功能,需要实现NSCopying协议,有必要也实现NSMutableCopying协议;NSCopying的协议方法为copyWithZone,内容实现为:

- (id)copyWithZone:(NSZone *)zone {
// 需调用allocWithZone
MyClass *copy = [[self class] allocWithZone:zone];
// copy class中的属性数据等
return copy;
}
PS: copy定义在NSObject中,要实现NSCopying协议才能调用,copy的文档说明如下:
This is a convenience method for classes that adopt the NSCopying protocol. An exception is raised if there is no implementation for copyWithZone:.
NSObject does not itself support the NSCopying protocol. Subclasses must support the protocol and implement the copyWithZone: method.

property的本质是什么?

@property = ival + getter + setter, 由编译器自动生成;
property的只是给编译器看的一种指令,可以帮助我们管理引用计数器,可以编译之后为你生成ivar变量以及响应的getter与setter方法;如果指定了retain/copy/assign,也会做出相应处理;

protocol与category中如何使用@property

protocol中定义了属性,说明需要代理实现setter与getter方法,否则会报unrecognized selector错误;
category中使用属性,需要使用runtime函数set或者get变量:

- (NSString *)name {
objc_getAssociateObject(self, @"name");
}
- (void)setName:(NSString *)str {
objc_setAssociateObject(self, @"name", str,
OBJC_ASSOCIATION_COPY_NONATOMIC);
}

runtime如何实现weak?

参考:《objc高级编程》
当我们初始化一个weak变量时,runtime会调用objc_initWeak函数将weak变量存储在weak表中, key是weak赋值对象的内存地址;
weak表:一个弱引用表,实现为一个weak_table_t结构体,存储了对象相关的所有的弱引用信息,weak_entries成员变量负责维护和存储指向一个对象的所有弱引用hash表;

对象释放流程如下:
1.调用objc_release;
2.计数器变为0,执行dealloc;
3.在dealloc中,调用_objc_rootDealloc函数;
4.在_objc_rootDealloc中,调用了object_dispose函数;
5.调用objc_destructInstance;
6.最后调用objc_clear_deallocating -->
objc_clear_deallocating这个函数首先找出对象的weak_entry_t链表,然后挨个将弱引用置为nil,最后清理对象的记录;

load 与 initialize

PS:在Compile Sources中,文件的排放顺序就是起装载顺序,自然也就是load方法调用的顺序;
initialize方法是在第一次给某个类发送消息时调用,并且只会调用一次;


Paste_Image.png
UITableView优化?

UITableView原理
UITableViewCell的重用机制能够提高cell的使用效率,减少了内存消耗;
UITableview是先计算cell的高度确定将要显示的cell(所有cell的height都会刷新),再显示cell(只刷新显示的cell),所以主要优化在 tableView:heightForRowAtIndexPath 与 tableView:cellForRowAtIndexPath 方法;
heightForRowAtIndexPath是调用最频繁的方法;

//异步绘制
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        CGRect rect = [_data[@"frame"] CGRectValue];
        UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0);
        CGContextRef context = UIGraphicsGetCurrentContext();
        //整个内容的背景
        [[UIColor colorWithRed:250/255.0 green:250/255.0 blue:250/255.0 alpha:1] set];
        CGContextFillRect(context, rect);
       //内容如果是图文混排,就添加View,用CoreText绘制
       //图文混排,可以查阅Google,研究下CoreText,内容比较多
       [self drawText];
}
GCD 任务控制?

Mac OS X 10.6, iOS4 以上可以使用;

Core Data 操作及多线程处理

CoreData实际上是对SQLite的封装,提供了更高级的持久化方式;
CoreData操作简单方便,但是存储性能一般,批处理数据不好,而且对于多线程的支持也不太好;
Core Data 堆栈
对象图管理
持久化

参考:
Apple CoreData
Core Data 概述
一个完整的Core Data应用
objc.io core-data
ios8 swift core data tutorial

NSOperation 自定义?

参见AFNetWorking的 AFHTTPRequestOperation.h
重写 main 函数:处理耗时操作后,返回回调处理;

运行时添加变量?

不能向编译后得到的类中增加实例变量,能向运行时创建的类中添加实例变量;
because:

runloop与线程?

runloop是为了线程而生,没有线程就没有存在的必要;内部是一个do while循环类似的结构,比如一个event消息事件处理线程;

  1. 主线程的runloop默认是启动的;
  2. 其他线程,runloop默认是没有启动的,如果需要更多的线程交互可以手动配置和启动,只是执行一个长时间的已确定任务则不需要;
  3. 任何一个cocoa程序的线程中,都可以通过 [NSRunLoop currentRunLoop] 获取到当前线程的runloop;
    《Objective-C之run loop详解》
    《深入理解RunLoop》

runloop的mode作用?
mode主要用来指定事件在运行循环中的优先级;

autoreleasepool
autoreleas对象释放机制?
autoreleasepool的实现:

主要通过三个函数:

  1. objc_autoreleasepoolPush
  2. objc_autoreleasepoolPop
  3. objc_autorelease
    《黑幕背后的Autorelease》
BAD_ACCESS发生在什么情况?
block内修改外部变量

原则:block不允许修改外部变量的值,是指占中指针的内存地址;栈区是红灯区不可修改,堆区才是绿灯区可修改
使用__block修饰外部变量,实际上是把变量从栈区修改到堆区中了,可使用例子验证:

__block int a = 1;
NSLog(@"%p", &a); // 在栈区
void (^foo)(void) = ^ {
a = 2;
NSLog(@"%p", &a); //在堆区 1
};
NSLog(@"%p", &a); //在堆区 2
foo();

如何手动触发KVO
当你观察一个对象时,一个新的类会被动态创建。
这个类继承自该对象的原本的类,并重写了被观察属性的 setter 方法;
重写的 setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象:值的更改;
最后通过 isa 混写(isa-swizzling)把这个对象的 isa 指针 
( isa 指针告诉 Runtime 系统这个对象的类是什么 ) 
指向这个新创建的子类,对象就神奇的变成了新创建的子类的实例;

键值观察通知依赖于NSObject的两个方法:willChangeValueForKey和didChangeValueForKey;
系统会在setValue(成员变量赋值)或者setter(属性赋值)中以某种方法在中间插入wilChangeValueForKey:
、 didChangeValueForKey:
和 observeValueForKeyPath:ofObject:change:context:
的调用;
什么方式?通过isa-swizzling;
Manual Change Notification---Apple 官方文档

IBOutlet连出来的视图属性为什么可以被设置成weak?

Should IBOutlets be strong or weak under ARC?
视图本身已经对它有一个强引用了;

如何调试BAD_ACCESS?zombie object

iOS Debugging Magic

  1. Enable Zombie Objects;
  1. 全局断点开启;
  2. xcode7的 Address Sanitizer;
  3. 重写object的respondsToSelector方法,显示出现bad access前最后访问的一个object;
LLVM原理及优化?

LLVM:Low Level Virtual Machine 底层虚拟机
LLVM是架构编译器的框架系统,以C++编写而成,用于优化以任意程序语言编写的程序的编译时间、链接时间、运行时间及空闲时间,对开发者保值开放;LLVM计划启动于2000年,2006年加盟Apple Inc;Apple也是LLVM计划的主要资助者;
Clang是LLVM的一个编译器前端,它目前支持C/C++/Object-C以及Object-C++等变成余元;clang对源程序进行词法分析和语义分析,并将分析结果转换为抽象语法树,最后使用LLVM作为后端代码生成器;

meituan 面试部分
APP跳转

调用openUrl跳转到指定app;

后台持续运行机制

多米音乐播放器会持续运行
可以持续运行的是:音乐播放、GPS定位服务、voip、后台下载、fetch;

stackoverflow 问题
上一篇下一篇

猜你喜欢

热点阅读