zoukankan      html  css  js  c++  java
  • iOS基础笔试题

    前言

    下文转载自https://mp.weixin.qq.com/s?__biz=MzA4ODk0NjY4NA==&mid=454115946&idx=1&sn=c7f1b50151b2c1f1383f217cfc373e5f&scene=1&srcid=0415AOiFsX0EZNXa4kelypdA&key=b28b03434249256bc43abf211f946e097bba6a29435ed7523f915e436c4bb17cdbd442a60625aa61c188386f768579ab&ascene=0&uin=MTYwODEwMjY2MA%3D%3D&devicetype=iMac+MacBookPro10%2C1+OSX+OSX+10.11.3+build(15D21)&version=11020201&pass_ticket=Ho6XfSRq5gjEkU%2FiFQVr%2FjCNQcL9jY%2F%2B0J%2BOdP8aUyJaH3CPEGzVnzaIqc6B%2FXQy

    1. #import和#include的区别?

     

    参考答案:

    #import是Objective-C导入头文件的语法,可保证不会重复导入。

    #include是C/C++导入头文件的语法,如果是Objective-C与C/C++混编码,对于C/C++类型的文件,还是使用#include来引入,这种写法需要添加防重复导入的语法。

    2. @class的作用

     

    参考答案:

    @class一般用于头文件中通过前向声明,就可以声明了,但是在.m文件中还是需要使用#import进来的。它的作用只是前向声明。

    3. 用NSLog函数输出一个浮点类型,结果四舍五入,并保留一位小数

     

    参考答案:

    float money = 1.011;

    NSLog(@"%.1f", money);

    使用%f来格式化,其中要保留一位小数,因此再用%.1f就是保留一位。

    4.property属性的修饰符有什么样的作用

     

    参考答案:

    property是属性访问声明,扩号内支持以下几个属性:

    getter=getName、setter=setName:设置setter与getter的方法名

    readwrite、readonly:设置可供访问级别

    assign:方法直接赋值,不进行任何retain操作,为了解决原类型与环循引用问题

    retain:其setter方法对参数进行release旧值再retain新值,所有实现都是这个顺序

    copy:其setter方法进行copy操作,与retain处理流程一样,先对旧值release,再copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。

    nonatomic:非原子性访问,不加同步, 多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。

    5. self.name=@object和name=@object有什么不同?

     

    参考答案:

    self.name =”object”:会调用对象的setName()方法;name = “object”:会直接把"object"字符串赋值给当前对象的name属性。

    6. viewDidLoad、loadView和viewDidUnload何时调用

     

    参考答案:

    viewDidLoad在view加载完成时调用,loadView在controller的view为nil时调用。对于viewDidUnload现在已经不能直接调用了。

    7. objective-c中的可变与不可变词典

     

    参考答案:

    可变字典就是可以增、删、改操作的字典,对应于NSMutableDictionary类型。

    不可变字典就是不能执行增、删、改操作的字典,对应于NSDictionary类型。

    8.Objective-C的内存管理

     

    参考答案: 

    现在内存管理几乎都采用ARC,也就是Automatic Reference Counting,意思是自动引用计数。由编译器在编译时自动为添加retain、release等代码。

    如果问的MRC,也就是Manual Reference Counting,意思是手动内存管理。

    黄金法则:谁使对象的引用计数+1,不再使用该对象时,谁就应该使该对象的引用计数-1。

    9. 自动生成getter/setter方法

     

    参考答案:

    对于以前的代码,那时还没有property,使用这样的方法来创建:

    - (void)setName:(NSString *)aName;

    - (NSString *)name;

    在后面有了property,直接使用@property (nonatomic, copy) NSString *name这样的方法来声明,编译器会自动生成getter/setter方法并生成一个_name成员变量。

    10. 什么是MVC

     

    参考答案:

    我相信大部分人在被问到这个问题时,都会回答M就是Model,V就是View,C就是Controller。这都是停留在概念上的回答,明显没有什么工作经验。对于一个对框架和架构有一定的思想的人,回答时会从项目的耦合度、团队开发如何减少冲突、如何降低团队与团队之间的沟通成本、如何将M、V、C之间按照既定的标准建立沟通的桥梁。

    Model用于处理数据,通常来说,Model中会包含多个字段,用于存储数据。但是,Model还会有一部分逻辑,比如说:

    @interface TestModel: HYBBaseModel 

     // 这个是接口返回的字段,1表示XXX,2表示YYY,3表示ZZZ

    @property (nonatomic, assign) NSUInteger type; 

    // 这个不是接口返回的字段,但是由于`type`字段是一个数值,不是`view`需要显示的数据

    // 所以我们最好将逻辑统一放到这里来,外部只管获取最终显示需要的值即可。即使哪天接口

    // 返回的字段变化或者增加什么新的值,只需要处理这个模型内部就好了。 

    @property (nonatomic, copy, readonly) NSString relationship;

    @end

    对于View,不应该包含逻辑,应该根据模型直接获取数据。

    对于Controller,大部分交互逻辑都集中到了这里,所有View需要的数据,都是通过Controller提取Model然后交给view去显示数据。

    11. 重写getter/setter方法

    假设声明属性:

    @property (nonatomic, copy) NSString *blogName;

    重写这个属性的getter/setter方法:

    参考答案:

    这里一旦连getter方法也重写,编译器不会给我们自动生成成员变量_blogName,因此我们需要在类的声明中添加一个成员变量_blogName:

    @interface Demo () {

       NSString *_blogName;

    }

     @end

    在自动内存管理下(ARC):

    - (void)setBlogName:(NSString *)aName {

       if (_blogName != aName) {

          _blogName = nil;

          _blogName = [aName copy];

       }

    }

    - (NSString *)blogName {

      return _blogName;

    }

    对于手动内存管理(MRC):

    - (void)setBlogName:(NSString *)aName {

       if (_blogName != aName) {

          [_blogName release];

          _blogName = nil;

          _blogName = [aName copy];

       }

    }

    - (NSString *)blogName {

      return _blogName;

    }

    12. obj在编译时和运行时分别时什么类型的对象

    如下面的代码,obj在编译时和运行时分别时什么类型的对象:

    NSString *obj = [[NSData alloc] init];

    参考答案:

    在编译时,我们所声明的obj是NSString *类型,因此是NSString类型对象。在运行时,由于指针obj所指向的是NSData类型对象的内存,因此实际上是NSData类型的对象。在编译时,这一行代码会转换成类似这样:

    NSString *obj = ((id (*)(id, SEL))objc_msgSend)([NSData class], @selector(alloc));

    obj = ((id (*)(id, SEL))objc_msgSend)((id)obj, @selector(init));

    由于在编译时,转换成id,因此可以用NSString *指向NSData对象,而id是具备运行时特性的,因此在链接时,通过id的isa指针可以找到其所属的类,因此最终类型还是通过isa确定其所属类型。

    13. id声明的对象有什么特性?

    id类型可以指向任何类型的对象。

    参考答案:

    我们先看看其定义:

    /// Represents an instance of a class.

    struct objc_object {

        Class isa  OBJC_ISA_AVAILABILITY;

    };

    /// A pointer to an instance of a class.

    typedef struct objc_object *id;

    可其定义可知id类型是一个指向objc_object结构体类型的指针,这个结构体只有一个指向对象无类的指针isa,因此id可以指向任何类型的对象,故其具备运行时特性。

    14. iOS设备性能测试

    在实际开发中,我们经常需要对应用瘦身,因此对性能的检测是很重要的。

    参考答案:

    使用Profile-> Instruments ->Time Profiler可以检测性能。

    15. Objective-C中有私有方法、私有变量么?

    我记得曾经我就被这么问过,不知道大家有没有遇到过。

    参考答案:

    在类的.m实现文件内声明,就可以作为私有方法、私有变量。但是,并不是绝对的私有,如果外部知道有这么个方法,一样可以调用,而且不会报错。就像苹果公司没有公开出来的API,只要我们通过其它方式了解到api就可以调用。于是苹果审核时经常由于使用了私有api而打回来了。

    16. 简述tableview的重用机制

    曾经笔者面试时,也被问到这个问题。

    参考答案: 

    [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]

     这个方法就是重用机制的核心了。比如,有一个界面可显示10个cell,那么创建10次cell,并给cell指定同样的重用标识(当然,可以为不同显示类型的cell指定不同的标识)并且10个cell将全部都加入到visiableCells数组,reusableTableCells为空.

    滚动tableView,当有一个cell完全移出屏幕时,这个cell就会被加入到reusableTableCells。而新出现的那个cell将加入到visiableCells,而这个cell就是被重用的。

    如果要让tableview不重用,不设置reuseIdentifier就可以了。

    17. nil与NULL的区别

     

    参考答案:

    nil和C语言的NULL相同,在objc/objc.h中定义。nil表示Objective-C对象的值为空。在C语言中,指针的空值用NULL表示。在Objective-C中,nil对象调用任何方法表示什么也不执行,也不会崩溃。

    18. Category是什么,何时使用?

     

    参考答案:

    Category就是所谓的扩展。

    有时我们需要在一个已经定义好的类中增加一些方法,而不想去重写该类,这时候使用扩展就很好。比如,当工程已经很大,代码量比较多,或者类中已经有很多方法,已经有其他代码调用了该类创建对象并使用该类的方法时,可以使用类别对该类扩充新的方法。

    笔者所到公司之处,都会根据公司的UI风格定制一套UI组件,统一全局的风格。本人向来不喜欢用xib/storyboard开发,因为维护成本太高了。我们不能通过继承的方式定制各种组件吧?所以这个时候使用扩展是最佳时期.

    19. 什么是Delegate?常用场景?

     

    参考答案:

    Delegate就是所谓的代理,代理是一种设计模式。在iOS开发中,会使用到大量的代理,而代理设计模式是苹果中的标准设置模式。

    常用场景有反向传值。比如:苹果的蓝牙,我们进入到下一个界面去打开或者关闭蓝牙,当操作之后需要将状态反馈到前一个界面,并更新显示。对于这种状态,使用代理设计模式是很标准的模式。

    20. 什么是单例,如何设计单例?

     

    参考答案:

    单例就是全局都只有一个对象存在,而且是在整个App运行过程中都存在。每个App都会有单例,比如UIApplication。而我们在做用户数据存储时,通常都会用单例存储,因为应用在所有操作中,经常要求先登录。

    下面这种写法是最常用的写法,这个是线程安全的。

    + (instancetype)shared {

      static HYBUserManager *sg_userManager = nil;

      static dispatch_once_t onceToken;

      dispatch_once(&onceToken, ^{

        if (sg_userManager == nil) {

          sg_userManager = [[HYBUserManager alloc] init];

        }

      });

      return sg_userManager;

    }

    21. 什么是通知?

     

    参考答案:

    在iOS中,通知是非常常用的设计模式。它是多对多的关系。关于通知,由于这一节比较重要,单独写成一篇文章,后续发出!

    写在最后

    文章中难免有说得不合理的地方,如果您认为说法不正确或者哪里有错误的地方,请在评论中留言,笔者会在第一时间修正!!!

  • 相关阅读:
    java中的 equals 与 ==
    String类的内存分配
    SVN用命令行更换本地副本IP地址
    npoi 设置单元格格式
    net core 微服务框架 Viper 调用链路追踪
    打不死的小强 .net core 微服务 快速开发框架 Viper 限流
    net core 微服务 快速开发框架 Viper 初体验20201017
    Anno 框架 增加缓存、限流策略、事件总线、支持 thrift grpc 作为底层传输
    net core 微服务 快速开发框架
    Viper 微服务框架 编写一个hello world 插件02
  • 原文地址:https://www.cnblogs.com/smile-smile/p/5394304.html
Copyright © 2011-2022 走看看