自己整理的iOS面试题

由于之前在公司负责技术面试,因此整理了一份面试题。现在自己也要找工作了,正好看看复习一下相关知识。

 

1.Block循环引用问题,OC怎么解决?Swift怎么解决?UIView animation为什么没有循环引用?

 

Block有几种类型?(GlobalBlock StackBlock MallocBlock)

 

__weak和__block区别?(__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型。__block对象可以在block中被重新赋值,__weak不可以。__block对象在ARC下可能会导致循环引用,非ARC下会避免循环引用,__weak只在ARC下使用,可以避免循环引用。)

 

为什么用copy修饰block?ARC下strong行不行?非ARC下retain行不行?为什么?(非ARC下block访问外部局部变量,block存放在栈里面,用copy会把它放在堆里面。ARC下block访问外部局部变量,block存放在堆里面。strong也可以,系统自动做了copy动作,咱们拿到的block已经在堆里了)

 

2.property属性有哪些修饰符?(getter, setter, atomic, nonatomic, readwrite, readonly, assign, retain, copy, string, weak)

 

assign和weak的区别

1)weak 此特质表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同assign类似, 然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。 而 assign 的“设置方法”只会执行针对“纯量类型” (scalar type,例如 CGFloat 或 NSlnteger 等)的简单赋值操作。

2)assigin 可以用非OC对象,而weak必须用于OC对象

 

NSString用copy和strong修饰有什么问题?

 

深拷贝(有一个是Mutable就是深拷贝,值拷贝)、浅拷贝(引用拷贝,两个指针指向同一内存地址)的问题。

 

@synthesize和@dynamic分别有什么作用

1)@property有两个对应的词,一个是@synthesize,一个是@dynamic。如果@synthesize和@dynamic都没写,那么默认的就是@syntheszie var = _var;

2)@synthesize的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法。

3)@dynamic告诉编译器:属性的setter与getter方法由用户自己实现,不自动生成。(当然对于readonly的属性只需提供getter即可)。假如一个属性被声明为@dynamic var,然后你没有提供@setter方法和@getter方法,编译的时候没问题,但是当程序运行到instance.var = someVar,由于缺setter方法会导致程序崩溃;或者当运行到 someVar = var时,由于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。

 

3.多线程问题:有几种方式?(pThread, NSThread, GCD, NSOperation)

 

dispatch_group(下载图片然后处理的问题)

 

NSOperation(添加依赖:确定执行顺序)

 

加锁的方式有几种?(@synchronized(id anObject),NSLock, NSRecursiveLock递归锁,NSConditionLock条件锁,NSDistributedLock分布锁,互斥锁,自旋锁)

 

dispatch_barrier_async的作用是什么?

在并行队列中,为了保持某些任务的顺序,需要等待一些任务完成后才能继续进行,使用 barrier 来等待之前任务完成,避免数据竞争等问题。 dispatch_barrier_async 函数会等待追加到Concurrent Dispatch Queue并行队列中的操作全部执行完之后,然后再执行 dispatch_barrier_async 函数追加的处理,等 dispatch_barrier_async 追加的处理执行结束之后,Concurrent Dispatch Queue才恢复之前的动作继续执行。

 

category中怎么增加属性?

objc_setAssociatedObject

objc_getAssociatedObject

 

runloop和线程的关系?

1. 主线程的run loop默认是启动的。main()函数中,重点是UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象,这就解释了:为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。

2.对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。

3.在任何一个 Cocoa 程序的线程中,都可以通过以下代码来获取到当前线程的 run loop 。

 

runloop有几种mode?

  • NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
  •  
  • UITrackingRunLoopMode:ScrollView滑动时
  •  
  • UIInitializationRunLoopMode:启动时
  •  
  • NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合
  •  

 

内存管理问题:

ARC、MRC内存管理机制

 

ARC通过什么方式帮助开发者管理内存?

编译时根据代码上下文,插入 retain/release

 

KVC机制通过key找到value的原理

当通过KVC调用对象时,比如:[self valueForKey:@”someKey”]时,程序会自动试图通过下面几种不同的方式解析这个调用。

首先查找对象是否带有 someKey 这个方法,如果没找到,会继续查找对象是否带有someKey这个实例变量(iVar),如果还没有找到,程序会继续试图调用 -(id) valueForUndefinedKey:这个方法。如果这个方法还是没有被实现的话,程序会抛出一个NSUndefinedKeyException异常错误。

补充:KVC查找方法的时候,不仅仅会查找someKey这个方法,还会查找getsomeKey这个方法,前面加一个get,或者_someKey以_getsomeKey这几种形式。同时,查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在。

设计valueForUndefinedKey:方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。

 

 

KVO的实现方式

当你观察一个对象时,一个新的类会被动态创建。这个类继承自该对象的原本的类,并重写了被观察属性的 setter 方法。重写的 setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象:值的更改。最后通过 isa 混写(isa-swizzling) 把这个对象的 isa 指针 ( isa 指针告诉 Runtime 系统这个对象的类是什么 ) 指向这个新创建的子类,对象就神奇的变成了新创建的子类的实例。

 

lldb调试常用命令 breakpoint ni si po p

 

MVC MVVM设计模式

 

runtime class 相关

 

class在runtime中是个什么类型?typedef struct objc_class * Class; 是个objc_class的结构体指针。

 

objc_class结构体的定义:

struct objc_class {

 

        Class isa  OBJC_ISA_AVAILABILITY;

 

 

        #if !__OBJC2__

 

        Class super_class                       OBJC2_UNAVAILABLE;  // 父类

 

        const char *name                        OBJC2_UNAVAILABLE;  // 类名

 

        long version                            OBJC2_UNAVAILABLE;  // 类的版本信息,默认为0

 

        long info                               OBJC2_UNAVAILABLE;  // 类信息,供运行期使用的一些位标识

 

        long instance_size                      OBJC2_UNAVAILABLE;  // 该类的实例变量大小

 

        struct objc_ivar_list *ivars            OBJC2_UNAVAILABLE;  // 该类的成员变量链表

 

        struct objc_method_list **methodLists   OBJC2_UNAVAILABLE;  // 方法定义的链表

 

        struct objc_cache *cache                OBJC2_UNAVAILABLE;  // 方法缓存

 

        struct objc_protocol_list *protocols    OBJC2_UNAVAILABLE;  // 协议链表

 

        #endif

 

} OBJC2_UNAVAILABLE;

 

对象的isa指针指向谁?类有没有isa指针?(类) 类的isa指针指向谁?元类有没有isa指针?(元类metaClass)元类的isa指针指向谁?(根元类)根元类有没有isa指针?根元类的isa指针指向谁?(他自己)

 

super_class 指向该类的父类,如果该类已经是最顶层的根类(如NSObject或NSProxy),则super_class为NULL

 

在objc_class中,所有的成员变量、属性的信息是放在链表ivars中的。

Objective-C不支持往已存在的类中添加实例变量,因此不管是系统库提供的提供的类,还是我们自定义的类,都无法动态添加成员变量。但如果我们通过运行时来创建一个类的话,又应该如何给它添加成员变量呢?这时我们就可以使用class_addIvar函数了。不过需要注意的是,这个方法只能在objc_allocateClassPair函数与objc_registerClassPair之间调用。另外,这个类也不能是元类。

 

objc_method_list方法链表中存放的是该类的成员方法(-方法),类方法(+方法)存在meta-class的objc_method_list链表中。

 

isMemberOfClass 和 isKindOfClass 联系与区别

联系:两者都能检测一个对象是否是某个类的成员

区别:isKindOfClass 不仅用来确定一个对象是否是一个类的成员,也可以用来确定一个对象是否派生自该类的类的成员 ,而isMemberOfClass 只能做到第一点。

举例:如 ClassA派 生 自NSObject 类 , ClassA *a = [ClassA alloc] init];,[a isKindOfClass:[NSObject class]] 可以检查出 a 是否是 NSObject派生类 的成员,但 isMemberOfClass 做不到。

 

iOS 开发中数据持久性有哪几种?

数据存储的核心都是写文件。

属性列表:只有NSString、NSArray、NSDictionary、NSData可writeToFile;存储依旧是plist文件。plist文件可以存储的7中数据类型:array、dictionary、string、bool、data、date、number。

对象序列化(对象归档):对象序列化通过序列化的形式,键值关系存储到本地,转化成二进制流。通过runtime实现自动化归档/解档,请参考这个文章。实现NSCoding协议必须实现的两个方法:

1.编码(对象序列化):把不能直接存储到plist文件中得到数据,转化为二进制数据,NSData,可以存储到本地;

2.解码(对象反序列化):把二进制数据转化为本来的类型。

SQLite 数据库:大量有规律的数据使用数据库。

CoreData :通过管理对象进行增、删、查、改操作的。它不是一个数据库,不仅可以使用SQLite数据库来保持数据,也可以使用其他的方式来存储数据。如:XML。

Realm

 

对象可以被copy的条件

只有实现了NSCopying和NSMutableCopying协议的类的对象才能被拷贝,分为不可变拷贝和可变拷贝

- (id)copyWithZone:(NSZone *)zone

 

TCP和UDP的区别于联系

TCP为传输控制层协议,为面向连接、可靠的、点到点的通信;

UDP为用户数据报协议,非连接的不可靠的点到多点的通信;

TCP侧重可靠传输,UDP侧重快速传输。

 

TCP连接的三次握手

第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包,即SYN+ACK包,此时服务器进入SYN+RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次状态。

 

Scoket连接和HTTP连接的区别

HTTP协议是基于TCP连接的,是应用层协议,主要解决如何包装数据。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。

HTTP连接:短连接,客户端向服务器发送一次请求,服务器响应后连接断开,节省资源。服务器不能主动给客户端响应(除非采用HTTP长连接技术),iPhone主要使用类NSURLConnection。

Socket连接:长连接,客户端跟服务器端直接使用Socket进行连接,没有规定连接后断开,因此客户端和服务器段保持连接通道,双方可以主动发送数据,一般多用于游戏.Socket默认连接超时时间是30秒,默认大小是8K(理解为一个数据包大小)。

 

HTTP协议的特点,关于HTTP请求GET和POST的区别

GET和POST的区别:

HTTP超文本传输协议,是短连接,是客户端主动发送请求,服务器做出响应,服务器响应之后,链接断开。HTTP是一个属于应用层面向对象的协议,HTTP有两类报文:请求报文和响应报文。

HTTP请求报文:一个HTTP请求报文由请求行、请求头部、空行和请求数据4部分组成。

HTTP响应报文:由三部分组成:状态行、消息报头、响应正文。

GET请求:参数在地址后拼接,没有请求数据,不安全(因为所有参数都拼接在地址后面),不适合传输大量数据(长度有限制,为1024个字节)。

GET提交、请求的数据会附在URL之后,即把数据放置在HTTP协议头中。

以?分割URL和传输数据,多个参数用&连接。如果数据是英文字母或数字,原样发送,

如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密。

POST请求:参数在请求数据区放着,相对GET请求更安全,并且数据大小没有限制。把提交的数据放置在HTTP包的包体中.

GET提交的数据会在地址栏显示出来,而POST提交,地址栏不会改变。

传输数据的大小:

GET提交时,传输数据就会受到URL长度限制,POST由于不是通过URL传值,理论上书不受限。

安全性:

POST的安全性要比GET的安全性高;

通过GET提交数据,用户名和密码将明文出现在URL上,比如登陆界面有可能被浏览器缓存。

HTTPS:安全超文本传输协议(Secure Hypertext Transfer Protocol),它是一个安全通信通道,基于HTTP开发,用于客户计算机和服务器之间交换信息,使用安全套结字层(SSI)进行信息交换,即HTTP的安全版。

 

SVN、Git

 

Jenkins、Fastlane

 

推送、IM、地图、bug统计、分享

 

逆向开发,有没有逆向过别人的代码?怎么写Tweak插件?

 

安全:防注入、防越狱机器、代码混淆、加密、RSA、DES等

 

CoreGraphics坐标系和UIkit坐标系不一样,需要转换的问题

 

视频播放、点播、直播,ijkplayer,FFMPEG,rtmp,rtsp,hls

 

swift单例:static let shared = ABC()

 

class和struct的区别:class可以继承,类型转换允许在运行时检查和解释一个类实例的类型,析构器允许一个类实例释放任何其所被分配的资源,引用计数允许对一个类的多次引用。

struct是值类型,class是引用类型

 

swift中的Extension可以干什么?添加计算型属性和计算型类型属性,定义实例方法和类型方法,提供新的构造器,定义下标,定义和使用新的嵌套类型,使一个已有类型符合某个协议

 

swift 高阶函数:map, flatmap, reduce, filter

map,flatmap区别:flatmap会过滤掉nil,降维

 

swift访问权限:

private:private访问级别所修饰的属性或者方法只能在当前类里访问

fileprivate:fileprivate访问级别所修饰的属性或者方法在当前的Swift源文件里可以访问。

internal:默认访问级别。internal访问级别所修饰的属性或方法在源代码所在的整个模块都可以访问。

public:可以被任何人访问。但其他module中不可以被override和继承,而在module内可以被override和继承。

open:可以被任何人使用,包括override和继承。

 

final是干什么用的?不允许对其修饰的内容继承或重写

 

mutating是干嘛用的?修饰枚举和结构体,标识允许修改成员变量内容

 

defer干嘛用的?推迟执行,函数结束时才执行。

defer{1} defer{2} defer{3}执行顺序,3、2、1

 

inout干吗用的?传递引用类型,而不是值类型

 

swift 定义类方法?static 和 class区别?static 方法不可被重写,class方法可以被重写。struct enum 用static, class用class。类的成员变量用static声明。protocol中用static定义类方法,实现时struct enum用static,class可以用static,也可以用class

 

swift 可选值的概念,swift 可选绑定if let,  强制展开感叹号,带默认值取值:??

 

swift Tuple 元组

 

String和NSString最大的区别是什么?String是值类型,NSString是引用类型

 

try?和try!有什么区别?可选和强制

 

Typealias有什么用?typealias 是用来为已经存在的类型重新定义名字的,比如网络类中的Success闭包

 

associatedtype干什么用的?关联类型,协议中声明泛型,需要使用这个关键字

 

字符串截取怎么做?Swift4.0和上版本Swift在这方面有什么变化?

 

swift Closure闭包 是引用类型 @escaping什么意思?

当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸。当你定义接受闭包作为参数的函数时,你可以在参数名之前标注 @escaping,用来指明这个闭包是允许“逃逸”出这个函数的。

将一个闭包标记为 @escaping 意味着你必须在闭包中显式地引用 self。比如说,在下面的代码中,传递到 someFunctionWithEscapingClosure(_:) 中的闭包是一个逃逸闭包,这意味着它需要显式地引用 self。相对的,传递到 someFunctionWithNonescapingClosure(_:) 中的闭包是一个非逃逸闭包,这意味着它可以隐式引用 self。

 

swift 泛型:干什么用的?怎么使用?

 

什么是copy on write:copy on write, 写时复制,简称COW,它通过浅拷贝(shallow copy)只复制引用而避免复制值;当的确需要进行写入操作时,首先进行值拷贝,在对拷贝后的值执行写入操作,这样减少了无谓的复制耗时。

 

怎么在Swift中使用runtime?继承OC的类,dynamic,@objc

Swift中类似runtime的是什么?Mirror

 

dynamic的作用:

dynamic 可以用来修饰变量或函数,告诉编译器使用动态分发而不是静态分发。

使用动态分发,可以更好的与OC中runtime的一些特性(如CoreData,KVC/KVO)进行交互

标记为dynamic的变量/函数会隐式的加上@objc关键字,它会使用OC的runtime机制

 

Optional是用什么实现的?Optional 是个枚举。有两个枚举成员,Some(T) 和 None,通过泛型来兼容所有类型

 

如何定义下标?使用subscript语法

 

Swift、OC混编如何操作?Swift通过桥接文件调用OC方法。Objective-C中若要调用Swift代码,可以导入Swift生成的头函数ProjectName-Swift.h来实现。

Swift文件中若要规定固定的方法或属性暴露给Objective-C使用,可以在方法或属性前加上@objc来声明。如果该类是NSObject子类,那么Swift会在非private的方法或属性前自动加上@objc。

 

library和framework的区别?

Library 仅能包含编译后的代码,即 .a 文件。但一般来说,一个完整的模块不仅有代码,还可能包含 .h 头文修的 、 .nib 视图文件 、 图片资源文件 、 说明文档 。

Framework 作为 Cocoa/Cocoa Touch 中使用的一种资源打包方式,可以上述文件等集中打包在一起,方便开发者使用(就像Bundle)

 

查看library支持的架构?

lipo -info

library库合并怎么做?

lipo -create liba-arm64.a liba-i386.a -output liba.a

library抽取指定架构怎么做?

lipo liba.a -thin arm64 -output liba-arm64.a

framework合并怎么做?需要和并framework包中的可执行文件,并将两个framework中的Modules里的swiftdoc文件合并到一起

 

static和dynamic Library的区别是什么?

简单的说,静态链接库是指模块被编译合并到应用中,应用程序本身比较大,但不再需要依赖第三方库。运行多个含有该库的应用时,就会有多个该库的Copy在内存中,冗余。

动态库可以分开发布,在运行时查找并载入到内存,如果有通用的库,可以共用,节省空间和内存。同时库也可以直接单独升级,或作为插件发布。

 

framework SDK 怎么开放接口?open或public权限,拖入build Phase Public Header。

swift framework SDK 中怎么和OC混编,swift使用OC方法?在framework的umbrella header,比如JYiOSDeviceFingerPrintSDK.h中声明OC文件,再拖到Build Phases中Public Header中。

OC使用swift方法:OC中导入framework库的头文件.h

更好的做法:新建module.modulemap,写入如下内容

module OCSource [system] {

    //由于module.modulemap和OCSource.h是在同一个文件夹的,如果不是同一个,路径要写全

    header "OCSource.h"

    export *

}

 

 

CocoaPods私有Spec怎么创建?

怎么进行framework的二进制化?

 

MVVM,RxSwift的使用?

 

Swift中常用的第三方框架?

 

Realm使用方式?怎么实现数据绑定?

 

模块化/组件化方案?

 

数据结构和算法,数组、链表、哈希、常用算法、堆、栈等等

编译过程,性能优化,启动速度优化

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值