面试题总结(二)

(1)Foundation对象与Core Foundation对象有什么区别?

  • Foundation对象是OC对象,Core Foundation对象是C对象
  • 数据类型之间的转换
    ARC:bridge_retained(持有对象所有权,F->CF),bridge_transfer(释放对象所有权CF->F)
    非ARC:__bridge

(2)编写一个函数,实现递归删除指定路径下的所有文件

+ (void)deleteFiles:(NSString *)path
{
    //1.判断文件还是目录
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isDir = NO;
    BOOL isExist = [fileManager fileExistsAtPath:path isDirectory:&isDir];
    if (isExist) {
        //2.判断是不是目录
        if (isDir) {
            NSArray *dirArray = [fileManager contentsOfDirectoryAtPath:path error:nil];
            NSString *subPath = nil;
            for (NSString *str in dirArray) {
                subPath = [path stringByAppendingPathComponent:str];
                BOOL isSubDir = NO;
                [fileManager fileExistsAtPath:subPath isDirectory:&isSubDir];
                [self deleteFiles:subPath];
            }
        }else {
            NSLog(@"%@",path);
            [fileManager removeItemAtPath:path error:nil];
        }
    }else {
        NSLog(@"你打印的是目录或者不存在");
    }
}

(3)苹果是如何实现autoreleasepool的?

autoreleasepool以一个队列数组的形式实现,主要通过以下三个函数实现:

  • objc_autoreleasepoolPush
  • objc-autoreleasepoolPop
  • objc-autorelease
    看函数名就可以知道,对autoreleasepool分别执行了Push、Pop操作。销毁对象时执行release操作。

(4)objc使用什么机制管理对象的内存?

通过引用计数器(retainCount)的机制来决定对象是否需要释放。每次runloop完成一个循环的时候,都会检查对象的retainCount,如果retainCount为0,说明该对象没有地方需要继续使用了,可以释放掉了。

(5)内存管理的原则

  • 只要还有人在使用这个对象,那么这个对象就不会被回收
  • 只要你想使用这个对象,那么就应该让这个对象的引用计数器加1
  • 当你不想使用这个对象时,应该让对象的引用计数器减1
  • 谁创建,就由谁release
    如果你通过alloc、new、copy来创建一个对象,当你不想用这个对象的时候就必须调用release或者autorelease让引用计数器减1
    不是你创建的就不用你负责release
  • 谁retain,谁release
    只要你调用了retain,无论这个对象如何生成,都需要调用release
  • 总结:有加就应该有减,曾让某个计数器加1,就应该让其在最后减1

(6)UITableView的性能优化,滑动的时候有种卡的感觉是为什么?怎么解决?

  • 在使用第三方应用时,确经常遇到性能上的问题,普遍表现在滚动时比较卡,特别是cell中包含图片的情况时。
  • 实际上针对性地优化一下就可以解决tableView滑动的时候卡顿的问题:

1、 使用不透明视图。不透明的视图可以提高渲染的速度,可以将cell及其子视图的opaque属性设置为YES(默认值)。
2、不要重复创建不必要的cell。UITableView只需要一屏幕的UITableViewCell对象即可。因此在cell不可见时,可以将其缓存起来,而在需要时继续使用它即可。注意:cell被重用时,需要调用setNeedsDisplayInRect:或setNeedsDisplay方法重绘cell。
3、减少动画效果的使用,最好不要使用insertRowAtIndexPaths:withRowAnimation:方法,而是直接调用reloadData方法。
4、减少视图的数目。Cell包含了textLable、detailTextLabel和imageView等view,而你还可以自定义一些视图放在它的contentView里,创建它会消耗较多资源,并且也影响渲染的性能。
5、cell包含图片,且数目较多,使用自定义的cell速度会比使用默认的要快。
6、不需要与用户交互时,使用CALayer,将内容绘制到layer上,然后对cell的contentView.layer调用addSubLayer:方法。
7、不要做多余的绘制工作。在实现drawRect:的时候,它的rect参数就是需要绘制的区域,这个区域之外的不需要进行绘制。
8、预渲染图层。在图形上下文中画,导出成UIImage对象,然后再绘制到屏幕上。(头像圆角,或者其他变形的时候,用图形上下文能提高性能。)异步绘制
9、不要阻塞主线程。tableView在更新数据时,整个界面卡住不动,完全不响应用户请求。常见的是网络请求,等待时间长待数秒。(解决方案:使用多线程,让子线程去执行这些函数或方法)
注意:当下载线程数超过2时,会显著影响主线程的性能。所以在不需要响应用户请求时,下载线程数可以增加到5,不建议再加了,以加快下载速度。如果用户正在交互,应把线程数量控制在2个以内。
10、提前计算并缓存好高度,因为heightForRowAtIndexPath调用非常频繁
11、选择正确的数据结构:学会选择对业务场景最合适的数据结构是写出高效代码的基础。
12、gzip/zip压缩:当从服务端下载相关附件时,可以通过gzip/zip压缩够再下载,使得内存更小,下载速度也更快。

你可能感兴趣的:(面试题总结(二))