2017年面试总结

作者: 奶茶大叔 | 来源:发表于2020-08-21 11:29 被阅读0次

    1.Runtime的理解和项目运用
    2.TableView的优化

    • 正确使用reuseIdentifier来重用Cells
    • 尽量使所有的view 不透明,包括Cell自身
    • 尽量少用或不用透明图层
    • 如果Cell内现实的内容来自web,使用异步加载,缓存请求结果
    • 减少subviews的数量
    • 在heightForRowAtIndexPath:中尽量不使用cellForRowAtIndexPath:,如果你需要用到它,只用一次然后缓存结果
    • 尽量少用addView给Cell动态添加View,可以初始化时就添加,然后通过hide来控制是否显示
    • 提前计算并缓存好高度(布局),因为heightForRowAtIndexPath:是调用最频繁的方法;
    • 异步绘制,遇到复杂界面,遇到性能瓶颈时,可能就是突破口;
    • 滑动时按需加载,这个在大量图片展示,网络加载的时候很管用!(SDWebImage已经实现异步加载,配合这条性能杠杠的)。

    3.二叉树,快速排序,冒泡排序(实际应用题)
    4.Socket是如何实现的
    5.[[person alloc] init]内存栈结构问题
    6.无限展开列表实现
    7.大图片资源分段加载问题,类似于地图
    8.核心动画,Quartz2D
    9.设计模式理解MVC MVVM MVP 项目运用

    image.jpeg

    10.手写约束
    11.ARC内存管理解实现
    oc 中内存的管理主要依赖引用计数,而对引用计数的影响又依赖修饰属性,
    ①修饰属性:
    读写控制:
    readwrite:可读可写,会生成getter和setter方法。
    readonly:只读,只会生成getter方法,不会生成setter方法。
    引用方式:
    copy:拷贝,复制一个对象并创建strong关联,引用计数为1 ,原来对象计数不变。
    assign:赋值,不涉及引用计数的变化,弱引用。ARC中对象不能使用assign,但原始类型(BOOL、int、float)仍然可以使用。
    retain:持有,对原对象引用计数加1,强引用。ARC中使用strong。
    weak:赋值(ARC),比assign多了一个功能,对象释放后把指针置为nil,避免了野指针。
    strong:持有(ARC),等同于retain。
    ②修饰变量(修饰不使用@property 定义时,比如函数内的局部变量)
    __strong:是缺省的关键词,强引用。
    __weak:声明了一个可以自动置 nil 的弱引用(ARC 中)。
    __unsafe_unretained:声明一个弱引用,但是不会自动 nil 化(只有 iOS 4 才
    应该使用)。
    __autoreleasing:用来修饰一个函数的参数,这个参数会在函数返回的时候被
    自动释放(类似 autorelease)。
    (3)默认的引用计数:
    alloc:分配对象,分配后引用计数为 1。
    autorelease:对象引用计数减 1,但如果为 0 不马上释放,等待最近一个 pool 时释放。
    12.第三方框架的版本号
    13.最新在看哪些新技术,iOS版本特点,技术博客,自己多久会写Demo
    14.iOS消息转发机制
    15.git和SVN优缺点
    ①GIT是分布式的,SVN是集中式
    ②GIT把内容按元数据方式存储,而SVN是按文件
    ③GIT分支和SVN的分支不同
    ④GIT没有一个全局的版本号,而SVN没有
    ⑤GIT的内容完整性要优于SVN

    16.数据库多表查询,sqlite和coredata优缺点 sqlite语句
    ①sqlite语句

    //建表语句:
    CREATE TABLE IF NOT EXISTS t_class (id integer primary key autoincrement ,name text, age integer);
    //删除表:
    drop table if exists t_person;
    //插入数据 字符串使用''括住.
    INSERT INTO t_class (name ,age) values ('hm13' ,7);
    //更新数据
    UPDATE t_class SET name = 'lisi' WHERE age < 8; 
    //删除数据
    DELETE FROM t_class WHERE name = 'zhangsan';
    //查询数据
    SELECT name , age  FROM t_class  WHERE age > 6 LIMIT 5;
    

    ②多表查询
    外连接可分为:左连接、右连接、完全外连接。

    左连接  left join 或 left outer join
    右连接  right join 或 right outer join
    完全外连接  full join 或 full outer join
    内连接  join 或 inner join
    交叉连接 cross join
    

    17.什么时候用到单例

    第一、基本概念 单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问。

    第二、在IOS中使用单例模式的情况

    1.如果说创建一个对象会耗费很多系统资源,那么此时采用单例模式,因为只需要一个实例,会节省alloc的时间

    2.在IOS开发中,如果很多模块都要使用同一个变量,此时如果把该变量放入单例类,则所有访问该变量的调用变得很容易,否则,只能通过一个模块传递给另外一个模块,这样增加了风险和复杂度

    第三、创建单例模式的基本步骤

    1.声明一个单例对象的静态实例,并初始化为nil
    2.声明一个类的工厂方法,生成一个该类的实例,并且只会生成一个
    3.覆盖allcoWithZone方法,确保用户在alloc 时,不会产生一个多余的对象
    4.实现NSCopying协议,覆盖release,autorelease,retain,retainCount方法,以确保只有一个实例化对象
    5.在多线程的环境中,注意使用@synchronized关键字

    ①单例模式:饿汉式 ,懒汉式,登记式

    当A、B线程并发的情况下,会创建出两个实例来,也就是单例的控制在并发情况下失效了。
    (2)饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。
    (3)如何实现懒汉式的线程安全呢?

    当然懒汉式也是可以实现线程安全的,只要加上synchronized即可,如下:

    1.  public static synchronized Singleton getInstance(){} 
    

    但是这样一来,会降低整个访问的速度,而且每次都要判断。那么有没有更好的方式来实现呢?

    (4)双重检查加锁

    可以使用"双重检查加锁"的方式来实现,就可以既实现线程安全,又能够使性能不受到很大的影响。那么什么是"双重检查加锁"机制呢?
    所谓双重检查加锁机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。
    双重检查加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

    看看代码可能会更加清楚些。示例代码如下:

    1.  public class Singleton {  
    2.  /**  
    3.  * 对保存实例的变量添加volatile的修饰  
    4.  */  
    5.  private volatile static Singleton instance = null;  
    6.  private Singleton(){  
    7.  }  
    8.  public static  Singleton getInstance(){  
    9.  //先检查实例是否存在,如果不存在才进入下面的同步块  
    10.  if(instance == null){  
    11.  //同步块,线程安全地创建实例  
    12.  synchronized(Singleton.class){  
    13.  //再次检查实例是否存在,如果不存在才真正地创建实例  
    14.  if(instance == null){  
    15.  instance = new Singleton();  
    16.  }  
    17.  }  
    18.  }  
    19.  return instance;  
    20.  }  
    21.  } 
    

    这种实现方式可以实现既线程安全地创建实例,而又不会对性能造成太大的影响。它只是在第一次创建实例的时候同步,以后就不需要同步了,从而加快了运行速度。

    ②iOS单例的创建与销毁
    18.如何让程序后台不退出
    19.UIKit Foundation区别
    20.GCD底层实现和如何添加操作依赖,GCD 和NSOperation区别

    image.jpeg

    ⑴底层实现

    ①IOS和OS X的核心是XNU内核,GCD是基于XUN内核实现的
    ②GCD的API全部在libdispatch库中
    ③GCD的底层实现主要有Dispatch Queue 和Dispatch Source
    Dispatch Queue :管理block操作
    Dispatch Source :处理事件(比如线程间通信)
    ⑵GCD操作依赖


    image.jpeg

    队列:串行队列,并行队列,全局队列,主队列

    image.jpeg

    串行队列
    同步执行任务 会在当前线程内执行 # 不一定是主线程
    异步执行 会创建一个新的线程来执行任务

    并行队列,

    同步的方式执行 并不会开辟新线程

    异步的方式执行 会创建多个新的线程来执行多个任务 是随机无序执行的

    1. //串行队列 同步执行任务 会在当前线程内执行 //所以打印的会是当前线程的编号 不一定是主线程
    2.  -(void)demo  
    3.  {  
    4.  //串行队列 DISPATCH_QUEUE_SERIAL  
    5.  //并行队列 DISPATCH_QUEUE_CONCURRENT  
    6.  dispatch_queue_t queue=dispatch_queue_create("itcast", DISPATCH_QUEUE_SERIAL);  
    
    8.  //创建任务  
    9.  dispatch_block_t task1=^{  
    10.  NSLog(@"%@  同步执行了方法1",[NSThread currentThread]);  
    11.  };  
    
    13.  dispatch_block_t task2=^{  
    14.  NSLog(@"%@  同步执行了方法2",[NSThread currentThread]);  
    15.  };  
    16.  //加入队列  
    
    18.  //同步的方式 dispatch_sync  
    19.  //异步的方式 dispatch_async 
    20.  dispatch_sync(queue, task1);  
    
    22.  dispatch_sync(queue, task2);  
    23.  }  
    

    ⑶区别

    ①GCD是纯C语言的API, NSOperationQueue是基于GCD的OC版本封装
    ②GCD只支持FIFO的队列,NSOperationQueue可以很方便地调整执行顺序 设置最大并发数量
    ③NSOperationQueue 可以轻松地在operation 间设置依赖关系,而GCD需要写很多的代码
    ④NSOperationQueue支持KVO,可以监测operation是否正在执行(is Executed),是否结束(is finished),是否取消( is canceld);
    ⑤ GCD的执行速度比NSOperationQueue快

    总结:
    NSOperationQueue 任务之间有依赖/或者要监听任务的执行情况
    GCD 任务之间不太互相依赖

    21.js交互的方式

    iOS7之后

    ①JavaScriptCore
    JavaScriptCore中类及协议:

    • JSContext:给JavaScript提供运行的上下文环境
    • JSValue:JavaScript和Objective-C数据和方法的桥梁
    • JSManagedValue:管理数据和方法的类
    • JSVirtualMachine:处理线程相关,使用较少
    • JSExport:这是一个协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议

    自定义JSObjcDelegate协议,而且此协议必须遵守JSExport这个协议,自定义协议中的方法就是暴露给web页面的方法。在webView加载完毕的时候获取JavaScript运行的上下文环境,然后再注入桥梁对象名为Toyun,承载的对象为self即为此控制器,控制器遵守此自定义协议实现协议中对应的方法。在JavaStript调用完本地应用的方法做完相对应的事情之后,又回调了JavaStript中对应的方法,从而实现了web页面和本地应用之间的通讯。

    JavaScriptCore使用注意
    JavaStript调用本地方法是在子线程中执行的,这里要根据实际情况考虑线程之间的切换,而在回调JavaScript方法的时候最好是在刚开始调用此方法的线程中去执行那段JavaStript方法的代码

    ②拦截协议
    拦截协议这个适合一些比较简单的一些情况,不需要引入什么框架,只需要web前端配合一下就好
    ③第三方框架WebViewJavaScriptBridge github
    iOS8之后
    WKWebView的代理方法实现JS交互(WKScriptMessageHandler)

    23.多线程安全的几种解决办法及多线程安全如何控制
    ① 只在主线程刷新访问UI
    ② 如果要防止资源抢夺,得用synchronized进行加锁保护
    ③ 如果异步操作要保证线程安全等问题,尽量使用GCD(有些函数默认就是安全的)

    24.NSTimer和Runloop
    25.网络传输加密

    相关文章

      网友评论

        本文标题:2017年面试总结

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