iOS面试系列6

父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。
深拷贝同浅拷贝的区别:浅拷贝是指针拷贝,对一个对象进行浅拷贝,相当于对指向对象的指针进行复制,产生一个新的指向这个对象的指针,那么就是有两个指针指向同一个对象,这个对象销毁后两个指针都应该置空。深拷贝是对一个对象进行拷贝,相当于对对象进行复制,产生一个新的对象,那么就有两个指针分别 指向两个对象。当一个对象改变或者被销毁后拷贝出来的新的对象不受影响。
 
实现深拷贝需要实现 NSCoying 协议,实现 - ( id )copyWithZone:(NSZone *)zone 方法。当对一个 property 属性含有 copy 修饰符的时候,在进行赋值操作的时候实际上就是调用这个方法。
 
父类实现深拷贝之后,子类只要重写 copyWithZone 方法,在方法内部调用父类的 copyWithZone 方法,之后实现自己的属性的处理
 
父类没有实现深拷贝,子类除了需要对自己的属性进行处理,还要对父类的属性进行处理。
 
KVO NSNotification delegate block 区别
• KVO 就是 cocoa 框架实现的观察者模式,一般同 KVC 搭配使用,通过 KVO 可以监测一个值的变化,比如 View 的高度变化。是一对多的关系,一个值的变化会通知所有的观察者。
 
• NSNotification 是通知,也是一对多的使用场景。在某些情况下, KVO NSNotification 是一样的,都是状态变化之后告知对方。 NSNotification 的特点,就是需要被观察者先主动发出通知,然后观察者注册监听后再来进行响应,比 KVO 多了发送通知的一步,但是其优 点是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听,监听范围广,使用也更灵活。
 
• delegate 是代理,就是我不想做的事情交给别人做。比如狗需要吃饭,就通过 delegate 通知主人,主人就会给他做饭、盛饭、倒水,这些操作,这些狗都不需要关 心,只需要调用 delegate (代理人)就可以了,由其他类完成所需要的操作。所以 delegate 是一对一关系。
 
• block delegate 的另一种形式,是函数式编程的一种形式。使用场景跟 delegate 一样,相比 delegate 更灵活,而且代理的实现更直观。
 
• KVO 一般的使用场景是数据,需求是数据变化,比如股票价格变化,我们一般使用 KVO (观察者模式)。 delegate 一般的使用场景是行为,需求是需要别人帮我做一件事情,比如买卖股票,我们一般使用 delegate
 
Notification 一般是进行全局通知,比如利好消息一出,通知大家去买入。 delegate 是强关联,就是委托和代理双方互相知道,你委托别人买股票你就需要知道经纪人, 经纪人也不要知道自己的顾客。 Notification 是弱关联,利好消息发出,你不需要知道是谁发的也可以做出相应的反应,同理发消息的人也不需要知道 接收的人也可以正常发出消息。
 
将一个函数在主线程执行的 4 种方法
• GCD 方法,通过向主线程队列发送一个 block 块,使 block 里的方法可以在主线程中执行。
dispatch_async(dispatch_get_main_queue(), ^{
    需要执行的方法
});
 
• NSOperation 方法
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];  主队列
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    需要执行的方法
}];
[mainQueue addOperation:operation];
 
• NSThread 方法
[ self performSelector: @selector (method) onThread:[NSThread mainThread] withObject: nil waitUntilDone: YES modes: nil ];
[ self performSelectorOnMainThread: @selector (method) withObject: nil waitUntilDone: YES ];
[[NSThread mainThread] performSelector: @selector (method) withObject: nil ];
 
• RunLoop 方法
[[NSRunLoop mainRunLoop] performSelector: @selector (method) withObject: nil ];
 
  如何让计时器调用一个类方法
计时器只能调用实例方法,但是可以在这个实例方法里面调用静态方法。
使用计时器需要注意,计时器一定要加入 RunLoop 中,并且选好 model 才能运行。 scheduledTimerWithTimeInterval 方法创建一个计时器并加入到 RunLoop 中所以可以直接使用。
如果计时器的 repeats 选择 YES 说明这个计时器会重复执行,一定要在合适的时机调用计时器的 invalid 。不能在 dealloc 中调用, 因为一旦设置为 repeats yes ,计时器会强持有 self ,导致 dealloc 永远不会被调用,这个类就永远无法被释放。比如可以在 viewDidDisappear 中调用,这 样当类需要被回收的时候就可以正常进入 dealloc 中了。
[NSTimer scheduledTimerWithTimeInterval:1 target: self selector: @selector (timerMethod) userInfo: nil repeats: YES ];
-( void )timerMethod
{
    调用类方法
    [[ self class ] staticMethod];
}
-( void )invalid
{
    [timer invalid];
    timer = nil ;
}
 
如何重写类方法
• 1 、在子类中实现一个同基类名字一样的静态方法
• 2 、在调用的时候不要使用类名调用,而是使用 [ self class ] 的方式调用。原理,用类名调用是早绑定,在编译期绑定,用 [ self class ] 是晚绑定,在运行时决定调用哪个方法。
 
NSTimer 创建后,会在哪个线程运行。
scheduledTimerWithTimeInterval 创建的,在哪个线程创建就会被加入哪个线程的 RunLoop 中就运行在哪个线程
自己创建的 Timer ,加入到哪个线程的 RunLoop 中就运行在哪个线程。
 
id NSObject *的区别
id 是一个 objc_object 结构体指针,定义是 typedef struct objc_object * id
id 可以理解为指向对象的指针。所有 oc 的对象 id 都可以指向,编译器不会做类型检查, id 调用任何存在的方法都不会在编译阶段报错,当然如果这个 id 指向的对象没有这个方法,该崩溃还是会崩溃的。
• NSObject * 指向的必须是 NSObject 的子类,调用的也只能是 NSObjec 里面的方法否则就要做强制类型转换。
不是所有的 OC 对象都是 NSObject 的子类,还有一些继承自 NSProxy NSObject * 可指向的类型是 id 的子集。
以下内容后续补充
 
iOS 核心框架
• CoreAnimation
• CoreGraphics
• CoreLocation
• AVFoundation
• Foundation
 
iOS 核心机制
• UITableView 重用
• ObjC 内存管理;自动释放池, ARC 如何实现
• runloop
• runtime
• Block 的定义、特性、内存区域、如何实现
• Responder Chain
• NSOperation
 
• GCD
数据结构
• 8 大排序算法
二叉树实现
二分查找实现
 
面向对象编程
封装、继承、多态
设计模式 6 个原则
设计一个类的功能,如何划分粒度(单一职责)
接口隔离。
如果有一个鸟类,有飞的动作,一个鸵鸟继承它是合适的吗(里氏替换)
类之间的依赖如何依赖偶合度最小(依赖倒转)
高层依赖低层,低层不能依赖高层。依赖接口,不能依赖具体的类。
如果 A 要调用 C 函数,但 C B 的成员类,应该如何设计?(迪米特 法则
如何设计类,能做到只增加代码,而不修改代码,有哪些经验(开放封闭)
通过设计模式解决。
 
计算机技术
计算机网络: TCP/IP HTTPCDN SPDY
计算机安全: RSA AES DES
操作系统:线程、进程、堆栈、死锁、调度算法
 
iOS 新特性、新技术
• iOS7 UIDynamic SpritKit 、新布局、扁平化
• iOS8 应用程序扩展、 HealthKit SceneKit CoreLocation TouchID PhotoKit
• iOS9
• Apple Watch
 
第三方库: SDWebImage AFNetwork JSONKit wax
 

 
简述 OC 中内存管理机制 .
: 内存管理机制 : 使用引用计数管理 , 分为 ARC MRC,MRC 需要程序员自己管理内存 ,ARC 则不需要 . 但是并不是所有对象在 ARC 环境下均不需要管理内存 , 子线程和循环引用并不是这样 . retain 配对使用的是 release,retain 代表引用计数 +1,release 代表引用计数 -1, 当引用计数减为 0 , 对象则被系统自动销毁 . alloc 配对使用的是 dealloc,alloc 代表为对象开辟内存空间 ,dealloc 则代表销毁对象的内存空间 .
 
2. readwrite,readonly,assign,retain,copy,nonatomic,atomic,strong,weak 的作用 ?
: 读写属性 :readonly readwrite;  语义属性 :assign/retain/copy;   原子性 :nonatomic.
 
.readwrite 代表可读 , 可写 , 即有 setter getter 方法 , 是默认属性 .readonly 代表只可读 , 即只有 get 方法 , 因为不会生成 setter 方法 , 所以它不可以和 copy/retain/assign 组合使用 .
 
.weak assign 均是弱引用 ,assign 修饰基本数据类型 ,weak 修饰对象类型 .strong weak 用于 ARC (ARC 下的代理使用 weak,block 块使用 copy).strong 相当于 retain.weak 相当于 assign;assign/retain/copy 这些属性用于指定 set 访问器的语义 , 也就是说 , 这些属性决定了以何种方式对数据成员赋值 .
 
assign, 直接赋值 , 引用计数不改变 , 适用于基本数据类型 .
 
retain, 浅拷贝 , 使用的是原来的内存空间 , 只能适用于 Objective-C 对象类型 , 而不能适用于 Core Foundation 对象 (retain 会增加对象的引用计数 , 而基本数据和 Core Foundation 对象都没有引用计数 ).
 
copy: 对象的拷贝 , 新申请一块内存空间 , 并把原始内容复制到那片空间 . 新对象的引用计数为 1, 此属性只对那些遵循了 NSCopy 协议的对象类型有效 .
 
.nonatomic, 非原子性访问 , 不加同步 , 是异步操作 . 默认为 atomic, 原子操作 ,atomic Objc 使用的一种线程保护技术 , 基本上来讲 , 是防止在写未完成的时候被另外一个线程读取 , 造成数据错误 , 而这种机制是消耗系统内存资源的 , 所以在移动端 , 都选择 nonatomic.
 
3. 内存分为 5 个区 , 分别是栈区 , 堆区 , 全局区 , 文字常量区 , 程序代码区 .
 
栈区 : 由编译器自动分配释放 , 不需要管理内存 .
堆区 : 一般有程序员分配释放 .
全局区 : 存放全局变量和静态变量 .
常量区 : 存放常量字符串 .
代码区 : 存放二进制代码 .
 
3. 类变量的 @protected,@private,@public,@package, 声明各有什么含义 ?
@protected 受保护的 . 本类 , 子类可见 .
@private 私有的 , 类内可用
@public 公有的 , 类内 , 子类 , 外部均可用
@package 可见度在 @protected @public 之间 , 这个类型最常用于框架类的实例变量 .
 
4. 线程是什么 ? 进程又是什么 ? 区别和联系 .
进程 : 正在运行的程序 , 负责程序的内存分配 .
线程 : 线程是进程中一个独立执行的控制单元 ( 路径 ), 一个进程至少包含一条线程 , 即主线程 .
创建线程的目的 : 开辟一条新的执行路径 , 运行指定的代码 , 与主线程的代码实现同时执行 .
 
5. 对多线程开发的理解 ,iOS 中有几种实现多线程的方式 .
多线程的使用场景 : 防止卡顿 , 可以同时完成多个任务 , 且不影响主线程 , 把耗时操作放在子线程中执行 , 但是会消耗内存 .
实现多线程的方式 :
.NSThread( 内存需要自己管理 . 触发 ),
.NSOperationQueue( 不再关注线程 , 当前可执行任务个数 queue.maxConcurrentOperationCount)
.GCD
Theard
 
详解三种实现多线程的方式:
GCD:
 
GCD 里面包含了串行队列、并行队列、主队列、全局队列。
 
Dispatch_queue_t q = dispatch_queue_create(“qqq”,DISPATCH_QUEUE_SERIAL); 创建一个串行队列
 
Dispatch_sync(q,^{
    
}); 开启同步任务
 
Dispatch_async(q,^{
    
}) ; 开启异步任务
 
并行队列: DISPATCH_QUEUE_CONCURRENT
 
主队列: dispatch_queue_t q = dispatch_get_main_queue();
 
全局队列: dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
NSThread
 
获取当前线程: NSThread * current = [NSThread currentThread];
 
获取主线程: NSThread * main = [NSThread mainThread];
 
使用 NSThread 创建线程的两种方式:
 
- ( id )initWithTarget:( id )target selector:( SEL )selector object:( id )argument;
 
+ ( void )detachNewThreadSelector:( SEL )selector toTarget:( id )target withObject:( id )argument;
 
暂停当前线程:
 
[NSThread sleepForTimeInterval:2];
NSOperationQueue
 
创建一个操作队列: NSOperationQueue * queue = [[NSOperationQueue alloc]init];
 
添加 NSOperation NSOperationQueue 中: [queue addOperation:operation];
 
添加一组 operation [queue addOperations:operations waitUntilFinished: NO ];
 
添加一个 block 形式的 operation [queue addOperationWithBlock:^(){
    
}];
 
添加 NSOperation 的依赖对象: [operation2 addDependency:operation1];
 
设置队列的最大操作数: [queue setMaxConcurrentOperationCount:1];
 
等待 options 完成: [operation waitUntilFinished];
 
暂停、继续 queue:[queue setSuspended: YES ] [queue setSuspend: NO ]
 
6. 线程同步和异步的区别 ?ios 中如何实现线程的同步 ?
 
同步 : 任务顺序执行 , 下一个任务依赖于上一任务的完成 .
 
异步 : 任务执行顺序不定 , 一起执行 .
 
实现 : 设置依赖 :NSOpreationQueue  GCD 中的串行队列 .
 
7. iOS 类是否可以多继承 , 如果没有 , 怎么实现 ?
 
不可以多继承 . 可以通过类目 , 延展 , 协议实现多继承 .
 
类目 : 类目也叫分类 , 英文 category, 在没有原类 .m 文件的基础上 , 给该类添加方法 . 类目里不能添加实例变量 , 不能添加和原始类方法名相同的方法 , 否则会发生覆盖 . 一个类可以添加多个类目 , 类目中的方法可以成为原始类的一部分 , 和原始类方法级别相同 , 可以被子类继承 .
 
延展 :Extension, 是一种特殊形式的类目 , 主要是在一个类的 .m 里面声明与实现 . 作用 : 就是给某类添加私有方法或者私有变量 .
 
虽然延展是给一个类定义私有方法 , 但是 OC 没有绝对的私有方法 , 其实还是可以调用的 , 延展里面声明的变量只能在该类内部使用 , 外界访问不了 . 如果是新建文件建的的某类延展 .h 文件 , 则不能添加实例变量 , 如果括号里没有类目名 , 则认为延展里面的方法为全都必须实现 , 如果有 , 则可选实现 .
 
类目写的方法必须实现 , 延展写的方法非必须 .
 
8. 栈和堆的区别 ?
: 内存系统管理 ( 系统开辟 , 系统释放 ), 先进后出 .
: 内存自己管理 ( 自己开辟 , 自己释放 ). 先进先出 .
 
9. iOS 本地数据存储都有几种方式 ?
.NSkeyedArchiver: 采用归档的形式来保存数据 , 该数据对象需要遵守 NSCoding 协议 , 并且该对象对应的类必须提供 encodeWithCoder: initWithCoder: 方法 . 前一个方法告诉系统怎么对对象进行编码 , 而后一个方法则是告诉系统怎么对对象进行解码 .
 
.NSUserDefaults: 用来保存应用程序设置和属性 , 用户保存的数据 . 用户再次打开程序或者开机后这些数据仍然存在 .NSUserDefaults 可以存储的数据类型包括 :NSData,NSString,NSNumber,NSDate,NSArray.NSDictionary, 其他类型的数据需要先行转换 .
 
.Write 写入方式 : 永久保存在磁盘中 . 具体 :a. 获得文件保存的路径 .b. 生成该路径下的文件 ,c, 往文件中写入数据 .d. 从文件中读出数据 .
 
.SQLite: 采用 SQLite 数据库来存储数据 ,SQLite 作为一种轻量级数据库 . 具体 :a. 添加 SQLite 相关的库以及头文件 ,b. 使用数据库存数数据 : 打开数据库 , 编写数据库语句 , 执行 , 关闭数据库 . : 写入数据库 , 字符串可以采用 char 方式 , 而从数据库中取出 char 类型 , char 类型有表示中文字符时 , 会出现乱码 , 这是因为数据库默认使用 ascII 编码方式 , 所以想要正确从数据库中取出中文 , 需要使用 NSString 来接受从数据库取出的字符串 .
 
.CoreData: 原理是对 SQLite 的封装 , 开发者不需要接触 sql 语句 , 就可以对数据库进行操作 .
 
10. ios 动态类型和动态绑定
多态 : 父类指针指向子类对象 .
动态类型 : 只有在运行期 , 才能确定其真正类型 .
动态加载 : 根据不同的条件 , 加载不同的资源 .32 64 .
 
11. 深拷贝和浅拷贝的理解 .
深拷贝 ; 拷贝的内容 .
浅拷贝 : 拷贝的指针 .
 
深拷贝如 :
NSMutableDictionary  * dic = [@{} mutableCopy];
NSMutableArray  * ary = [@[] mutableCopy];
 
12. 怎么实现一个 单例 的类 .
 
单例是一种设计模式 , 对象只有一个 . 缺点 : 对象不会被释放 , 如果创建很多的话会占用很多内存 , 优点 : 可以当做工具类使用 .
 
static SortDetailsModelDown * single = nil ;
 
+(SortDetailsModelDown *)shareSortDetailsModelDown{
    
    @synchronized ( self ){
        
        if (!single) {
            
            single = [[SortDetailsModelDown alloc]init];
            
        }
        
    }
    
    return single;
    
}
 
13. 什么是安全释放 ?
先释放再置空 .
 
14. RunLoop 是什么 ?
事件循环 , 是线程里面的一个组件 . 主线程的 RunLoop 是自动开启的 . 分为 : 计时源 (timer source), 事件源 ( 输入源 ):input source. 防止 CPU 中断 ( 保证程序执行的线程不会被系统终止 ).
 
Runloop 提供了一种异步执行代码的机制 , 并不能并行执行任务 , 是事件接收和分发机制的一个实现 . 每一个线程都有其对应的 RunLoop, 但是默认非主线程的 RunLoop 是没有运行的 , 需要为 RunLoop 添加至少一个事件源 , 然后 run .
 
一般情况下我们是没有必要去启动线程的 RunLoop , 除非你在一个单独的线程中需要长时间的检测某个事件 .
 
RunLoop, 正如其名所示 , 是线程进入和被线程用来响应事件以及调用事件处理函数的地方 .
 
input source 传递异步事件 , 通常是来自其他线程和不同程序的消息 .
 
timer source 传递同步事件 .
 
当有事件发生时 ,RunLoop 会根据具体的事件类型通知应用程序作出响应 .
 
当没有事件发生时 ,RunLoop 会进入休眠状态 , 从而到达省电的目的 .
 
当事件再次发生时 ,RunLoop 会被重新唤醒 , 处理事件 .
 
一般在开发中很少会主动创建 RunLoop, 而通常会把事件添加到 RunLoop .
 
15. 什么是序列化和反序列化 , 可以用来做什么 ? 如何在 OC 中实现复杂对象的存储 .
序列化和反序列化 : 归档和反归档 , 进行本地化 , 进行数据存储 .
CoreData: 数据托管 . 有四种存储方式 :xml,sqlite, 二进制 , 内存 .
遵循 NSCoding 协议之后 , 进行归档即可实现复杂对象的存储 .
 
16. 写一个标准宏 MIN, 这个宏输入两个参数并返回较小的一个 .
#define MIN(A,B) (A)>(B)?(B):(A)
 
17. iPhone OS 有没有垃圾回收机制 , 简易阐述一下 OC 内存管理 .
木有 . 引用计数 ,ARC MRC,swift( 自动引用计数 ).
 
18. 简述应用程序按 HOME 键进入后台时的生命周期 , 以及从后台进入前台时的生命周期 .
前者 :- ( void )applicationWillResignActive:(UIApplication *)application
- ( void )applicationDidEnterBackground:(UIApplication *)application
 
后者 :- ( void )applicationWillEnterForeground:(UIApplication *)application
- ( void )applicationDidBecomeActive:(UIApplication *)application
 
:
各个程序运行状态时代理的回调:
 
- ( BOOL )application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 
告诉代理进程启动但还没进入状态保存
 
- ( BOOL )application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 
告诉代理启动基本完成程序准备开始运行
 
- ( void )applicationWillResignActive:(UIApplication *)application
 
当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,比如来电话了
 
- ( void )applicationDidBecomeActive:(UIApplication *)application
 
当应用程序入活动状态执行,这个刚好跟上面那个方法相反
 
- ( void )applicationDidEnterBackground:(UIApplication *)application
 
当程序被推送到后台的时候调用。所以要设置后台继续运行,则在这个函数里面设置即可
 
- ( void )applicationWillEnterForeground:(UIApplication *)application
 
当程序从后台将要重新回到前台时候调用,这个刚好跟上面的那个方法相反。
 
- ( void )applicationWillTerminate:(UIApplication *)application
 
当程序将要退出是被调用,通常是用来保存数据和一些退出前的清理工作。这个需要要设置 UIApplicationExitsOnSuspend 的键值。
 
- ( void )applicationDidFinishLaunching:(UIApplication*)application
 
当程序载入后执行
 
在上面 8 个方法对应的方法中键入 NSLog 打印。
 
现在启动程序看看执行的顺序:
 
启动程序
 
lifeCycle[40428:11303] willFinishLaunchingWithOptions
 
lifeCycle[40428:11303] didFinishLaunchingWithOptions
 
lifeCycle[40428:11303] applicationDidBecomeActive
 
按下 home
 
lifeCycle[40428:11303] applicationWillResignActive
 
lifeCycle[40428:11303] applicationDidEnterBackground
 
双击 home 键,再打开程序
 
lifeCycle[40428:11303] applicationWillEnterForeground
 
lifeCycle[40428:11303] applicationDidBecomeActive
 
19. ViewController
alloc,loadView,viewDidLoad,viewWillAppear,viewDidUnload,dealloc,init 分别是在什么时候调用 ? 在自定义 ViewController 的时候这几个函数里面应该做什么工作 ?
 
alloc: 申请内存时调用 .
 
loadView: 加载视图时调用 .
 
viewDidLoad; 视图已经加载后调用 .
 
viewWillAppear: 视图将要出现时调用 .
 
dealloc: 销毁该视图时调用 .
 
init; 初始化该视图时调用 .
 
20. 描述应用程序的启动顺序 .
a. 程序入口 main 函数创建 UIApplication 实例和 UIApplication 代理实例 .
 
b. UIApplication 代理实例中重写启动方法 , 设置根 ViewController
 
c. 在第一 ViewController 中添加控件 , 实现应用程序界面 .
 
21. 为什么很多内置类如 UITableViewControl delegate 属性都是 assign 而不是 retain?
防止循环引用 .
 
: 对象 A 引用了对象 B, 对象 B 引用了对象 C, 对象 C 引用了对象 B, 这个时候 B 的引用计数是 2, C 的引用计数是 1, A 不再使用 B 的时候 , 就释放了 B 的所有权 , 这个时候 C 还引用对象 B, 所以 B 不会释放 , 引用计数为 1, 因为 B 也引用着对象 C,B 不释放 , 那么 C 也就不会被释放 , 所以他们的引用计数都为 1, 并且永远不会被释放 , 形成了循环引用 .
 
22. 使用 UITableView 的时候必须要实现的几种方法 ?
2 个数据源方法 . 分别是 :
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
 
23. 写一个遍历构造器 .
 
+( id )leftModelWith{
    
    leftModel * model = [ self alloc]init];
    
    return model;
    
}
 
24. UIImage 初始化一张图片有几种方法 ? 简述其特点 ?
3 ,
imageNamed: 系统会先检查系统缓存中是否有该名字的 image, 如果有的话 , 则直接返回 , 如果没有 , 则先加载图像到缓存 , 然后再返回 .
 
initWithContentsOfFile: 系统不会检查缓存 , 而直接从文件系统中记载并返回 .
 
imageWithCGImage:scale:orientation scale= 1 的时候图像为原始大小 ,orientation 指定绘制图像的方向 .
 
25. person retainCount , 并解释为什么 ?
 
Person * per = [Person alloc]init];
 
self .person = per;
 
1 或者 2. person 是什么类型修饰的 .
 
alloc+1,assign+0,retain+1.
 
26. 下面这段代码有何问题 ?
 
@implementation Person
 
- ( void )setAge:( int )newAge {
    
    self .age = newAge;
    
}
 
@end
 
死循环
 
27.     这段代码有什么问题 , 如何修改
for ( int i = 0; i < someLargeNumber; i++) {
    
    NSString *string = @”Abc”;
    
    string = [string lowercaseString];
    
    string = [string stringByAppendingString: @"xyz" ];
    
    NSLog(@“%@”, string);
    
}
 
加入自动释放池 @autoreleasepool {};
 
for ( int i = 0; i < someLargeNumber; i++) {
    
    @antoreleasepool {
        
        NSString *string = @”Abc”;
        
        string = [string lowercaseString];
        
        string = [string stringByAppendingString: @"xyz" ];
        
        NSLog(@“%@”, string);
        
    }
    
}
 
28. 截取字符串 "20 | http://www.baidu.com" 中, "|" 字符前面和后面的数据,分别输出它们
 
[ "20 | http://www.baidu.com " componentSeparatedByString: @"|" ];
 
29. obj-c 写一个冒泡排序 .
 
NSMutableArray *ary = [@[ @"1" , @"2" , @"3" , @"4" , @"6" , @"5" ] mutableCopy];
 
for ( int i = 0; i < ary.count - 1; i++) {
    
    for ( int j = 0; j < ary.count - i - 1; j++) {
        
        if ([ary[j] integerValue] < [ary[j + 1] integerValue]) {
            
            [ary exchangeObjectAtIndex:j withObjectAtIndex:j + 1];
            
        }
        
    }
    
}
 
NSLog( @"%@" , ary);
 
30. 简述对 UIView.UIWindow CALayer 的理解 .
UIWindow 是应用的窗口 , 继承于 UIResponder.
 
UIView 继承于 UIView, 是创建窗口中的一个视图 , 可以响应交互事件 . 一个程序只有一个主 window, 可以有多个 window.
 
CALayer 图层 , 一个 view 可有多个图层 , 不可以响应事件 .
 
31. 写一个完整的代理 , 包括声明 , 实现 .
代理 : 遵守协议的对象 .
 
@class MyView;
 
第一步 : 指定协议 :( 协议名 : 类名 +Delegate)
 
@protocol MyViewDelegate <NSObject>
 
@required
 
-( void )changeViewBackgroudColor:(MyView *)view;
 
@optional
 
-( void )test;
 
@end
 
@interface MyView : UIView
 
第二步 : 指定代理
 
@property ( nonatomic , assign ) id <MyView> delegate;
 
@end
 
第三步 : 代理遵循协议 .
 
第四步 : 代理实现协议里面的必须实现的方法和其他可选方法 .
 
第五步 : 委托方通知代理开始执行方法 .
 
32. 分析 json.xml 的区别 , 底层如何实现 ?
Json: 键值对 . 数据小 , 不复杂 . 便于解析 , 有框架支持 , 适合轻量级传输 . 作为数据包个数传输的时候效率更高 .
 
xml: 标签套内容 .xml 数据两较大 , 比较复杂 . 适合大数据量的传输 .xml 有丰富的编码工具 , 比如 :Dom4j,JDom. 解析方式有两种 , 一是通过文芳模型解析 , 另外一种遍历节点 .
 
33. ViewController didReceiveMemoryWarning 是在什么时候被调用的 ?
1. 当应用程序的内存使用接近系统的最大内存使用时 , 应用会向系统发送内存警告 , 这时候系统会调用方法向所有 ViewController 发送内存警告 .
 
2. 打开系统相机 .
 
3. 加载高清图片 .
 
默认操作 : 把里面没有用的对象进行释放 .
 
34. 面向对象的三大特征 , 简单介绍 .
封装 : 代码模块化 , 方便以后调用 .
 
继承 : 子类继承父类的所有方法和属性 .
 
多态 : 父类指针指向子类对象 .
 
35. 重写一个 NSString 类型的 ,retain 方式声明 name 属性的 setter getter 方法 .
属性的三大特性 : 语义特性 , 原子特性 , 读写特性 .
 
同时重写 setter getter 方法 , @synchronized name = _name, 关联属性和实例变量 .
 
- ( void )setName:(NSString *)name{
    
    if (_name != name){
        
        [_name retain];
        
        [_name release];
        
        _name = name;
        
    }
    
}
 
- (NSString *)name{
    
    return [[_name retain]autorelease];
    
}
 
36. 简述 NotificationCenter.KVC,KVO,Delegate? 并说明它们之间的区别 ?
NotificationCenter: 消息中心 . 消息通知 .
 
KVC: 利用键 - 值间接访问类中的某个属性 .
[ self setValue: @"123" forKeyPath: @"name" ];
NSLog( @"%@" ,[ self valueForKeyPath: @"name" ]);
 
KVO: 利用键 - 路径间接访问类中的某个属性 , 也就是观察者模式 (KVO+ 通知中心 ). 基于 KVC 和通知中心 , 观察的是实例变量 .
 
Delegate: 用于多个类之间的传值 .
 
37. What is lazy loading?
懒加载
 
38. MVC 的理解 , 好处 ?
MVC: 是一种架构 .model: 数据处理 ,view: 视图显示 ,controller: 逻辑控制 , 负责视图和模型之间的通信 .
 
高类聚 , 低耦合 , 提高代码的复用性 .
 
39. 监测键盘的弹出 .
通知 .
 
[[NSNotificationCenter defaultCenter]addObserver: self    selector: @selector ()  name:UIKeyboardWillShowNotification  object: nil ];
 
40.   5 ios,sdk 库和第三方库 .
系统库 :UIKit 框架 : 负责应用程序的图形及事件驱动的关键基础 , : 用户界面管理 , 图形和窗口支持 .
 
Mapkit 框架 : 地图 .
 
Message UI 框架 : 电子邮件
 
AV Foundation 框架 : 可用于音频播放 .
 
OpenAL 框架 : 用于播放 , 可播放高质 , 高性能的网络音频
 
Core Data 框架 : 将数据存储在 SQLite 数据库 .
 
Core Media 框架 : 播放视频 .
 
第三方 :SDWebImage : 简化图片处理
 
ShareSDK    分享
 
SVProgressHUD   轻量级菊花
 
AFNetworkin  方便网络开发
 
FreeStreamer  播放音频
 
41. 介绍响应者链 .
当用户点击屏幕 , 能够产生响应的对象组成的链 .
 
继承自 NSResponder, 响应者链能够中断 .
 
42. 传值方式 :
通知 , 单例 , 代理 , 属性 ,block.
 
43. NSString * test = [[NSData alloc] init],test 在编译时和运行时分别是什么类型的对象 ?
编译时是 NSString, 运行时是 NSData.NSData
 
44. OC 中对象的交互是如何实现的 ?
消息机制 .
 
45. 给定一个字符串 , 判断字符串中是否还有 png, 有就删除 .
stringContains 使用 @"" 直接替换实现删除
 
46. 目标 - 动作机制 .
Target - action
 
47. 什么是沙盒 ? 沙盒里包含哪些文件 , 如何获取文件路径 .
沙盒 : 程序可操作的磁盘空间 , 系统为之开辟 .
 
包含了 3 个文件夹 .
 
1.Documents: 存放一些比较重要的文件 , 但是放入 Documents 中的文件不能过大 .
 
2.Library : 是一个资源库 , 存储一些不太重要的数据 . 里面包含了两个子文件夹 ,Caches 文件夹 , 用于缓存 ,
 
Preferences 文件夹 , 系统偏好设置 , 用户对应用程序的设置 , 如密码 .perferences 路径无法找到 , 只能通过 NSUserDefaults.
 
:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES ) firstObject];
 
48. 介绍一下 XMPP?
基于 XML 的点对点通讯协议 , 实现通讯功能 .
 
优点 : 可以跨平台开发 .
 
缺点 : 丢包 , 只能发文字 ( 图片发送发的是链接 ).
 
49. 应用程序如何省电 ?
获取请求不能过频 . 优化算法 .
 
50. 写一个递归方法 , 计算 n 的阶乘 .
-(NSInteger)digui:(NSInteger)i{
    
    if (i>0) {
        
        return i*[ self digui:(i-1)];
        
    } else {
        
        return 1;
        
    }
    
}
 
[[NSUserDefaults standardUserDefaults]setObject:@([ self digui:3]) forKey: @"value" ];
 
51. NSArray NSMutableArray 的区别 ? 多线程下那个更安全 .
NSArray: 不可变数组 .
 
NSMutableArray: 可变数组 .
 
多线程下 NSArray 更安全 .
 
52. 取出一个数组中的重复元素 .
1. 放进集
 
2. 遍历删除
 
3. 放进字典作为 key, 再取出 key
 
54. isKindOfClass,isMemberOfClass 作用分别是什么 ?
isKindOfClass 是某个类的实例或者子类的实例 .
 
isMemberOfClass 是某个类的实例
 
55. 请分别写出 SEL,id 的意思 ?
SEL : 选择器 .
id : 范类型
OC 中的对象就是 C 语言的指针 .
 
56. iPhone , 能被应用程序直接调用的系统程序是什么 ?
: 相册 , 相机 , 通讯录 , 音乐 .
 
不能 : 计算器 , 天气 , 日历 , 指南针 .
 
57. .mm 为扩展名的文件里 , 可以包含哪些代码 ?
C++,C,OC
 
58. 说说后台如何运行程序 .
plist 配置 Application does not run in background 设置 NO ( 默认就是 NO ) 的前提下 .
 
添加 required background modes, 值是 App registers for location updates App plays auto or streams audio/video using AirPlay
 
59. sizeof strlen 的区别和联系 ?
sizeof : 占用空间大小 .
strlen : 字符串大小 .
 
60. sprintf,strcpy,memcpy 的功能 ? 使用上要注意哪些地方 ?
sprintf: 将某些类型转换成字符串类型
strcpy: 拷贝字符串 , 会越界 ,'/0'
memcpy: 拷贝内存
 
61. 写一个函数实现 strlen 的功能 ?
int sl( const char *s)
 
{
    
    int length = 0;
    
    while (*s!='') {
        
        s++;
        
        length++;
        
    }
    
    return length;
    
}
 
62. 写一个代码片实现输入一个字符串 "20130322152830" , 输出一个 NSDate 类型的对象 , 打印该对象输出 2013 - 03 - 11 15 : 28 : 32
 
NSString * str = @"20130322152832" ;
 
NSDateFormatter * format = [[NSDateFormatter alloc]init];
 
format.dateFormat = @"yyyyMMddHHmmss" ; // 设置格式
 
NSLog( @"%@" ,[[format dateFromString:str] dateByAddingTimeInterval:8*60*60]);
 
63. 用变量 a 写出以下定义
 
a 、一个整型数 int a = 10
 
b 、一个指向整型数的指针 int *p = 10
 
c 、一个指向指针的指针,它指向的指针是指向一个整型数 int **p =10
 
d 、一个有 10 个整型数的数组 int a[10]
 
e 、一个有 10 个指针的数组,该指针是指向一个整型数的 int *a[10]
 
f 、一个指向有 10 个整型数数组的指针 int *a = {1,2,3,4,5,6,7,8,9,10};
 
g 、一个指向函数的指针,该函数有一个整型参数,并返回一个整型数
 
int *a( int   b){
    
    return b;
    
}
 
64. cocoa cocoa touch?
 
cocoa 包含 Foundation AppKit 框架,可用于开发 Mac OS X 系统的应用程序
 
cocoa touch 包含 Foundation UIKit 框架,可用于开发 iPhone OS 系统的应用程序
 
Cocoa Mac OS X 的开发环境, cocoa Touch Iphone OS 的开发环境
 
65. 网络从下往上分为几层?
从下往上:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
 
IP 协议对应网络层, TCP 协议对应传输层, HTTP 协议对应于应用层。
 
socket 则是对 TCP/IP 协议的封装和应用。也可以说, TCP/IP 协议是传输层协议,主要解决数据如何在网络中传输,而 HTTTP 是应用层协议,主要解决
 
66. 热更新几种实现方式
 
67. 多线程的底层实现?
 
线程:进程中一个特立独行的控制单元(路径)。多线程:一个进程至少有一个线程,即主线程。
①、 Mach 是第一个以多线程方式处理任务的系统,因此多线程的底层实现机制就是基于 Mach 的线程。
 
②、开发中很少用到 Mach 级的线程,因为 Mach 级的线程没有提供多线程的基本特征,线程之间是独立的。
 
④、开发中实现多线程的方案:
 
NSThread GCD NSOperationQueue.NSOperation
 
68. 线程之间怎么通信 ?
 
.performSelect:onThread:withObject:waitUntilDone:
 
.NSMachPort
 
69. 网络图片问题中怎么解决一个相同的网络地址重复请求的问题 .
 
利用字典 : 图片地址为 key, 下载操作为 value.value
 
70. NSOperation NSOperationQueue 处理 A.B.C 三个线程 , 要求执行完 A.B 后才能执行 ?
 
创建队列
NSOperationQueue * queue = [[NSOperationQueue alloc]init];
 
创建三个操作
NSOperation * A = [NSBlockOperation blockOperationWithBlock:^{
    
    NSLog{ @"A" };
    
}];
 
NSOperation * B = [NSBlockOperation blockOperationWithBlock:^{
    
    NSLog{ @"B" };
    
}];
 
NSOperation * C = [NSBlockOperation blockOperationWithBlock:^{
    
    NSLog{ @"C" };
    
}];
 
添加依赖
[C addDependency:a];
 
[C addDependency:b];
 
执行操作
[queue addOperation:a];
 
[queue addOperation:b];
 
[queue addOperation:c];
 
71. GCD 内部怎么实现的 ?
1 IOS和OS X的核心是XNU内核,GCD是基于XUN内核实现的
2 GCD的API全部在libdispatch库中
3 GCD的底层实现主要有Dispatch Queue 和Dispatch Source
Dispatch Queue :管理block操作
Dispatch Source :处理事件(比如线程间通信)
 
72. 怎么保证多人开发进行内存泄露检查。
使用 Analuze 进行代码的静态分析,为避免麻烦,多人开发尽量使用 ARC.
 
73 、非自动内存管理情况下怎么做单例模式。
创建一个单例对象的静态实例,并初始化为 nil
 
创建一个类的类工厂方法,当且仅当这个类的实例为 nil 时生成一个类的实例。
 
实现 NScopying 协议,覆盖 allocWithZone :方法,确保用户在直接分配对象时,不会产生另一个对象。
 
覆盖 release autorelease retain retainCount 方法,确保单例的状态。
 
74 、对于类方法(静态方法)默认是 autorelease 的,所有类方法都会这样吗?
①、系统自带的绝大数类方法返回的对象,都是经过 autorelease.
 
75 block ARC 中和 MRC 中的方法有何区别?需要注意什么?
①.对于没有引用外部变量的 Block ,无论在 ARC 还是 MRC 下,类型都是 _NSGlobalBlock_, 这种类型的 block 可以理解为一种全局的 block, 不需要考虑作用域的问题。同时,对它进行 Copy Retain 操作也是无效的。
 
②.避免循环引用。
 
根据 isa 指针, block 一共有 3 种类型的 block
 
_NSConcreteGlobalBlock 全局静态
 
_NSConcreteStackBlock 保存在栈中,出函数作用域就销毁
 
_NSConcreteMallocBlock 保存在堆中, retainCount == 0 销毁
 
76. 什么情况下会发生内存泄露和内存溢出?
当程序在申请内存后,无法释放已经申请的内存空间(例如一个对象或者变量在用完后没有释放,这个对象就一直占用着内存),一次内存泄露可以忽略,但如果泄露过多的话,就会造成内存溢出。
 
当程序在申请内存时,但存入了更大的数据,出现内存溢出。
 
77. [NSArray arrayWithobject<id>] 这个方法添加对象后,需要对这个数组进行释放操作吗?
不需要,这个对象会被放到自动释放池中。
 
78. 自动释放池如何实现?
自动释放池以栈的形式实现,当你创建一个新的自动释放池时,它将被添加到栈顶,当一个对象收到发送 autorelease 消息时,它将添加到当前线程的处于栈顶的自动释放池中,当自动释放池被回收时,它们从栈中被删除并且会给池子里所有对象都做一次 release 操作。
 
79. KVO 内部实现原理?
①. KVO 是基于 runtime 机制实现的。
 
②.当某个类的对象第一次被观察时,系统就会在运行期动态的创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的 setter 方法。
 
派生类在被重写 setter 方法中实现了真正的通知机制。( Person->NSKVONotification Person
 
80. 能否把比较耗时的操作放在 NSNotificationCenter 中。
如果在异步线程发出的通知,那么就可以把耗时操作放到 NSNotificationCenter
如果在主线程发的通知,那么就不可以把耗时操作放到 NSNotificationCenter 中。
 
81.F oundation 对象与 Core Foundation 对象有何区别?
Foundation 对象是 OC 的, Core Foundation 对象是 C 对象。
数据类型之间的转换:
 
ARC _bridge_retained _bridge_transfer
 
ARC:_bridge
 
82 、不用第三变量,交换 AB 的值。
A=A+B
 
B=A-B
 
A=A-B
 
或者
 
A=A^B
 
B=A^B
 
A=A^B
 
83. 简单描述下对单例模式设计的理解?
节省内存资源,一个应用就一个对象。
 
84. runtime 实现的机制是什么?怎么用,一般用于干嘛。
运行时机制, runtime 库里面包含了跟类、成员变量、方法相关的 API ,比如获取类里面的所有成员变量,为类动态添加成员变量、动态改变类的方法实现,为类动态添加新的方法等,需要导入 <objc/message.h><objc/message.h>
 
①. runtime, 运行时机制,它是一套 C 语言库。
 
②.实际上我们编写的所有 OC 代码,最终都是转换成为了 runtime 库的东西,比如类转换成了 runtime 库里面的结构体等数据类型,方法转换成了 runtime 库里面的 C 语言函数,平时调方法都是转成了 objc_msgSend 函数(所以说 OC 有个消息发送机制)
 
③、因此,可以说 runtime OC 的底层实现,是 OC 的幕后执行者。
 
④、有了 runtime 库,能做什么呢?可以获取类里面的所有成员变量、为类动态的添加成员变量、动态的改变类的方法实现、为类动态添加新的方法等等。
 
85. 是否使用 Core Text 或者 Core Image
Core Text
 
随意修改文本的样式
 
图文混排(纯 C 语言)
 
Core Image( 滤镜处理 )
 
能够调节图片的各种属性(对比度、色温、色差等)
 
86 NSNotification KVO 的区别和用法是什么?什么时候应该使用通知,什么时候应该使用 KVO, 他们的实现有何区别?如果用 protocol delegate 来实现类似的功能可能吗?可能的话有何问题?不可能的话 why
 
通知比较灵活,一个通知能被多个对象接受,一个对象可以接受多个通知。
 
代理不交规范,但是代码较多(默认是一对一)
 
KVO 性能不好(底层会产生新的类),只能监听某个对象属性的变化,不推荐使用。
 
87 block 内部的实现原理。
Objective-C 是对 C 语言的扩展, block 的实现是基于指针和函数指针。
 
88 、怎么解决缓存池满的问题?
iOS 中不存在缓存池满的情况,通常在对象需要创建时才创建,比如 UITableView 中一般只会创建刚开始在屏幕中的 cell ,之后都是从缓存池里取,不会再创建新对象。
 
89 控制器 View 的生命周期及相关函数是什么?你在开发中是如何使用的?
1 、首先判断控制器是否有视图,如果没有就调用 loadView 方法创建:通过 storyBoard 或者代码。
 
2 、随后调用 viewDidLoad ,可以进行下一步的初始化操作,只会被调用一次。
 
3 、在视图显示之前调用 viewWillAppear, 该函数可以多次调用。
 
4 、视图 viewDidAppear
 
5 、在布局变化前后,调用 viewWill/DidLayoutSubViews 处理相关信息。
 
90 有些图片加载比较慢怎么处理?你是怎么优化程序的性能的?
①、图片下载放在异步线程。
 
②、图片下载过程使用占位图片。
 
③、如果图片比较大,可以使用多线程断点下载。
 
91. App 需要加载大量数据,给服务器发送请求,但是服务器卡住了怎么办?
设置请求超时,给用户提示请求超时,根据用户操作再次请求。
 
92 SDWebImage 具体如何实现?
其实就是沙盒缓存机制,主要由三块组成:内存图片缓存,内存操作缓存,磁盘沙盒缓存。
 
①、利用 NSOperationQueue NSOperation 下载图片,还使用了 GCD (解析 GIF 图片)。
 
②、利用 URL 作为 key NSOperation 作为 value.
 
③、利用 URL 作为 key UIImage 作为 value
 
93 AFNetWorking 实现原理。
基于 NSURL. 采用 block 的方法处理请求,直接返回的是 json XML 数据。 AFN 直接操作对象是 AFHTTPClient, 是一个实现了 NSCoding NSCopying 协议的 NSObject 子类。 AFGTTPClient 是一个封装了一系列操作方法的工具类。 AFN 默认没有封装同步请求,如果开发者需要使用同步请求,需要重写相关的方法( getPath:parameters:failure ),对 AFHTTPRequestOperation 进行同步处理。
 
 
9 4 、什么是响应链,它是怎么工作的?
 
9 5 iOS 的沙盒目录结构是怎样的? App Bundle 里面都有什么?
1. 沙盒结构
 
Application :存放程序源文件,上架前经过数字签名,上架后不可修改
Documents :常用目录, iCloud 备份目录,存放数据 , 这里不能存缓存文件 , 否则上架不被通过
Library
Caches :存放体积大又不需要备份的数据 ,SDWebImage 缓存路径就是这个
Preference :设置目录, iCloud 会备份设置信息
tmp :存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能
 
2.App Bundle 里面有什么
 
Info.plist: 此文件包含了应用程序的配置信息 . 系统依赖此文件以获取应用程序的相关信息
可执行文件 : 此文件包含应用程序的入口和通过静态连接到应用程序 target 的代码
资源文件 : 图片 , 声音文件一类的
其他 : 可以嵌入定制的数据资源
 
iOS 的签名机制大概是怎样的?
 
假设,我们有一个 APP 需要发布,为了防止中途篡改 APP 内容,保证 APP 的完整性,以及 APP 是由指定的私钥发的。首先,先将 APP 内容通过摘要算法,得到摘要,再用私钥对摘要进行加密得到密文,将源文本、密文、和私钥对应的公钥一并发布即可。那么如何验证呢?
验证方首先查看公钥是否是私钥方的,然后用公钥对密文进行解密得到摘要,将 APP 用同样的摘要算法得到摘要,两个摘要进行比对,如果相等那么一切正常。这个过程只要有一步出问题就视为无效。
iOS 7 的多任务添加了哪两个新的 API? 各自的使用场景是什么?
 
后台获取( Background Fetch): 后台获取使用场景是用户打开应用之前就使 app 有机会执行代码来获取数据,刷新 UI 。这样在用户打开应用的时候,最新的内容将已然呈现在用户眼前,而省去了所有的加载过程。
推送唤醒( Remote Notifications): 使用场景是使设备在接收到远端推送后让系统唤醒设备和我们的后台应用,并先执行一段代码来准备数据和 UI ,然后再提示用户有推送。这时用户如果解锁设备进入应用后将不会再有任何加载过程,新的内容将直接得到呈现。
 
9 6 UIScrollView 大概是如何实现的,它是如何捕捉、响应手势的?
 
我对 UIScrollView 的理解是 frame 就是他的 contentSize,bounds 就是他的可视范围 , 通过改变 bounds 从而达到让用户误以为在滚动 , 以下是一个简单的 UIScrollView 实现
 
在头文件定义一个 contentSize 属性
 
@interface MyScrollView : UIView
@property (nonatomic) CGSize contentSize;
@end
 
@implementation MyScrollView
- ( instancetype )initWithFrame:(CGRect)frame{
    self = [ super initWithFrame:frame];
    if ( self == nil ) {
        return nil ;
    }
 
    添加一个滑动手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget: self action: @selector (panGesture:)];
    [ self addGestureRecognizer:pan];
    return self ;
}
 
- ( void )panGesture:(UIPanGestureRecognizer *)gestureRecognizer{
   
改变 bounds
    CGPoint translation = [gestureRecognizer translationInView: self ];
    CGRect bounds = self .bounds;
    
    CGFloat newBoundsOriginX = bounds.origin.x - translation.x;
    CGFloat minBoundsOriginX = 0.0;
    CGFloat maxBoundsOriginX = self .contentSize.width - bounds.size.width;
    bounds.origin.x = fmax(minBoundsOriginX, fmin(newBoundsOriginX, maxBoundsOriginX));
    
    CGFloat newBoundsOriginY = bounds.origin.y - translation.y;
    CGFloat minBoundsOriginY = 0.0;
    CGFloat maxBoundsOriginY = self .contentSize.height - bounds.size.height;
    bounds.origin.y = fmax(minBoundsOriginY, fmin(newBoundsOriginY, maxBoundsOriginY));
    
    self .bounds = bounds;
    [gestureRecognizer setTranslation:CGPointZero inView: self ];
}
 
第二个问题个人理解是解决手势冲突 , 对自己添加的手势进行捕获和响应
 
UIScrollView 遵守 UIGestureRecognizerDelegate 协议 , 实现这个方法 , 在这里方法里对添加的手势进行处理就可以解决冲突
- ( BOOL )gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
 
9 7 Objective-C 如何对已有的方法,添加自己的功能代码以实现类似记录日志这样的功能?
 
这题目主要考察的是 runtime 如何交换方法
 
先在分类中添加一个方法 , 注意不能重写系统方法 , 会覆盖
 
+ (NSString *)myLog
{
    这里写打印行号 , 什么方法 , 哪个类调用等等
}
 
然后交换方法
 
加载分类到内存的时候调用
+ ( void )load
{
    获取 imageWithName 方法地址
    Method description = class_getClassMethod( self , @selector (description));
    
    获取 imageWithName 方法地址
    Method myLog = class_getClassMethod( self , @selector (myLog));
    
    交换方法地址,相当于交换实现方式
    method_exchangeImplementations(description, myLog);
}
 
9 8 +load +initialize 的区别是什么?
 
+( void )load;
当类对象被引入项目时 , runtime 会向每一个类对象发送 load 消息
load 方法会在每一个类甚至分类被引入时仅调用一次 , 调用的顺序:父类优先于子类 , 子类优先于分类
load 方法不会被类自动继承
+( void )initialize;
也是在第一次使用这个类的时候会调用这个方法
 
9 9 、如何让 Category 支持属性?
使用 runtime 可以实现
 
头文件
 
@interface NSObject (test)
 
@property (nonatomic, copy) NSString *name;
 
@end
 
.m 文件
 
@implementation NSObject (test)
  定义关联的 key
static const char *key = "name" ;
- (NSString *)name
{
    根据关联的 key ,获取关联的值。
    return objc_getAssociatedObject( self , key);
}
- ( void )setName:(NSString *)name
{
    第一个参数:给哪个对象添加关联
    第二个参数:关联的 key ,通过这个 key 获取
    第三个参数:关联的 value
    第四个参数 : 关联的策略
    objc_setAssociatedObject( self , key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
 
100 NSOperation 相比于 GCD 有哪些优势?
提供了在 GCD 中不那么容易复制的有用特性。
可以很方便的取消一个 NSOperation 的执行
可以更容易的添加任务的依赖关系
提供了任务的状态: isExecuteing, isFinished.
 
101 strong / weak / unsafe_unretained 的区别?
weak 只能修饰 OC 对象 , 使用 weak 不会使计数器加 1, 对象销毁时修饰的对象会指向 nil , strong 等价与 retain, 能使计数器加 1, 且不能用来修饰数据类型
 
unsafe_unretained 等价与 assign, 可以用来修饰数据类型和 OC 对象 , 但是不会使计数器加 1, 且对象销毁时也不会将对象指向 nil , 容易造成野指针错误
 
102 、如何为 Class 定义一个对外只读对内可读写的属性 ?
在头文件中将属性定义为 readonly, .m 文件中将属性重新定义为 readwrite
 
103 Objective-C 中, meta-class 指的是什么?
meta- class Class 对象的类 , 为这个 Class 类存储类方法 , 当一个类发送消息时 , 就去那个类对应的 meta- class 中查找那个消息 , 每个 Class 都有不同的 meta- class , 所有的 meta- class 都使用基类的 meta- class ( 假如类继承 NSObject, 那么他所对应的 meta- class 也是 NSObject) 作为他们的类
 
104 UIView CALayer 之间的关系?
UIView 显示在屏幕上归功于 CALayer ,通过调用 drawRect 方法来渲染自身的内容,调节 CALayer 属性可以调整 UIView 的外观, UIView 继承自 UIResponder CALayer 不可以响应用户事件
UIView iOS 系统中界面元素的基础,所有的界面元素都继承自它。它内部是由 Core Animation 来实现的,它真正的绘图部分,是由一个叫 CALayer(Core Animation Layer) 的类来管理。 UIView 本身,更像是一个 CALayer 的管理器,访问它的根绘图和坐标有关的属性,如 frame bounds 等,实际上内部都是访问它所在 CALayer 的相关属性
UIView 有个 layer 属性,可以返回它的主 CALayer 实例, UIView 有一个 layerClass 方法,返回主 layer 所使用的类, UIView 的子类,可以通过重载这个方法,来让 UIView 使用不同的 CALayer 来显示
 
105 +[UIView animateWithDuration:animations:completion:] 内部大概是如何实现的?
animateWithDuration: 这就等于创建一个定时器
animations: 这是创建定时器需要实现的 SEL
completion: 是定时器结束以后的一个回调 block
 
以上只是自己的理解 , 不一定正确 , 有对这个有研究的朋友请告知下
 
106 什么时候会发生「隐式动画」?
当改变 CALayer 的一个可做动画的属性,它并不能立刻在屏幕上体现出来 . 相反,它是从先前的值平滑过渡到新的值。这一切都是默认的行为,你不需要做额外的操作 , 这就是隐式动画
 
107 如何处理异步的网络请求?
异步请求:会单独开一个线程去处理网络请求,主线程依然处于可交互状态 , 程序运行流畅
POST 请求
NSString *urlString = @" www.baidu.com " ;
创建 url 对象
NSURL *url = [NSURL URLWithString:urlString];
创建请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
创建参数字符串对象
NSString *parmStr = [NSString stringWithFormat: @" 参数 " ];
将字符串转换为 NSData 对象
NSData *data = [parmStr dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];
[request setHTTPMethod: @"POST" ];
创建异步连接
[NSURLConnection connectionWithRequest:request delegate: self ];
 
然后实现代理方法
 
服务器接收到请求时
- ( void )connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
}
当收到服务器返回的数据时触发 , 返回的可能是资源片段
- ( void )connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
}
当服务器返回所有数据时触发 , 数据返回完毕
- ( void )connectionDidFinishLoading:(NSURLConnection *)connection
{
}
请求数据失败时触发
- ( void )connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog( @"%s" , __FUNCTION__ );
}
 
108 frame bounds 的区别是什么?
frame 相对于父视图 , 是父视图坐标系下的位置和大小。 bounds 相对于自身 , 是自身坐标系下的位置和大小。
frame 以父控件的左上角为坐标原点, bounds 以自身的左上角为坐标原点
 
109 、如何把一张大图缩小为 1 / 4 大小的缩略图?
let data = UIImageJPEGRepresentation(image, 0.25)
 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值