SwiftTips-DayByDay

本文是對喵神書的學(xué)習(xí)總結(jié)逊脯, 僅僅只是為了加深理解記錄优质,支持正版支持正版

第一版就買了此書,一直沒好好看军洼,真是罪過罪過

一些簡單的代碼Github地址

2016-12-7

創(chuàng)建隨機數(shù)

使用arc4random()來創(chuàng)建隨機數(shù)是一個不錯的方法巩螃,并且在swift中也可以使用,如果想要某個范圍內(nèi)的數(shù)匕争,可以使用模運算%來實現(xiàn)避乏。

API
public func arc4random() -> UInt32
public func arc4random_uniform(_ __upper_bound: UInt32) -> UInt32

但是有一個問題:
在iPhone5s及之后的設(shè)備上沒問題,但是在iPhone5及之前的設(shè)備上有時候會崩潰

原因:
Swift的Int是和CPU的架構(gòu)相關(guān)的:在32位的CPU上甘桑,實際上他是Int32拍皮,在64位的CPU上,他是Int64的扇住。而使用arc4random()返回的值始終是UInt32的春缕,所以在32位的機器上有一個班的概率會在進行Int轉(zhuǎn)換時候越界,從而崩潰艘蹋。

實踐锄贼,實現(xiàn)創(chuàng)建一個Range的隨機數(shù)的方法

//創(chuàng)建一個Range的隨機數(shù)的方法

func randomInRange(inRange range: Range<Int>) -> Int{
    let count = UInt32(range.upperBound - range.lowerBound)
    return Int(arc4random_uniform(UInt32(count))) + range.lowerBound
}

for _ in 0...10 {
    let range = Range(1...6)
    print(randomInRange(inRange: range))
}

自定制print數(shù)據(jù)的格式

實現(xiàn)該功能,在Objective-C中女阀,主要靠重載description方法來實現(xiàn)

在Swift中通過實現(xiàn)CustomStringConvertible協(xié)議來實現(xiàn)

class MyPrintClass{
    var num: Int
    init() {
        num = 1
    }
}

extension MyPrintClass: CustomStringConvertible{
    var description: String{
        return "Num: \(self.num)"
    }
}

let printClass = MyPrintClass()
print(printClass)

其實主要是學(xué)習(xí)一種思想:實現(xiàn)和定義一個類型的時候宅荤,先定義最簡單的類型結(jié)構(gòu)屑迂,再通過擴展(extension)的方式來實現(xiàn)各種協(xié)議和功能

還有另外一個協(xié)議CustomDebugStringConvertible,通過實現(xiàn)它可以設(shè)置在調(diào)試中使用debugger來進行打印時候的輸出冯键,類似po printClass的命令進行打印

未實現(xiàn)時打印結(jié)果類似

 (lldb)  po printClass
<MyPrintClass: 0x608000029da0>

實現(xiàn)后打印結(jié)果類似

(lldb) po printClass
MyPrintClass Num : 1

打斷點觀察對象時十分有用惹盼,實現(xiàn)方式

class MyPrintClass {
    var num: Int
    init() {
        num = 1
    }
}

extension MyPrintClass: CustomDebugStringConvertible{
    var debugDescription: String{
        return "MyPrintClass Num : \(self.num)"
    }
}

2016-12-6

delegate的使用

協(xié)議-委托模式太常見了,不多說

在OC中惫确,使用ARC手报,通常將delegate設(shè)置為weak,這樣可以使得delegate實際的對象被釋放時候改化,被置為nil掩蛤。但在Swift中,不能直接將其設(shè)置為weak陈肛,要解決這個問題揍鸟,首先要知道原因

swift中的protocol不僅可以被class所遵循,還可以被structenum這樣的類型遵循句旱,而對于這些類型阳藻,本身就不會通過引用計數(shù)來進行內(nèi)存管理,所以不能用weak這樣的概念來修飾

明白了原因就好解決谈撒,就是設(shè)法將protocol限制在class 內(nèi)

方法一

因為在Objective-C中的protocol只有類能實現(xiàn)腥泥,所以可以將protocol聲明為Objective-C的,通過在protocol前添加@objc來實現(xiàn)

@objc protocol MyClassDelegate {
    func method()
}

class MyClass {
    weak var delegate: MyClassDelegate?
}

方法二

在protocol聲明的后面加上class港华,為編譯器顯示的指明該protocol只能由class實現(xiàn)

protocol MyClassDelegate: class{
    func method()
}

class MyClass {
    weak var delegate: MyClassDelegate?
}

關(guān)聯(lián)對象的實現(xiàn)

在Objective-C中道川,我們可以利用Objective-C的運行時和Key-Value Coding的特性,在運行時實現(xiàn)向一個對象添加值存儲立宜。在使用Category擴展現(xiàn)有類的功能時冒萄,直接添加實例變量是不被允許的,但可以使用property配合 Associated Object 的方式橙数,將一個對象關(guān)聯(lián)到一個已有的要擴展的對象上尊流,從外部來看,就像是直接通過屬性訪問對象的實例變量一樣灯帮。

在Swift中實現(xiàn)向extension中使用 Associated Object的方式將對象進行關(guān)聯(lián)

class MyClass{
    
}

private var key: Void?

//error: extensions may not contain stored properties
extension MyClass {
    var title: String?{
        get{
            return objc_getAssociatedObject(self, &key) as? String
        }
        set{
            objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
}

let myClass = MyClass()

if let title = myClass.title {
    print("設(shè)置了title: \(title)")
}else{
    print("該屬性為空")
}

myClass.title = "Tom"

if let title = myClass.title {
    print("設(shè)置了title: \(title)")
}else{
    print("該屬性為空")
}

說明:
key的類型被聲明為 Void?崖技,并通過&符號取地址作為UnsafePointer<Void>類型傳入。

2016-12-5

GCD和延遲調(diào)用

使用GCD來實現(xiàn)多線程編程钟哥,先來個最經(jīng)常使用的例子

//創(chuàng)建目標(biāo)隊列
let workingQueue = DispatchQueue(label: "com.ivan.myqueue")

//派發(fā)到剛創(chuàng)建的隊列中迎献,GCD會負(fù)責(zé)線程調(diào)度
workingQueue.async { 
    //在workQueue中異步進行
    print("Working....")
    //模擬兩秒的執(zhí)行時間
    Thread.sleep(forTimeInterval: 2)
    print("Work finish")
    DispatchQueue.main.async {
        print("在主線程中更新UI")
    }
}

實現(xiàn)延遲調(diào)用,這樣寫主要是為了實現(xiàn)能夠在調(diào)用之前取消該操作

    typealias Task = (_ cancel: Bool) -> Void
    
    func delay(_ time: TimeInterval,task: @escaping () -> ()) -> Task? {
        
        //這個時候就體會到@escaping的含義了
        func dispatch_later(block: @escaping () -> ()){
            let t = DispatchTime.now() + time
            DispatchQueue.main.asyncAfter(deadline: t, execute: block)
        }
        
        var closure: (() -> Void)? = task
        var result: Task?
        
        let delayedClosure: Task = {
            cancel in
            if let internalClosure = closure {
                if cancel == false {
                    DispatchQueue.main.async(execute: internalClosure)
                }
            }
            closure = nil
            result = nil
        }
        
        result = delayedClosure
        
        dispatch_later {
            if let delayedClosure = result{
                delayedClosure(false)
            }
        }
        
        return result
    }
    
    func cancel(_ task: Task?) {
        task?(true)
    }

2016-12-4

值類型和引用類型

在swift中腻贰,有值類型和引用類型兩種吁恍,值類型在傳遞和賦值時將進行復(fù)制,引用類型只會使用引用對象的一個‘指向’。在swift中有幾點需要注意

  • swift中的structenum定義的類型都是值類型冀瓦,使用class定義的對象是引用類型
  • swift中所有的內(nèi)建類型都是值類型伴奥,不僅包括IntBool翼闽,甚至連String拾徙、ArrayDictionary都是值類型。

這樣做的好處是可以減少堆內(nèi)存上內(nèi)存分配和回收的次數(shù)感局。

驗證一下在swift中數(shù)組是值類型

//驗證: 數(shù)組在swift中是值類型
var array = ["A","B","C"]

var array1 = array

array1.removeLast()

array //["A", "B", "C"]

array1 //["A", "B"]

驗證一下值類型中存儲值類型和引用類型時的操作

//驗證:  值類型在復(fù)制時尼啡,將存儲在其中的值類型進行復(fù)制,但對于其中的引用類型询微,只是復(fù)制一份引用

//引用類型
class MyClass{
    var num: Int
    
    init(num: Int) {
        self.num = num
    }
}

var myObj = MyClass(num: 1)

var classArray = [myObj]

myObj.num = 101

classArray[0].num //101

//值類型
struct MyStruct{
    var num: Int
}

var myStruct = MyStruct(num: 2)

var structArray = [myStruct]

myStruct.num = 102

structArray[0].num //2

區(qū)分一下String和NSString

先來個自己的總結(jié)

** StringNSString其實并沒有太大的區(qū)別玄叠,他們兩個基本上市可以無縫轉(zhuǎn)換的,之所以有時候需要轉(zhuǎn)換拓提,只是他們有很少一部分沒有相互實現(xiàn)的API,只是為了使用起來方便**

比如遍歷一個字符串

使用String會更方便隧膘,因為它實現(xiàn)了ColletionType這樣的協(xié)議

var str = "Hello, playground"

for character in str.characters {
    print(character)
}

但如果是要和Range配合使用代态,使用NSString會更方便一些

//比如我們要實現(xiàn)一個替換第一個字符到第5個字符之前的字符的功能

//使用String
let startPosition = str.index(str.startIndex, offsetBy: 1)
let endPosition = str.index(str.startIndex, offsetBy: 5)

let range: Range = startPosition..<endPosition

str.replacingCharacters(in: range, with: "TEST") //"HTEST, playground"

//如果使用NSString

let nsRnage = NSMakeRange(1, 4)

(str as NSString).replacingCharacters(in: nsRnage, with: "TEST") //"HTEST, playground"

JUST DO IT.

2016-12-3

在Swift中實現(xiàn)協(xié)議方法的可選實現(xiàn)

在Objective-C中的protocol可是使用關(guān)鍵字@optional來實現(xiàn)可選方法。但是在Swift中疹吃,默認(rèn)所有的方法都是必須要實現(xiàn)的蹦疑。但是也并非不能實現(xiàn),有兩種方法

將協(xié)議本身和可選方法都定義為Objective-C

其實也就是在協(xié)議之前和協(xié)議方法之前都加上@objc萨驶,這樣就可以使用optional關(guān)鍵字了

有一些限制歉摧,說明一下:

  • 使用@objc修飾的protocol只能被class實現(xiàn),對于structenum類型腔呜,無法令他們實現(xiàn)可選方法和屬性了
  • 實現(xiàn)他的class 的方法也必須被標(biāo)注為@objc叁温,或者整個類就是繼承自NSObject
@objc protocol MyProtocol1 {
    @objc optional func method1() -> String
    
    func method2() -> Int
}

class MyClass1: MyProtocol1 {
    
    //不實現(xiàn)也是可以的
//    func method1() -> String {
//        return "Test"
//    }
    
    func method2() -> Int {
        return 2
    }
}

//是會報錯的 error: non-class type 'MyStruct1' cannot conform to class protocol 'MyProtocol1'
struct MyStruct1: MyProtocol1{
    func method1() -> String {
        return "Struct"
    }
    
    func method2() -> Int {
        return 3
    }
}

使用extension

這個方法是在swift2.0之后才支持的,其實就是使用protocolextension給出方法的默認(rèn)實現(xiàn)核畴,這樣膝但,這些方法在實際的類中就是可選實現(xiàn)的了

protocol MyProtocol2 {
    func method1() -> String
    
    func method2() -> Int
}

extension MyProtocol2 {
    func method1() -> String {
        return "MyProtocol2DefaultString"
    }
    
}

class MyClass2: MyProtocol2 {
    func method2() -> Int {
        return 3
    }
}

2016-11-30

條件編譯

swift中沒有宏的概念,所以不能使用#ifdef的方法來檢測某個符號是否經(jīng)過宏定義

編譯標(biāo)記的使用語法


 #if <condition>

 #elseif <condition> //可選

 #else //可選

 #endif
 

condition的內(nèi)建組合

方法 可選參數(shù)
os() masOS谤草、iOS跟束、tvOS、watchOS丑孩、Linux
arch() i386冀宴、x86_64(對應(yīng)模擬器上的32位和64位CPU),arm、arm54(對應(yīng)真機)
swift() >= 某個版本

可以配合 typealias使用温学,更強大

自定義condition進行條件編譯

使用方法一樣略贮,主要是如何定義編譯符合

在項目的編譯選項中進行設(shè)置,Building Settings - Swift Compiler - Custom Flags,在其中的 Other Swift Flags 加上 -D 定義的編譯符號 就可以了

可用于

  • 在同一個Target中完成同一個APP的不同版本,進行區(qū)分
  • 在Debug或Release版本中進行不同的操作

編譯標(biāo)記

在OC中刨肃,使用 #param來標(biāo)記代碼區(qū)間
在Swift中古拴,使用// MARK:來標(biāo)記代碼區(qū)間
還有 // TODO:// FIXME:來提示工作尚未完成或需要修改的地方

注意:這些都是區(qū)分大小寫的

給方法添加文檔說明,可使用快捷鍵 alt+command+/真友,這樣在使用時候黄痪,使用alt+單擊可以查看該方法的文檔說明

2016-11-29

單例的創(chuàng)建


class MyManager{
    static let shared = MyManager()
    private init(){
        
    }
    
    //在初始化類變量的時候,Apple會將這個初始化包裝在一次 swift_once_block_invoke 中盔然,以保證他的唯一性桅打,類似 dispatch_once 的方式
    //加入一個私有的初始化方法,覆蓋默認(rèn)的公開初始化方法愈案,這樣挺尾,其他地方就不能夠通過 init 來生成自己的 MyManager 實例,也保證了單例的唯一性
}

let manager = MyManager.shared


實例方法的動態(tài)調(diào)用


class MyClass{
    func method(num: Int) -> Int {
        return num + 1
    }
}

//如果想要調(diào)用method方法站绪,一般是生成 MyClass 的實例遭铺,使用 .method 來調(diào)用

let obj = MyClass()
obj.method(num: 2)

//或者使用 Swift 的 Type.instanceMethod 的語法來生成一個可以柯里化的方法
let f = MyClass.method //f 的類型是 (MyClass) -> (Int) -> Int
let obj1 = MyClass()
//知道了f的類型,就不難理解為何這樣調(diào)用了
f(obj1)(2)

//注:這種方法只適用于實例方法恢准,對于屬性的getter和setter不可以

//還有一種情況魂挂,實例方法和類型方法名字沖突時

class MyClass1{
    func method(num: Int) -> Int {
        return num + 1
    }
    
    class func method(num: Int) -> Int{
        return num + 2
    }
}

// 使用 MyClass1.method 默認(rèn)取出來的是類型方法,解決方法是顯式的加上類型聲明

let method1 = MyClass1.method // class func
let method2: (Int) -> Int = MyClass1.method // class func
let method3: (MyClass1) -> (Int) -> Int = MyClass1.method // func method 的柯里化版本

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末馁筐,一起剝皮案震驚了整個濱河市涂召,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敏沉,老刑警劉巖果正,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異盟迟,居然都是意外死亡秋泳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門队萤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轮锥,“玉大人,你說我怎么就攤上這事要尔∩岫牛” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵赵辕,是天一觀的道長既绩。 經(jīng)常有香客問我,道長还惠,這世上最難降的妖魔是什么饲握? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上救欧,老公的妹妹穿的比我還像新娘衰粹。我一直安慰自己,他們只是感情好笆怠,可當(dāng)我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布铝耻。 她就那樣靜靜地躺著,像睡著了一般蹬刷。 火紅的嫁衣襯著肌膚如雪瓢捉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天办成,我揣著相機與錄音泡态,去河邊找鬼。 笑死迂卢,一個胖子當(dāng)著我的面吹牛某弦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播而克,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼刀崖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拍摇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤馆截,失蹤者是張志新(化名)和其女友劉穎充活,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜡娶,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡混卵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了窖张。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幕随。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖宿接,靈堂內(nèi)的尸體忽然破棺而出赘淮,到底是詐尸還是另有隱情,我是刑警寧澤睦霎,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布梢卸,位于F島的核電站,受9級特大地震影響副女,放射性物質(zhì)發(fā)生泄漏蛤高。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望戴陡。 院中可真熱鬧塞绿,春花似錦、人聲如沸恤批。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽开皿。三九已至涧黄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赋荆,已是汗流浹背笋妥。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留窄潭,地道東北人春宣。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像嫉你,于是被迫代替她去往敵國和親月帝。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫幽污、插件嚷辅、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評論 4 62
  • MSWeakTimer地址:https://github.com/mindsnacks/MSWeakTimer 基...
    Arnold134777閱讀 3,622評論 3 4
  • 董明明閱讀 407評論 5 3
  • 我們從火車上下來,已經(jīng)五點多了距误。意料之中的簸搞,我們買不到車票,在懷化要停留一個晚上准潭。 從火車站往右轉(zhuǎn)向下走一條長長的...
    厚厚的大樹閱讀 304評論 0 0
  • 不要埋怨過去刑然,人兒活在這世上寺擂,僅僅就那短短的幾十年,樂觀點看待生活萬事泼掠,簡單點對待人間千變怔软,總比杞人憂天,一副死人...
    一念花君臨天閱讀 240評論 0 0