美文网首页iOS面试题
iOS最新面试题汇总(三)

iOS最新面试题汇总(三)

作者: 寻常_0 | 来源:发表于2017-06-07 17:08 被阅读1280次

    iOS最新面试题汇总:
    iOS最新面试题汇总(一)
    iOS最新面试题汇总(二)
    iOS最新面试题汇总(三)
    iOS最新面试题汇总(四)

    1. 下面的代码输出什么?
        @implementation Son : Father
        - (id)init {
           if (self = [super init]) {
               NSLog(@"%@", NSStringFromClass([self class])); // Son
               NSLog(@"%@", NSStringFromClass([super class])); // Son
           }
           return self;
        }
        @end
        // 解析:
        self 是类的隐藏参数,指向当前调用方法的这个类的实例。
        super是一个Magic Keyword,它本质是一个编译器标示符,和self是指向的同一个消息接收者。
        不同的是:super会告诉编译器,调用class这个方法时,要去父类的方法,而不是本类里的。
        上面的例子不管调用[self class]还是[super class],接受消息的对象都是当前 Son *obj 这个对象。
    
    1. 写一个完整的代理,包括声明、实现
        // 创建
        @protocol MyDelagate
        @required
        -(void)eat:(NSString *)foodName; 
        @optional
        -(void)run;
        @end
    
        //  声明 .h
        @interface person: NSObject<MyDelagate>
    
        @end
    
        //  实现 .m
        @implementation person
        - (void)eat:(NSString *)foodName { 
           NSLog(@"吃:%@!", foodName);
        } 
        - (void)run {
           NSLog(@"run!");
        }
    
        @end
    
    1. isKindOfClass、isMemberOfClass、selector作用分别是什么
        isKindOfClass:作用是某个对象属于某个类型或者继承自某类型。
        isMemberOfClass:某个对象确切属于某个类型。
        selector:通过方法名,获取在内存中的函数的入口地址。
    
    4. ####delegate 和 notification 的区别
    
        1). 二者都用于传递消息,不同之处主要在于一个是一对一的,另一个是一对多的。
        2). notification通过维护一个array,实现一对多消息的转发。
        3). delegate需要两者之间必须建立联系,不然没法调用代理的方法;notification不需要两者之间有联系。
    
    1. 什么是block?
        闭包(block):闭包就是获取其它函数局部变量的匿名函数。
    
    1. block反向传值

        在控制器间传值可以使用代理或者block,使用block相对来说简洁。
    
        在前一个控制器的touchesBegan:方法内实现如下代码。
    
          // OneViewController.m
          TwoViewController *twoVC = [[TwoViewController alloc] init];
          twoVC.valueBlcok = ^(NSString *str) {
            NSLog(@"OneViewController拿到值:%@", str); 
          };
          [self presentViewController:twoVC animated:YES completion:nil];
    
          // TwoViewController.h   (在.h文件中声明一个block属性)
          @property (nonatomic ,strong) void(^valueBlcok)(NSString *str);
    
          // TwoViewController.m   (在.m文件中实现方法)
        - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
            // 传值:调用block
            if (_valueBlcok) {
                _valueBlcok(@"123456");
            }
        }
    
    1. block的注意点
        1). 在block内部使用外部指针且会造成循环引用情况下,需要用__week修饰外部指针:
            __weak typeof(self) weakSelf = self; 
        2). 在block内部如果调用了延时函数还使用弱指针会取不到该指针,因为已经被销毁了,需要在block内部再将弱指针重新强引用一下。
            __strong typeof(self) strongSelf = weakSelf;
        3). 如果需要在block内部改变外部栈区变量的话,需要在用__block修饰外部变量。
    
    1. BAD_ACCESS在什么情况下出现?
        答:这种问题在开发时经常遇到。原因是访问了野指针,比如访问已经释放对象的成员变量或者发消息、死循环等。
    
    1. lldb(gdb)常用的控制台调试命令?
        1). p 输出基本类型。是打印命令,需要指定类型。是print的简写
            p (int)[[[self view] subviews] count]
        2). po 打印对象,会调用对象description方法。是print-object的简写
            po [self view]
        3). expr 可以在调试时动态执行指定表达式,并将结果打印出来。常用于在调试过程中修改变量的值。
        4). bt:打印调用堆栈,是thread backtrace的简写,加all可打印所有thread的堆栈
        5). br l:是breakpoint list的简写
    
    1. 你一般是怎么用Instruments的?
        Instruments里面工具很多,常用:
        1). Time Profiler: 性能分析
        2). Zombies:检查是否访问了僵尸对象,但是这个工具只能从上往下检查,不智能。
        3). Allocations:用来检查内存,写算法的那批人也用这个来检查。
        4). Leaks:检查内存,看是否有内存泄露。
    
    1. iOS中常用的数据存储方式有哪些?
    数据存储有四种方案:NSUserDefault、KeyChain、file、DB。
        其中File有三种方式:plist、Archive(归档)
        DB包括:SQLite、FMDB、CoreData
    
    1. iOS的沙盒目录结构是怎样的?
    沙盒结构:
    1). Application:存放程序源文件,上架前经过数字签名,上架后不可修改。
    2). Documents:常用目录,iCloud备份目录,存放数据。(这里不能存缓存文件,否则上架不被通过)
    3). Library:
            Caches:存放体积大又不需要备份的数据。(常用的缓存路径)
            Preference:设置目录,iCloud会备份设置信息。
    4). tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能。
    
    1. iOS多线程技术有哪几种方式?
    答:pthread、NSThread、GCD、NSOperation
    
    1. GCD 与 NSOperation 的区别:
    GCD 和 NSOperation 都是用于实现多线程:
        GCD 基于C语言的底层API,GCD主要与block结合使用,代码简洁高效。
        NSOperation 属于Objective-C类,是基于GCD更高一层的封装。复杂任务一般用NSOperation实现。
    
    1. 写出使用GCD方式从子线程回到主线程的方法代码
    答:dispatch_async(dispatch_get_main_queue(), ^{ });
    
    1. 如何用GCD同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图)
    // 使用Dispatch Group追加block到Global Group Queue,这些block如果全部执行完毕,就会执行Main Dispatch Queue中的结束处理的block。
    // 创建队列组
    dispatch_group_t group = dispatch_group_create();
    // 获取全局并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_async(group, queue, ^{ /*加载图片1 */ });
    dispatch_group_async(group, queue, ^{ /*加载图片2 */ });
    dispatch_group_async(group, queue, ^{ /*加载图片3 */ }); 
    // 当并发队列组中的任务执行完毕后才会执行这里的代码
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            // 合并图片
    });
    
    1. dispatch_barrier_async(栅栏函数)的作用是什么?
    函数定义:dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
    作用:
        1.在它前面的任务执行结束后它才执行,它后面的任务要等它执行完成后才会开始执行。
        2.避免数据竞争
    
     // 1.创建并发队列
     dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    // 2.向队列中添加任务
    dispatch_async(queue, ^{  // 1.2是并行的
        NSLog(@"任务1, %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"任务2, %@",[NSThread currentThread]);
    });
    
     dispatch_barrier_async(queue, ^{
        NSLog(@"任务 barrier, %@", [NSThread currentThread]);
    });
    
     dispatch_async(queue, ^{   // 这两个是同时执行的
        NSLog(@"任务3, %@",[NSThread currentThread]);
    });
     dispatch_async(queue, ^{
        NSLog(@"任务4, %@",[NSThread currentThread]);
    });
    
     // 输出结果: 任务1 任务2 ——》 任务 barrier ——》任务3 任务4 
    // 其中的任务1与任务2,任务3与任务4 由于是并行处理先后顺序不定。
    
    1. 以下代码运行结果如何?
      - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"1");
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"2");
        });
        NSLog(@"3");
     }
    // 只输出:1。(主线程死锁)
    
    1. 什么是 RunLoop
      从字面上讲就是运行循环,它内部就是do-while循环,在这  个循环内部不断地处理各种任务。
    一个线程对应一个RunLoop,基本作用就是保持程序的持续运行,处理app中的各种事件。通过runloop,有事运行,没事就休息,可以节省cpu资源,提高程序性能。
    
      主线程的run loop默认是启动的。iOS的应用程序里面,程序启动后会有一个如下的main()函数
      int main(int argc, char * argv[]) {
         @autoreleasepool {
             return UIApplicationMain(argc, argv, nil,   NSStringFromClass([AppDelegate class]));
         }
     }
    
    1. 什么是 Runtime

    Runtime又叫运行时,是一套底层的C语言API,其为iOS内部的核心之一,我们平时编写的OC代码,底层都是基于它来实现的。
    

    联系

    github地址:https://github.com/meetly
    希望大家多多指教!

    相关文章

      网友评论

      • 默默_David:第一题加点自己的理解哈,
        struct objc_super {
        id receiver;
        Class superClass;
        };
        对于实例化的对象而言,super中的receiver也是指向当前对象本身,所以最后使用super调用的还是和self一样。
        15题应该是dispatch_async(dispatch_get_main_queue(), ^{ });,原文中使用的是同步
      • 午马丶:楼主能写篇介绍Instruments的那几个常用工具吗
      • 平凡的世界_风清扬:非常好,感谢楼主分享,mark

      本文标题:iOS最新面试题汇总(三)

      本文链接:https://www.haomeiwen.com/subject/gokafxtx.html