iOS精选面试题

iOS 头条面试整理

2020-03-29  本文已影响0人  赖晓嘉LMT

1,禁止init初始化

开发中,如果想指定初始化方法,不允许调用者乱用,可以用这两个宏:
NS_DESIGNATED_INITIALIZER,(- (instancetype)init NS_DESIGNATED_INITIALIZER;)
NS_UNAVAILABLE (- (instancetype)init NS_UNAVAILABLE;)

2,self.xx和_xx 区别

self.xx是调用的xx属性的get/set方法,而_xx则只是使用成员变量_xx,并不会调用get/set方法。两者的更深层次的区别在于,通过存取方法访问比直接访问多做了一些其他的事情(例如内存管理,复制值等),例如如果属性在@property中属性的修饰符有retain,那么当使用self.xx的时候相应的属性的引用计数器由于生成了setter方法而进行加1操作,此时的retaincount为2。

3,block本质上是什么,如何避免循环引用

  1. isa 指针,所有对象都有该指针,用于实现对象相关的功能。
  2. flags,用于按 bit 位表示一些 block 的附加信息,
  3. reserved,保留变量。
  4. invoke,函数指针,指向具体的 block 实现的函数调用地址。
  5. descriptor, 表示该 block 的附加描述信息
  6. variables,capture 过来的变量,block 能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中

4,copy修饰符的作用

拷贝一份不可变的副本,属性值不受外部变量变化而变化,相应的修饰可变对象时,会导致调用增删改的方式崩溃

5,lldb 如何观察kvo

watchpoint
iOS开发当中有一个重要的概念KVO,我们会给一个重要的变量设置一个观察者,用以在它发生变化的时候做出相应的操作。在调试过程中我们也可以借助LLDB来监视某个变量或某一块内存的读写情况。
我们利用watchpoint指令来监视变量情况。
p obj->isa 可以在set过程观察obj isa指针的变化

6,常见的锁有哪些

参考别人总结的

7,常用的多线程管理,GCD如何实现线程的依赖和返回

8,cocopods PodSpecs 所用 install和update区别

pod install的话,只会处理没有记录在Podfile.lock中的依赖库,会查找匹配Podfile中描述的版本。对于已经记录在Podfile.lock的依赖库,会下载Podfile.lock文件中记录的版本,而不会检查是否有更新。当然,如果你约束了pods的版本的话,会按照你指定的版本进行安装,同时也会更新Podfile.lock记录的信息。
pod update 要更新库的名字
这个命令会忽略Podfile.lock中的记录,直接去找符合Podfile文件中的该依赖库 的约束版本(无约束的话就是最新版本)。

9,Runloop与performSelector

指定延时0 并不会立即执行选择器,而是在线程循环运行中排队,并尽快执行
当调用 NSObject 的 performSelecter:afterDelay: 后,实际上其内部会创建一个 Timer 并添加到当前线程的 RunLoop 中。所以如果当前线程没有 RunLoop,则这个方法会失效。
当调用 performSelector:onThread: 时,实际上其会创建一个 Timer 加到对应的线程去,同样的,如果对应线程没有 RunLoop 该方法也会失效。

10

沙盒结构

1.document:
应用程序在运行时生成的一些需要长久保存的重要数据放在此文件中。通过iTunes,iCloud备份时,会备份此目录下的数据。iTunes共享文件时,可以共享此文件目录。

2.Library:
a.Cache:存放缓存文件,比如从网路上下载的数据或数据。一般用来保存应用需要长期使用的,数据量大,不需要备份的非重要数据。iTunes,iCloud备份时不会备份此目录下的数据

b.Prefrence:保存应用的所有偏好设置,比如账号,设置等。由系统自动管理。iTunes,iCloud备份时会备份此目录下的数据和文件(NSUerdefault 就在保存在这里的一个plist上)

3.tmp:
用于保存应用在运行时产生的一些临时数据文件,手机重启,系统空间不足的,关闭应用等场景下可能会删除该文件下的文件。iTunes备份时不会备份该目录下的文件

11,交替打印线程

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    NSCondition *lock = [NSCondition new];
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<100; i++) {
            [lock lock];
            if (i%2 == 0) {
                NSLog(@"偶数%zd,%@",i,[NSThread currentThread]);
                [lock signal];
                [lock wait];
            }
            [lock unlock];
            
        }
        
    });
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<100; i++) {
            [lock lock];
            if (i%2 != 0) {
                NSLog(@"奇数%zd,%@",i,[NSThread currentThread]);
                [lock signal];
                [lock wait];
            }
            [lock unlock];
            
        }
    });

12,链表的反转(非递归和递归)

     - (Node *) reverseList(Node*) {
         ListNode root = head;
         ListNode pre = null;
         ListNode next = null;
         if(head == null){
             return null;
         }
         while(root.next != null){
            next = root.next;
            root.next = pre;
            pre = root;
            root = next;
          }
        root.next = pre;
        return root;
        }
        //递归
       - (Node *) reverseList(Node*) {
         if(head == null || head.next == null){
              return head;
         }else{
            ListNode newhead = reverseList(head.next);
            head.next.next = head;
            head.next = null;
            return newhead;
         }
       }
上一篇 下一篇

猜你喜欢

热点阅读