1.class 和 struct 的区别?
- swift中,class是引用类型,struct是值类型。值类型在传递和赋值时将进行复制,而引用类型则只会使用引用对象的一个"指向"。所以他们两者之间的区别就是两个类型的区别。
- class有这几个功能struct没有的:
1.class可以继承,这样子类可以使用父类的特性和方法
2.类型转换可以在runtime的时候检查和解释一个实例的类型
3.可以用deinit来释放资源
4.一个类可以被多次引用- struct也有这样几个优势:
1.结构较小,适用于复制操作,相比于一个class的实例被多次引用更加安全。
2.无须担心内存memory leak或者多线程冲突问题- 补充:
C语言中,struct与的class的区别:
struct只是作为一种复杂数据类型定义,不能用于面向对象编程。
C++中,struct和class的区别:
对于成员访问权限以及继承方式,class中默认的是private的,而struct中则是public的。class还可以用于表示模板类型,struct则不行。
2.介绍一下观察者模式
观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
- 观察者Observer,通过NSNotificationCenter的addObserver:selector:name:object接口来注册对某一类型通知感兴趣。在注册时候一定要注意,NSNotificationCenter不会对观察者进行引用计数+1的操作,我们在程序中释放观察者的时候,一定要去报从center中将其注销了。
- 通知中心NSNotificationCenter,通知的枢纽。
- 被观察的对象,通过postNotificationName:object:userInfo:发送某一类型通知,广播改变。
- 通知对象NSNotification,当有通知来的时候,Center会调用观察者注册的接口来广播通知,同时传递存储着更改内容的NSNotification对象。
3.在一个HTTPS连接的网站里,输入账号密码点击登录后,到服务器返回这个请求前,中间经历了什么?
- 客户端打包请求。包括url,端口啊,你的账号密码等等。账号密码登陆应该用的是Post方式,所以相关的用户信息会被加载到body里面。这个请求应该包含三个方面:网络地址,协议,资源路径。注意,这里是HTTPS,就是HTTP + SSL / TLS,在HTTP上又加了一层处理加密信息的模块(相当于是个锁)。这个过程相当于是客户端请求钥匙。
- 服务器接受请求。一般客户端的请求会先发送到DNS服务器。 DNS服务器负责将你的网络地址解析成IP地址,这个IP地址对应网上一台机器。这其中可能发生Hosts Hijack和ISP failure的问题。过了DNS这一关,信息就到了服务器端,此时客户端会和服务器的端口之间建立一个socket连接,socket一般都是以file descriptor的方式解析请求。这个过程相当于是服务器端分析是否要向客户端发送钥匙模板。
- 服务器端返回数字证书。服务器端会有一套数字证书(相当于是个钥匙模板),这个证书会先发送给客户端。这个过程相当于是服务器端向客户端发送钥匙模板。
- 客户端生成加密信息。根据收到的数字证书(钥匙模板),客户端会生成钥匙,并把内容锁上,此时信息已经加密。这个过程相当于客户端生成钥匙并锁上请求。
- 客户端发送加密信息。服务器端会收到由自己发送出去的数字证书加锁的信息。 这个时候生成的钥匙也一并被发送到服务器端。这个过程是相当于客户端发送请求。
- 服务器端解锁加密信息。服务器端收到加密信息后,会根据得到的钥匙进行解密,并把要返回的数据进行对称加密。这个过程相当于服务器端解锁请求、生成、加锁回应信息。
- 服务器端向客户端返回信息。客户端会收到相应的加密信息。这个过程相当于服务器端向客户端发送回应。
- 客户端解锁返回信息。客户端会用刚刚生成的钥匙进行解密,将内容显示在浏览器上。
HTTPS加密过程详解请去:https原理:证书传递、验证和数据加密、解密过程解析
4.在一个app中间有一个button,在你手触摸屏幕点击后,到这个button收到点击事件,中间发生了什么?
- 响应链大概有以下几个步骤:
- 设备将touch到的UITouch和UIEvent对象打包, 放到当前活动的Application的事件队列中
- 单例的UIApplication会从事件队列中取出触摸事件并传递给单例UIWindow
- UIWindow使用hitTest:withEvent:方法查找touch操作的所在的视图view
- RunLoop这边我大概讲一下
- 主线程的RunLoop被唤醒
- 通知Observer,处理Timer和Source 0
- Springboard接受touch event之后转给App进程中
- RunLoop处理Source 1,Source1 就会触发回调,并调用_UIApplicationHandleEventQueue() 进行应用内部的分发。
- RunLoop处理完毕进入睡眠,此前会释放旧的autorelease pool并新建一个autorelease pool
深挖请去深入理解RunLoop
5. 不通过继承,代码复用(共享)的方式有哪些?
在swift 文件里直接写方法,相当于一个全局函数。
extension 给类直接扩展方法。
6. Set 独有的方法有哪些?
- 不会出现重复的值。
- 里面的元素必须时相同的类型。
7. 实现一个 min 函数,返回两个元素较小的元素?
func min<T : Comparable>(_ a : T , b : T) -> T {
return a < b ? a : b
}
8. map、filter、reduce 的作用?
- map : 映射 , 将一个元素根据某个函数 映射 成另一个元素(可以是同类型,也可以是不同类型)
- filter : 过滤 , 将一个元素传入闭包中,如果返回的是false , 就过滤掉
- reduce :先映射后融合(这样说容易理解) , 将数组中的所有元素映射融合在一起。举个例子:
struct Person {
let name : String
let money : String
}
let a = Person(name: "小王", money: "5.0")
let b = Person(name: "小李", money: "7.1")
let c = Person(name: "小张", money: "3.22")
let sumMoney = [a , b , c].reduce(0) {
return $0 + ($1.money as NSString).doubleValue
}
print(sumMoney)
9.map 与 flatmap 的区别
map不能将元素映射成可选类型,flatmap可以
10.如何获取当前代码的函数名和行号?
函数名#functio 行号#line 文件名#file
11.如何声明一个只能被类 conform 的 protocol?
protocol OnlyClassProtocol : class {
}
12.guard 使用场景?
可以理解为拦截,凡是不满足 guard 后面条件的,都不会再执行下面的代码。
我一般用来解包 。 不能解包的, 就不能执行下面的代码
相当于
if !(...) {
return
}
13. defer 使用场景?
在一对花括号 : { } 里 使用defer ,这个defer 里面的内容将会在结束 {} 前(or 后?) 被执行
14.String 与 NSString 的关系与区别?
能够互相转换,一个值类型,一个引用类型
15.怎么获取一个 String 的长度?
print( "abcdefg".characters.count )
//7
("abcdefg" as NSString).length //这个要算作NSString的获取长度的方法
16.throws 和 rethrows 的用法与作用?
- throws 声明在函数的末尾,表示这个函数会抛出 Error的子类.
- rethrows 再传入throws的闭包时,这个函数返回用rethrows
17. try? 和 try!是什么意思?
- try! 强制抛出错误,有错误就会崩溃
- try? 抛出错误,没错误不会崩溃直接返回
try
如果不用do catch , 就会编译报错
如果函数后面加上 throws , 将错误传递下去. 即使不用都do catch 编译也不会报错。 但是调用throwfun2()还是要使用do catch
17.associatedtype 的作用?
相当于protocol的范型
protocol Animal {
associatedtype AnimalType : Comparable
}
extension Animal {
typealias AnimalType = Self
}
18. 什么时候使用 final?
- 不允许class 被继承
- 不允许函数被重写
19. private、fileprivate、internal、public和open的区别的区别?
在Swift语言中,访问修饰符有五种,分别为fileprivate,private,internal,public和open,其中 fileprivate和open是Swift 3新添加的。由于过去 Swift对于访问权限的控制是基于文件的,不是基于类的。这样会有问题,所以Swift 3新增了两个修饰符对原来的private、public进行细分。
private
- private所修饰的属性或者方法只能在当前类里访问
- private所修饰类只能在当前.swift文件里访问
fileprivate- fileprivate访问级别所修饰的属性或者方法在当前的Swift源文件里可以访问。
internal(默认访问级别,internal修饰符可写可不写)- internal访问级别所修饰的属性或方法在源代码所在的整个模块都可以访问、被继承、被重写
- 如果是框架或者库代码,则在整个框架内部都可以访问,框架由外部代码所引用时,则不可以访问。
即使使用import,也会提示错误:No such module '...'
public
- 可以被任何人访问。但其他module中不可以被override和继承,而在module内可以被override和继承。
open- 可以被任何人使用,包括override和继承。
- 访问权限排序从高到低排序:open>public>interal > fileprivate >private
20.声明一个只有一个参数没有返回值闭包的别名?
typealias NoReturn = (String) -> Void
21.dynamic 的作用?
由于 swift 是一个静态语言, 所以没有 Objective-C 中的消息发送这些动态机制, dynamic 的作用就是让 swift 代码也能有 Objective-C 中的动态机制, 常用的地方就是 KVO 了, 如果要监控一个属性, 则必须要标记为 dynamic
22.什么时候使用 @objc?
- @objc 用途是为了在 Objective-C 和 Swift 混编的时候, 能够正常调用 Swift 代码. 可以用于修饰类, 协议, 方法, 属性.
- 常用的地方是在定义 delegate 协议中, 会将协议中的部分方法声明为可选方法, 需要用到@objc
23.Optional(可选型) 是用什么实现的?
- Optional 是一个泛型枚举
大致定义如下:enum Optional<Wrapped> { case none case some(Wrapped) }
- 除了使用 let someValue: Int? = nil 之外, 还可以使用let optional1: Optional<Int> = nil 来定义
24.如何自定义下标获取?
实现 subscript 即可, 如
索引除了数字之外, 其他类型也是可以的
24.?? 的作用
当 ?? 前面的值为nil 的时候就取 ??后面的值
25. lazy 的作用?
只有属性被调用的时候才会执行lazy
26. 一个类型表示选项,可以同时表示有几个选项选中(类似 UIViewAnimationOptions ),用什么类型表示?
继承了OptionSet的struct , enum 。 class 没有试过,应该也可以
27. inout 的作用?
改变函数外的值
28. Error 如果要兼容 NSError 需要做什么操作?
- Error是一个协议, swift中的Error 都是enum, 可以转 NSError
- 如果需要Error有NSError的功能,实现 LocalizedError CustomNSError 协议
29. 下面的代码都用了哪些语法糖 [1, 2, 3].map{ $0 * 2 }?
- 用$0 捕获第一个参数。
- 只有一行代码的时候, 隐藏掉了 return 。
30.什么是高阶函数?
一个函数如果可以以某一个函数作为参数, 或者是返回值, 那么这个函数就称之为高阶函数, 如map、flatMap、filter、reduce?
30.如何解决引用循环?
- 转换为值类型, 只有类会存在引用循环, 所以如果能不用类, 是可以解引用循环的,
- delegate 使用 weak 属性.
- 闭包中, 对有可能发生循环引用的对象, 使用 weak 或者 unowned, 修饰
31.定义静态方法时关键字 static 和 class 有什么区别?
static 定义的方法不可以被子类继承, class 则可以
struct 只能用static
class 的属性只能用 static , 其他地方都能随便用。
非class类型 一般 统一用 static 例如 枚举 结构体
protocol中 使用 static ,实现协议的 枚举 结构体 用 static
32.一个 Sequence 的索引是不是一定从 0 开始?
不是。
ArraySlice是Sequence的子类,ArraySlice就不是
33.autoclosure 的作用?
自动闭包,将参数自动封装为闭包参数
34.编译选项 whole module optmization 优化了什么?
编译器可以跨文件优化编译代码, 不局限于一个文件.
35.dynamic framework 和 static framework 的区别是什么?
静态库和动态库, 静态库是每一个程序单独打包一份, 而动态库则是多个程序之间共享
36.如何让自定义对象支持字面量初始化?
ExpressibleByArrayLiteral
可以由数组形式初始化
ExpressibleByDictionaryLiteral
可以由字典形式初始化
ExpressibleByNilLiteral
可以由nil 值初始化
ExpressibleByIntegerLiteral
可以由整数值初始化
ExpressibleByFloatLiteral
可以由浮点数初始化
ExpressibleByBooleanLiteral
可以由布尔值初始化
ExpressibleByUnicodeScalarLiteral
ExpressibleByExtendedGraphemeClusterLiteral
ExpressibleByStringLiteral
这三种都是由字符串初始化, 上面两种包含有 Unicode 字符和特殊字符
一.卓同学的 Swift 面试题
答 《卓同学的 Swift 面试题》
答《卓同学的 Swift 面试题》上
答《卓同学的 Swift 面试题》下