iOS 开发面试问题(二)

** iOS 开发面试问题(一)传送门 **

** 1、Push Notification 是如何工作的?**
iOS消息推送机制

** 2、什么是 Runloop?**
对Runloop实在的理解和运用
深入理解RunLoop

** 3、Toll-Free Bridging 是什么?什么情况下会使用?**
在开发中时常要使用Core Foundation框架,例如Core Graphics、Core Text等,有时需要在CF指针和OC对象之间进行转换,,在转换中需要注意内存管理。在ARC环境下,编译器不能自动管理CF对象的内存,我们需要使用CFRelease将其手动释放。因此需要时可以使用 __bridge __bridge_transfer __bridge_retained进行桥接。


使用方法

  • __bridge:CF和OC对象转化时只涉及对象类型不涉及对象所有权的转化
NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
CFURLRef ref = (__bridge CFURLRef)url;

使用__bridge时,不管是从OC转换到CF还是从CF转换成OC,即内存的管理权(所有权)不随转换而转换,CF对象还是需要使用CFRelease(),OC对象由ARC自动管理。


  • __bridge_transfer 、orCFBridgingRelease:在CF指针转换成OC对象时,将CF指针的所有权交给ARC管理,此时ARC就能自动管理该内存

  • __bridge_retained or CFBridgingRetain:将OC对象转换成CF指针时,管理的所有交由使用者手动释放
NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
CFURLRef ref = (__bridge_retained CFURLRef)url;
CFRelease(ref);

iOS里Toll-Free Bridging的桥接机制

** 4、当系统出现内存警告时会发生什么?**

  • 会将不在当前窗口上的view暂时移除
  • 如果放任内存警告,最终会导致软件强制被系统关闭

** 5、什么是 Protocol,Delegate 一般是怎么用的?**
理解协议与代理
协议:
协议是一个方法签名的列表,在其中可以定义若干个方法。根据配置,遵守该协议的类会去实现这个协议中规定的若干个方法。
代理:
代理是一个概念,它更像是一种关系,我要做某一个事情,但我自己不想去做这件事,我委托其他人帮我去做这件事。这个时候,这位其他人就是我的代理。
IOS学习之一个示例弄懂代理(delegate)和协议

** 6、autorelease 对象在什么情况下会被释放?**
分两种情况:手动干预释放和系统自动释放

  • 手动干预释放就是指定autoreleasepool,当前作用域大括号结束就立即释放
for (int i = 0; i < 10000000; ++i) {
   @autoreleasepool {
      HYBTestModel *tempModel = [[HYBTestModel alloc] init];
      // 临时处理
      // ...
   } // 出了这里,就会去遍历该自动释放池了
}
  • 系统自动去释放:不手动指定autoreleasepool,Autorelease对象会在当前的 runloop 迭代结束时释放
  • kCFRunLoopEntry(1):第一次进入会自动创建一个autorelease
  • kCFRunLoopBeforeWaiting(32):进入休眠状态前会自动销毁一个autorelease,然后重新创建一个新的autorelease
  • kCFRunLoopExit(128):退出runloop时会自动销毁最后一个创建的autorelease

黑幕背后的Autorelease

** 7、UIWebView 有哪些性能问题?有没有可替代的方案。**
UIWebView、WKWebView使用详解及性能分析

8、为什么 NotificationCenter 要 removeObserver? 如何实现自动 remove?

  • 如果不移除的话,万一注册通知的类被销毁以后又发了通知,程序会崩溃.因为向野指针发送了消息
  • 实现自动remove:通过自动释放机制,通过动态属性将remove转移给第三者,解除耦合,达到自动实现remove

NSNotification 线程管理以及自动注销开源方案个人感觉没必要实现自动remove,这篇文章我看的也是不走心。只要记住在页面出现的时候注册通知,页面消失时移除通知,一定要成双成对出现就OK 了。

** 9、当 TableView 的 Cell 改变时,如何让这些改变以动画的形式呈现?**
这里举个例子,点击cell以后以动画形式改变cell高度

@interface ViewController ()
@property (nonatomic, strong) NSIndexPath *index;
@end

@implementation ViewController

static NSString *ID = @"cell";
- (void)viewDidLoad {

    [super viewDidLoad];


}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    cell.textLabel.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row];
    return cell;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 20;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{

    if(self.index == indexPath){

        return 120;
    }

    return 60;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    self.index = indexPath;

    [tableView deselectRowAtIndexPath:indexPath animated:TRUE];
    // 重点是这2句代码实现的功能
    [tableView beginUpdates];
    [tableView endUpdates];
}

** 10、什么是 Method Swizzle,什么情况下会使用?**
又是一个RunTime的考点
Objective-C Method Swizzling 的最佳实践

11、 为什么 UIScrollView 的滚动会导致 NSTimer 失效?
这是否滚动取决于timer加入到Run Loop中的Mode是什么。Mode主要是用来指定事件在运行循环中的优先级的,分为:

NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
UITrackingRunLoopMode:ScrollView滑动时会切换到该Mode
UIInitializationRunLoopMode:run loop启动时,会切换到该mode
NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合

苹果公开提供的Mode有两个:

NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
NSRunLoopCommonModes(kCFRunLoopCommonModes)

在编程中:如果我们把一个NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环中的时候, ScrollView滚动过程中会因为mode的切换,而导致NSTimer将不再被调度。当我们滚动的时候,也希望不调度,那就应该使用默认模式。但是,如果希望在滚动时,定时器也要回调,那就应该使用common mode。

** 12、为什么当 Core Animation 完成时,layer 又会恢复到原先的状态?**
因为这些产生的动画只是假象,并没有对layer进行改变.那么为什么会这样呢,这里要讲一下图层树里的呈现树.呈现树实际上是模型图层的复制,但是它的属性值表示了当前外观效果,动画的过程实际上只是修改了呈现树,并没有对图层的属性进行改变,所以在动画结束以后图层会恢复到原先状态
让动画在完成后也不移除,并且停留在动画结束的状态可以这样:

alphaAnim.removedOnCompletion = NO;
alphaAnim.fillMode = kCAFillModeForwards;

图层的树状结构 这是个讲 iOS Animation的系列文章

** 13、你会如何存储用户的一些敏感信息,如登录的 token。**
使用Keychain存储用户敏感信息

14、 有用过一些开源组件吧,能简单说几个么,大概说说它们的使用场景实现。
这里给出两个知名度很高很常用的开源组件解析
关于AFNetworking 3.0
iOS程序猿之AFNetworking 3.0 版本使用
SDWebImage 原理及使用
SDWebImage的使用

15、 什么时候会发生 EXC BAD ACCESS 异常?

  • 访问一个僵尸对象,访问僵尸对象的成员变量或者向其发消息
  • 死循环

** 16、什么时候会使用 Core Graphics,有什么注意事项么?**
几个基本概念:

  • UIKit:cocoa touch框架,高层次的框架,允许开发人员创建视图、窗口、按钮和其他UI组件。同时将一些低级别的API引入到易于使用的高级别API中。
  • Quartz 2D:IOS上绘图的主要引擎,是一组二位绘图和渲染API。
  • Core Graphics:它支持图形上下文、加载图像、绘制图像,等等。
  • Core Animation 帮助开发者在IOS上实现动画的框架。

Core Graphics是基于C的API,可以用于一切绘图操作我们可以通过派生一个UIView的子类,获得它的上下文。在UIView中调用drawRect:方法时,会自动准备好一个图形上下文,可以通过调用UIGraphicsGetCurrentContext()来获取。 因为它是运行期间绘制图片,我们可以动态的做一些额外的操作。
使用Core Graphics,可以创建直线、路径、渐变、文字与图像等内容,并可以做变形处理。

Core Graphics教程1:入门
Core Graphics 框架学习笔记,以及demo

** 17、NSNotification 和 KVO 的使用场景?**
iOS KVC & KVO

** 18、使用 Block 时需要注意哪些问题?**

  • 在block内部使用外部指针且会造成循环引用情况下,需要用__weak
    修饰外部指针__weak typeof(self) weakSelf = self;

  • 在block内部如果调用了延时函数还使用弱指针会取不到该指针,因为已经被销毁了,需要在block内部再将弱指针重新强引用一下__strong typeof(self) strongSelf = weakSelf;

  • 如果需要在block内部改变外部变量的话,需要在用__block
    修饰外部变量

OS开发-语法篇-block详解
iOS OC语言: Block底层实现原理

** 19、performSelector:withObject:afterDelay: 内部大概是怎么实现的,有什么注意事项么?**
performSelector 和NSTimer使用注意事项

** 20、如何播放 GIF 图片,有什么优化方案么?**
IOS 播放动态Gif图片

** 21、使用 NSUserDefaults 时,如何处理布尔的默认值?(比如返回 NO,不知道是真的 NO 还是没有设置过) **

if([[NSUserDefaults standardUserDefaults] objectForKey:ID] == nil){
        NSLog(@"没有设置");
    }

NSUserDefaults的使用

** 22、有哪几种方式可以对图片进行缩放,使用 CoreGraphics 缩放时有什么注意事项?
**
ios中图片拉伸的几种方式
UIScrollView控件实现图片缩放功能
iOS中拉伸图片的几种方式
图片拉伸原理

** 23、哪些途径可以让 ViewController 瘦下来?**

  • 把 Data Source 和其他 Protocols 分离出来(将UITableView或者UICollectionView的代码提取出来放在其他类中)
  • 将业务逻辑移到 Model 中(和模型有关的逻辑全部在model中写)
  • 把网络请求逻辑移到 Model 层(网络请求依靠模型)
  • 把 View 代码移到 View 层(自定义View)

更轻量的 View Controllers

** 24、有哪些常见的 Crash 场景? **
比如数组越界、插空、空引用、引用未定义方法、访问野指针、发送未实现的selector等。
iOS Crash调试和Crash符号化

你可能感兴趣的:(iOS 开发面试问题(二))