?class 和 struct 的區(qū)別
class 為類, struct 為結(jié)構(gòu)體, 類是引用類型, 結(jié)構(gòu)體為值類型, 結(jié)構(gòu)體不可以繼承
不通過繼承,代碼復(fù)用(共享)的方式有哪些
擴(kuò)展, 全局函數(shù)
Set 獨(dú)有的方法有哪些?
// 定義一個(gè) set
let setA: Set<Int> = [1, 2, 3, 4, 4]
// {1, 2, 3, 4}, 順序可能不一致, 同一個(gè)元素只有一個(gè)值
?let setB: Set<Int> = [1, 3, 5, 7, 9]
// {1, 3, 5, 7, 9}
// 取并集 A | B
let setUnion = setA.union(setB)
// {1, 2, 3, 4, 5, 7, 9}
// 取交集 A & B
let setIntersect = setA.intersection(setB)
// {1, 3}
// 取差集 A - B
let setRevers = setA.subtracting(setB)
// {2, 4}
// 取對(duì)稱差集, A XOR B = A - B | B - A
let setXor = setA.symmetricDifference(setB)
//{2, 4, 5, 7, 9}
實(shí)現(xiàn)一個(gè) min 函數(shù),返回兩個(gè)元素較小的元素
Comparable?可以使用關(guān)系運(yùn)算符<,<=,> =和>進(jìn)行比較的類型。
func myMin<T: Comparable>(_ a: T, _ b: T) -> T {
?return a < b ? a : b
}
myMin(1, 2)
map、filter、reduce 的作用
map 用于映射, 可以將一個(gè)列表轉(zhuǎn)換為另一個(gè)列表
[1, 2, 3].map{"\($0)"}// 數(shù)字?jǐn)?shù)組轉(zhuǎn)換為字符串?dāng)?shù)組
["1", "2", "3"]
filter 用于過濾, 可以篩選出想要的元素
[1,2,3].filter{$0 %2==0}// 篩選偶數(shù)
// [2]
reduce 合并
// 轉(zhuǎn)換為字符串并拼接
[1,2,3].reduce(""){$0 +"\($1)"}// "123"
組合示例
(0..<10).filter{$0 %2==0}.map{"\($0)"}.reduce(""){$0 + $1}
// 02468
map 與 flatmap 的區(qū)別
flatmap 有兩個(gè)實(shí)現(xiàn)函數(shù)實(shí)現(xiàn),
public?func?flatMap(_transform: (Element)?throws->ElementOfResult?)?rethrows?->? [ElementOfResult]
這個(gè)方法, 中間的函數(shù)返回值為一個(gè)可選值, 而 flatmap 會(huì)丟掉那些返回值為nil的值
例如
["1","@","2","3","a"].flatMap{Int($0)}
// [1, 2, 3]
["1","@","2","3","a"].map{Int($0) ??-1}
//[Optional(1), nil, Optional(2), Optional(3), nil]
另一個(gè)實(shí)現(xiàn)
public?func?flatMap(_transform: (Element)?throws?-> SegmentOfResult)?rethrows?->? [SegmentOfResult.Iterator.Element]?where?SegmentOfResult : Sequence
中間的函數(shù), 返回值為一個(gè)數(shù)組, 而這個(gè) flapmap 返回的對(duì)象則是一個(gè)與自己元素類型相同的數(shù)組
func?someFunc(_array:[Int]) -> [Int] {
? ??return?array
}
[[1], [2,3], [4,5,6]].map(someFunc)
// [[1], [2, 3], [4, 5, 6]]
[[1], [2,3], [4,5,6]].flatMap(someFunc)
// [1, 2, 3, 4, 5, 6]
其實(shí)這個(gè)實(shí)現(xiàn), 相當(dāng)于是在使用 map 之后, 再將各個(gè)數(shù)組拼起來一樣的
[[1], [2,3], [4,5,6]].map(someFunc).reduce([Int]()) {$0 + $1}
// [1, 2, 3, 4, 5, 6]
什么是 copy on write時(shí)候
寫時(shí)復(fù)制, 指的是 swift 中的值類型, 并不會(huì)在一開始賦值的時(shí)候就去復(fù)制, 只有在需要修改的時(shí)候, 才去復(fù)制.
這里有詳細(xì)的說明
http://m.itdecent.cn/p/7e8ba0659646
如何獲取當(dāng)前代碼的函數(shù)名和行號(hào)
#file用于獲取當(dāng)前文件文件名
#line用于獲取當(dāng)前行號(hào)
#column用于獲取當(dāng)前列編號(hào)
#function用于獲取當(dāng)前函數(shù)名
以上這些都是特殊的字面量, 多用于調(diào)試輸出日志
具體可以看這里 apple 文檔
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html
這里有中文翻譯
http://wiki.jikexueyuan.com/project/swift/chapter3/04_Expressions.html
如何聲明一個(gè)只能被類 conform 的protocol
聲明協(xié)議的時(shí)候, 加一個(gè)class即可
如
protocol?SomeClassProtocl:class {
? ?func?someFunction()
}
guard 使用場景
guard和if類似, 不同的是,guard總是有一個(gè)else語句, 如果表達(dá)式是假或者值綁定失敗的時(shí)候, 會(huì)執(zhí)行else語句, 且在else語句中一定要停止函數(shù)調(diào)用
例如
guard1+1==2else{
? ? fatalError("something wrong")
}
常用使用場景為, 用戶登錄的時(shí)候, 驗(yàn)證用戶是否有輸入用戶名密碼等
guard?let?userName =?self.userNameTextField.text,
? ??let?password =?self.passwordTextField.text?else{
? ? ? ??return
}
defer 使用場景
defer語句塊中的代碼, 會(huì)在當(dāng)前作用域結(jié)束前調(diào)用, 常用場景如異常退出后, 關(guān)閉數(shù)據(jù)庫連接
func?someQuery() -> ([Result], [Result]){
? ??let?db = DBOpen("xxx")
? ??defer{
? ? ? ? db.close()
? ? }
? ??guard?results1 = db.query("query1")?else?{
? ? ? ??return nil
? ? }
? ??guard?results2 = db.query("query2")?else?{
? ? ? ??return nil
? ? }
? ??return(results1, results2)
}
需要注意的是, 如果有多個(gè)defer, 那么后加入的先執(zhí)行
func?someDeferFunction() {
? ??defer{
? ? ? ? print("\(#function)-end-1-1")
? ? ? ? print("\(#function)-end-1-2")
? ? }
? ??defer{
? ? ? ? print("\(#function)-end-2-1")
? ? ? ? print("\(#function)-end-2-2")
? ? }
? ??if?true{
? ? ? ??defer{
? ? ? ? ? ? print("if defer")
? ? ? ? }
? ? ? ? print("if end")
? ? }
? ? print("function end")
}
someDeferFunction()
// 輸出
// if end
// if defer
// function end
// someDeferFunction()-end-2-1
// someDeferFunction()-end-2-2
// someDeferFunction()-end-1-1
// someDeferFunction()-end-1-2
String 與 NSString 的關(guān)系與區(qū)別
NSString 與 String 之間可以隨意轉(zhuǎn)換,
let?someString ="123"
let?someNSString =NSString(string:"n123")
let?strintToNSString =someString?as?NSString
let?nsstringToString =someNSString?as?String
String是結(jié)構(gòu)體, 值類型, NSString 是類, 引用類型.
通常, 沒必要使用 NSString 類, 除非你要使用一些特有方法, 例如使用 pathExtension 屬性
怎么獲取一個(gè) String 的長度
不考慮編碼, 只是想知道字符的數(shù)量, 用characters.count
"hello".characters.count// 5
"你好".characters.count// 2
"こんにちは".characters.count// 5
如果想知道在某個(gè)編碼下占多少字節(jié), 可以用
"hello".lengthOfBytes(using: .ascii)// 5|
"hello".lengthOfBytes(using: .unicode)// 10
"你好".lengthOfBytes(using: .unicode)// 4
"你好".lengthOfBytes(using: .utf8)// 6
"こんにちは".lengthOfBytes(using: .unicode)// 10
"こんにちは".lengthOfBytes(using: .utf8)// 15
如何截取 String 的某段字符串
swift 中, 有三個(gè)取子串函數(shù),
substring:to , substring:from, substring:with.
let?simpleString ="Hello, world"
simpleString.substring(to: simpleString.index(simpleString.startIndex, offsetBy: 5))
// hello
simpleString.substring(from: simpleString.index(simpleString.endIndex, offsetBy: -5))
// world
simpleString.substring(with: simpleString.index(simpleString.startIndex, offsetBy: 5) ..< simpleString.index(simpleString.endIndex, offsetBy: -5))
使用起來略微麻煩, 具體用法可以參考這一篇文章
http://m.itdecent.cn/p/b3231f9406e9
throws 和 rethrows 的用法與作用
throws用在函數(shù)上, 表示這個(gè)函數(shù)會(huì)拋出錯(cuò)誤.
有兩種情況會(huì)拋出錯(cuò)誤, 一種是直接使用throw拋出, 另一種是調(diào)用其他拋出異常的函數(shù)時(shí), 直接使用tryxx 沒有處理異常.
如
enumDivideError:Error{
? ??caseEqualZeroError;
}
func?divide(_a:Double,_b:Double)throws->Double{
? ??guard?b !=Double(0)else{
? ? ? ??throw DivideError.EqualZeroError
? ? }
? ??returna / b
}
func?split(pieces:Int)throws->Double{
? ??return?try?divide(1,Double(pieces))
}
rethrows與throws類似, 不過只適用于參數(shù)中有函數(shù), 且函數(shù)會(huì)拋出異常的情況,rethrows可以用throws替換, 反過來不行
如
func?processNumber(a:Double, b:Double, function: (Double,Double)throws->Double)rethrows->Double{
? ??return?try?function(a, b)
}
try? 和 try!是什么意思
這兩個(gè)都用于處理可拋出異常的函數(shù), 使用這兩個(gè)關(guān)鍵字可以不用寫docatch.
區(qū)別在于,try? 在用于處理可拋出異常函數(shù)時(shí), 如果函數(shù)拋出異常, 則返回nil, 否則返回函數(shù)返回值的可選值, 如:
print(try? divide(2,1))
// Optional(2.0)
print(try? divide(2,0))
// nil
而try! 則在函數(shù)拋出異常的時(shí)候崩潰, 否則則返會(huì)函數(shù)返回值, 相當(dāng)于(try? xxx)!, 如:
print(try! divide(2,1))
// 2.0
print(try! divide(2,0))
// 崩潰
associatedtype 的作用
簡單來說就是protocol使用的泛型
例如定義一個(gè)列表協(xié)議
protocol?ListProtcol {
? ??associatedtype Element
? ??func?push(_element:Element)
? ??func?pop(_element:Element) ->Element?
}
實(shí)現(xiàn)協(xié)議的時(shí)候, 可以使用typealias指定為特定的類型, 也可以自動(dòng)推斷, 如
class?IntList : ListProtcol{
? ??typealias Element = Int // 使用 typealias 指定為 Int
? ??var?list = [Element]()
? ??func?push(_element:Element) {
? ? ? ??self.list.append(element)
? ? }
? ??func?pop(_element:Element) ->Element? {
? ? ? ??return?self.list.popLast()
? ? }
}
class?DoubleList:ListProtcol{
? ??var?list = [Double]()
? ??func?push(_element:Double) {// 自動(dòng)推斷
? ? ? ??self.list.append(element)
? ? }
? ??func?pop(_element:Double) ->Double? {
? ? ? ??return?self.list.popLast()
? ? }
}
使用泛型也可以
class?AnyList:ListProtcol{
? ??var?list = [T]()
? ??func?push(_element:T) {
? ? ? ??self.list.append(element)
? ? }
? ??func?pop(_element:T) ->T? {
? ? ? ??return?self.list.popLast()
? ? }
}
可以使用where字句限定 Element 類型, 如:
extension ListProtcol where Element == Int {
? ??func?isInt() ->Bool{
? ? ? ??return true
? ? }
}
什么時(shí)候使用 final
final 用于限制繼承和重寫. 如果只是需要在某一個(gè)屬性前加一個(gè) final.
如果需要限制整個(gè)類無法被繼承, 那么可以在類名之前加一個(gè)final
public和 open 的區(qū)別
這兩個(gè)都用于在模塊中聲明需要對(duì)外界暴露的函數(shù), 區(qū)別在于,public修飾的類, 在模塊外無法繼承, 而 open 則可以任意繼承, 公開度來說,public< open
聲明一個(gè)只有一個(gè)參數(shù)沒有返回值閉包的別名
沒有返回值也就是返回值為 Void
typealias?SomeClosuerType = (String) -> (Void)
let?someClosuer:SomeClosuerType= { (name:String)in
? ? print("hello,", name)
}
someClosuer("world")
// hello, world
Self的使用場景
Self通常在協(xié)議中使用, 用來表示實(shí)現(xiàn)者或者實(shí)現(xiàn)者的子類類型.
例如, 定義一個(gè)復(fù)制的協(xié)議
protocolCopyProtocol {
? ??func?copy() ->Self
}
如果是結(jié)構(gòu)體去實(shí)現(xiàn), 要將Self 換為具體的類型
structSomeStruct:CopyProtocol{
? ??let?value:Int
? ??func?copySelf() ->SomeStruct{
? ? ? ??returnSomeStruct(value:self.value)
? ? }
}
如果是類去實(shí)現(xiàn), 則有點(diǎn)復(fù)雜, 需要有一個(gè) required 初始化方法, 具體可以看這里 http://swifter.tips/use-self/
class?SomeCopyableClass:CopyProtocol{
? ??func?copySelf() ->Self{
? ? ? ??return?type(of:self).init()
? ? }
? ??required init(){}
}
dynamic 的作用
由于 swift 是一個(gè)靜態(tài)語言, 所以沒有 Objective-C 中的消息發(fā)送這些動(dòng)態(tài)機(jī)制, dynamic 的作用就是讓 swift 代碼也能有 Objective-C 中的動(dòng)態(tài)機(jī)制, 常用的地方就是 KVO 了, 如果要監(jiān)控一個(gè)屬性, 則必須要標(biāo)記為 dynamic, 可以參考我的文章http://m.itdecent.cn/p/ae26100b9edf
什么時(shí)候使用@objc
@objc用途是為了在 Objective-C 和 Swift 混編的時(shí)候, 能夠正常調(diào)用 Swift 代碼. 可以用于修飾類, 協(xié)議, 方法, 屬性.
常用的地方是在定義 delegate 協(xié)議中, 會(huì)將協(xié)議中的部分方法聲明為可選方法, 需要用到@objc
@objcprotocol?OptionalProtocol {
? ??@objcoptional?func?optionalFunc()
? ??func?normalFunc()
}
class?OptionProtocolClass:OptionalProtocol{
? ??func?normalFunc() {
? ? }
}
let?someOptionalDelegate:OptionalProtocol=OptionProtocolClass()
someOptionalDelegate.optionalFunc?()
Optional(可選型) 是用什么實(shí)現(xiàn)的
Optional 是一個(gè)泛型枚舉
大致定義如下:
enum?Optional {
? ??case?none
? ??case?some(Wrapped)
}
除了使用let?someValue:Int? =nil之外, 還可以使用let optional1: Optional =nil來定義
如何自定義下標(biāo)獲取
實(shí)現(xiàn) subscript 即可, 如
extension AnyList {
? ??subscript(index:Int) ->T{
? ? ? ??return?self.list[index]
? ? }
? ??subscript(indexString:String) ->T?{
? ? ? ??guard?let?index =Int(indexString)else{
? ? ? ? ? ??return nil
? ? ? ? }
? ? ? ??return?self.list[index]
? ? }
}
索引除了數(shù)字之外, 其他類型也是可以的
?? 的作用
可選值的默認(rèn)值, 當(dāng)可選值為nil 的時(shí)候, 會(huì)返回后面的值. 如
let?someValue = optional1 ??0
lazy 的作用
懶加載, 當(dāng)屬性要使用的時(shí)候, 才去完成初始化
如
class?LazyClass {
? ??lazy?var?someLazyValue:Int= {
? ? ? ? print("lazy init value")
? ? ? ??return1
? ? }()
? ??var?someNormalValue:Int= {
? ? ? ? print("normal init value")
? ? ? ??return2
? ? }()
}let?lazyInstance =LazyClass()
print(lazyInstance.someNormalValue)|
print(lazyInstance.someLazyValue)
// 打印輸出
// normal init value
// 2
// lazy init value
// 1
一個(gè)類型表示選項(xiàng),可以同時(shí)表示有幾個(gè)選項(xiàng)選中(類似 UIViewAnimationOptions ),用什么類型表示
需要實(shí)現(xiàn)自O(shè)ptionSet, 一般使用struct實(shí)現(xiàn). 由于 OptionSet 要求有一個(gè)不可失敗的init(rawValue:) 構(gòu)造器, 而 枚舉無法做到這一點(diǎn)(枚舉的原始值構(gòu)造器是可失敗的, 而且有些組合值, 是沒辦法用一個(gè)枚舉值表示的)
struct?SomeOption:OptionSet{
? ??let?rawValue:Int
? ??static?let?option1 =SomeOption(rawValue:1<<0)
? ??static?let?option2 =? SomeOption(rawValue:1<<1)
? ??static?let?option3 =? SomeOption(rawValue:1<<2)
}
let options: SomeOption = [.option1, .option2]
inout 的作用
輸入輸出參數(shù), 如:
func?swap( a:inoutInt, b:inoutInt) {
? ??let?temp = a
? ? a = b
? ? b = temp
}
var?a =1
var?b =2
print(a, b)// 1 2
swap(a: &a, b: &b)
print(a, b)// 2 1
Error如果要兼容NSError需要做什么操作
其實(shí)直接轉(zhuǎn)換就可以, 例如 SomeError.someError?as?NSError 但是這樣沒有錯(cuò)誤碼, 描述等等, 如果想和 NSError 一樣有這些東西, 只需要實(shí)現(xiàn) LocalizedError 和 CustomNSError 協(xié)議, 有些方法有默認(rèn)實(shí)現(xiàn), 可以略過, 如:
enum SomeError: Error, LocalizedError, CustomNSError {
? ??caseerror1, error2
? ??public?var?errorDescription:String? {
? ? ? ??switch?self{
? ? ? ??case.error1:
? ? ? ? ? ??return "error description error1"
? ? ? ??case.error2:
? ? ? ? ? ??return "error description error2"
? ? ? ? }
? ? }? ? var?errorCode:Int{
? ? ? ??switch?self{
? ? ? ??case.error1:
? ? ? ? ? ??return1
? ? ? ??case.error2:
? ? ? ? ? ??return2
? ? ? ? }
? ? }? ? public?static?var?errorDomain:String{
? ? ? ??return "error domain SomeError"
? ? }? ? public?var?errorUserInfo: [String:Any] {
? ? ? ??switchself{
? ? ? ??case.error1:
? ? ? ? ? ??return["info":"error1"]
? ? ? ??case.error2:
? ? ? ? ? ??return["info":"error2"]
? ? ? ? }
? ? }
}print(SomeError.error1 as NSError)
// Error Domain=error domain SomeError Code=1 "error description error1" UserInfo={info=error1}
下面的代碼都用了哪些語法糖
[1,2,3].map{ $0 *2}
[1,2,3] 使用了, Array 實(shí)現(xiàn)的ExpressibleByArrayLiteral 協(xié)議, 用于接收數(shù)組的字面值
map{xxx} 使用了閉包作為作為最后一個(gè)參數(shù)時(shí), 可以直接寫在調(diào)用后面, 而且, 如果是唯一參數(shù)的話, 圓括號(hào)也可以省略
閉包沒有聲明函數(shù)參數(shù), 返回值類型, 數(shù)量, 依靠的是閉包類型的自動(dòng)推斷
閉包中語句只有一句時(shí), 自動(dòng)將這一句的結(jié)果作為返回值0, 后續(xù)參數(shù)以此類推
什么是高階函數(shù)
一個(gè)函數(shù)如果可以以某一個(gè)函數(shù)作為參數(shù), 或者是返回值, 那么這個(gè)函數(shù)就稱之為高階函數(shù), 如 map, reduce, filter
如何解決引用循環(huán)
轉(zhuǎn)換為值類型, 只有類會(huì)存在引用循環(huán), 所以如果能不用類, 是可以解引用循環(huán)的,
delegate 使用 weak 屬性.
閉包中, 對(duì)有可能發(fā)生循環(huán)引用的對(duì)象, 使用 weak 或者 unowned, 修飾
下面的代碼會(huì)不會(huì)崩潰,說出原因
var?mutableArray = [1,2,3]
for _ in mutableArray {
? ? mutableArray.removeLast()
}
不會(huì), 原理不清楚, 就算是把 removeLast(), 換成 removeAll() ,這個(gè)循環(huán)也會(huì)執(zhí)行三次, 估計(jì)是在一開始,for?in就對(duì) mutableArray 進(jìn)行了一次值捕獲, 而 Array 是一個(gè)值類型 , removeLast() 并不能修改捕獲的值.
給集合中元素是字符串的類型增加一個(gè)擴(kuò)展方法,應(yīng)該怎么聲明
使用where子句, 限制 Element 為 String
extension Array where Element == String {
? ??var?isStringElement:Bool{
? ? ? ??return true
? ? }
}
["1", "2"].isStringElement
//[1, 2].isStringElement// error
定義靜態(tài)方法時(shí)關(guān)鍵字static和class有什么區(qū)別
static定義的方法不可以被子類繼承,class則可以
class?AnotherClass {
? ??static?func?staticMethod(){}
? ??class?func?classMethod(){}
}
class?ChildOfAnotherClass:AnotherClass{
? ??override?class?func?classMethod(){}
? ??//override static func staticMethod(){}// error
}
一個(gè)Sequence的索引是不是一定從0開始?
不一定, 兩個(gè)forin并不能保證都是從0開始, 且輸出結(jié)果一致, 官方文檔如下
Repeated Access
The Sequence?protocol?makes no requirement on conforming types regarding whether they will be destructively consumed by iteration. As aconsequence, don't assume that multiple for-in loops on a sequence will either resume iteration or restart from the beginning:
for?element?in?sequence {
? ? ? ??if... some condition {break}
}
for?element?in?sequence {
? ??// No defined behavior
}
有些同學(xué)還是不太理解, 我寫了一個(gè)demo 當(dāng)作參考
class Countdown: Sequence, IteratorProtocol {
? ??var?count:Int
? ??init(count:Int) {
? ? ? ??self.count= count
? ? }
? ??func?next() ->Int? {
? ? ? ??if?count==0{
? ? ? ? ? ??return?nil
? ? ? ? }else{
? ? ? ? ? ??defer{count-=1}
? ? ? ? ? ??return?count
? ? ? ? }
? ? }
}
var?countDown =Countdown(count:5)
print("begin for in 1")
for c in countDown {
? ? print(c)
}
print("end for in 1")
print("begin for in 2")
for c in countDown {
? ? print(c)
}
print("end for in 2")
最后輸出的結(jié)果是
begin?for?in?1
end?for?in?1
begin?for?in?2
end?for?in?2
很明顯, 第二次沒有輸出任何結(jié)果, 原因就是在第二次forin的時(shí)候, 并沒有將count 重置.
數(shù)組都實(shí)現(xiàn)了哪些協(xié)議
MutableCollection, 實(shí)現(xiàn)了可修改的數(shù)組, 如 a[1] =2
ExpressibleByArrayLiteral, 實(shí)現(xiàn)了數(shù)組可以從[1,2,3] 這種字面值初始化的能力
...
如何自定義模式匹配
這部分不太懂, 貼個(gè)鏈接吧
http://swifter.tips/pattern-match/
autoclosure 的作用
自動(dòng)閉包, 會(huì)自動(dòng)將某一個(gè)表達(dá)式封裝為閉包. 如
func?autoClosureFunction(_closure:@autoclosure() ->Int) {
? ? closure()
}
autoClosureFunction(1)
詳細(xì)可參考http://swifter.tips/autoclosure/
編譯選項(xiàng) whole module optmization 優(yōu)化了什么
編譯器可以跨文件優(yōu)化編譯代碼, 不局限于一個(gè)文件.
http://m.itdecent.cn/p/8dbf2bb05a1c
下面代碼中 mutating 的作用是什么
struct?Person {
? ??var?name:String{
? ? ? ??mutating get {
? ? ? ? ? ??return?store
? ? ? ? }
? ? }
}
讓不可變對(duì)象無法訪問 name 屬性
如何讓自定義對(duì)象支持字面量初始化
有幾個(gè)協(xié)議, 分別是
ExpressibleByArrayLiteral 可以由數(shù)組形式初始化
ExpressibleByDictionaryLiteral 可以由字典形式初始化
ExpressibleByNilLiteral 可以由nil 值初始化
ExpressibleByIntegerLiteral 可以由整數(shù)值初始化
ExpressibleByFloatLiteral 可以由浮點(diǎn)數(shù)初始化
ExpressibleByBooleanLiteral 可以由布爾值初始化
ExpressibleByUnicodeScalarLiteral
ExpressibleByExtendedGraphemeClusterLiteral
ExpressibleByStringLiteral
這三種都是由字符串初始化, 上面兩種包含有 Unicode 字符和特殊字符
dynamic framework 和static?framework 的區(qū)別是什么
靜態(tài)庫和動(dòng)態(tài)庫, 靜態(tài)庫是每一個(gè)程序單獨(dú)打包一份, 而動(dòng)態(tài)庫則是多個(gè)程序之間共享
鏈接:? ?http://m.itdecent.cn/p/7c7f4b4e4efe
鏈接:http://m.itdecent.cn/p/cc4a737ddc1d
鏈接:http://m.itdecent.cn/p/23d99f434281