學(xué)習(xí)Swift的一些Tips

前言:

最近幾天在看《100個Swift必備tips》這本書婿失,本篇為讀書筆記体斩,以作總結(jié)記錄用猜欺。


protocol的方法聲明為mutating:

swift里,protocol中定義的方法既可以被class實現(xiàn)吮龄,也可以被structenum來實現(xiàn)俭茧。但若是被后兩者實現(xiàn),默認(rèn)情況下漓帚,實現(xiàn)的方法內(nèi)部是無法更改structenum變量母债。若你將要定義的協(xié)議可能需要被structenum實現(xiàn),請在定義協(xié)議方法時尝抖,加上關(guān)鍵字mutating场斑。

為方便起見,若定義的協(xié)議需要被structenum實現(xiàn)牵署,建議在協(xié)議中定義方法時均添加mutating關(guān)鍵字漏隐。無論你定義的方法需不需要更改變量。


Sequence 協(xié)議:

Swift 中的 Sequence(一)
Swift 中的 Sequence(二)


元組Tuple:

讓我們想想奴迅,在C或OC中我們想讓函數(shù)返回多個值時青责,應(yīng)該怎么實現(xiàn)?你可以將多個返回值拼裝成一個DictionaryModel再返回取具。你還可以使用“指針類型參數(shù)”來傳遞值脖隶。

    CGRect small;
    CGRect large;
    CGRectDivide(self.view.bounds, &small, &large, 20, CGRectMinXEdge);

Swift中,就變得很簡單了暇检,只需返回一個Tuple就可以了产阱。對于元組里的元素,既可以像數(shù)組那樣通過下標(biāo)來訪問块仆,也可以像字典那樣通過key來訪問构蹬。


可選鏈:

像下面的代碼,即便Toy類中的name屬性不是可選型的悔据,但是最終獲取到的結(jié)果toyName仍然是可選的庄敛,因為在整個調(diào)用鏈條中pet,toy都是可選的,都有可能為nil科汗,而提前中止調(diào)用鏈條藻烤,返回nil
既然返回了nil,就說明結(jié)果是可選的怖亭,是String?型的涎显。因此,我們要用if let語句來解包兴猩。

if let toyName = xiaoming.pet?.toy?.name {
}

使參數(shù)可變 inout:

Swift中期吓,方法參數(shù)默認(rèn)是不可變的,不能在方法內(nèi)部修改參數(shù)的值峭跳。
若你真的想直接修改參數(shù)的值膘婶,則需用inout關(guān)鍵字來修飾參數(shù)缺前。 如此蛀醉,則在方法內(nèi)部就可以直接修改參數(shù)了,且inout讓參數(shù)具有了“傳址調(diào)用”的能力衅码,因此在調(diào)用時要在參數(shù)名前加&拯刁。

下面代碼定義了一個將變量重置為0的方法reset

    func reset(x: inout Int) {
        x = 0;
    }
        var x = 5
        self.reset(x: &x)
        print("result:x=\(x)")
        // log:   result:x=0

自定義下標(biāo) subscript:

在編程語言中,都可以以下標(biāo)來訪問Array逝段、Dictionary等集合對象垛玻。
Swift中可就更厲害了,它支持給任何類奶躯、結(jié)構(gòu)體和枚舉自定義下標(biāo)帚桩,使它們都可以以下標(biāo)的形式被訪問。
無論是項目中你自己定義的類嘹黔,還是原先就有下標(biāo)的集合類账嚎,你都可以自定義下標(biāo)訪問它們!

自定義下標(biāo)儡蔓,用subscript關(guān)鍵字郭蕉,非常類似用關(guān)鍵字init自定義構(gòu)造器。

比如下面的代碼喂江,我們拓展了Array的下標(biāo)召锈,使其下標(biāo)可以為數(shù)組,讀寫任意位置的元素获询。

extension Array {
    
    subscript(indexs: [Int]) -> [Element] {
        
        get {
            var resultArr = [Element]()
            for index in indexs {
                assert(index<self.count, "index out of range")
                resultArr.append(self[index])
            }
            return resultArr
        }
        
        set {
            
            for (index, i) in indexs.enumerated() {
                assert(i<self.count, "index out of range")
                self[i] = newValue[index]
            }
        }
    }
}

        var array = [1, 2, 3, 4, 5, 6]
        let resultArr = array[[0,1,2]] // 獲取下標(biāo)[1,2,3]的值
        print(resultArr)
        // log ————> [1,2,3]
        
        array[[0,1,2]] = [0,0,0] // 修改下標(biāo)[1,2,3]的值
        print(array)
        // log ————> [0,0,0,4,5,6]

Any 和 AnyObject:

簡單來說涨岁,AnyObject表示任何class類型;
Any表示任何類型,包括任何class烟馅、struct逊彭、enum類型。

我們知道沮尿,在OCid代表任何類型,并也有經(jīng)常見于Cocoa框架中,而Swift用的框架仍為Cocoa畜疾。為了能完美對接赴邻,Swift不得不發(fā)明個與OCid相對應(yīng)的類型,這便是AnyObject的來歷啡捶。(AnyObject其實是個協(xié)議姥敛,Swift中的所有class均實現(xiàn)了該協(xié)議。)

但是很遺憾的是瞎暑,Swift中的所有的基本類型彤敛,包括ArrayDictionary這些在OC中為class的東西,統(tǒng)統(tǒng)都是struct了赌。

所以墨榄,蘋果就又新增了更特殊,更強(qiáng)大勿她,能代表任何類型的Any袄秩。


多類型和容器:

按理說,數(shù)組中存入的元素都應(yīng)該是類型相同的逢并。但是在Swift中有AnyAnyObject這兩個很特殊的之剧,代表任何類型的類型。試想:若我們在定義數(shù)組時砍聊,將數(shù)組元素申明為AnyAnyObject背稼,是不是就可以存入不同類型的元素了。不管是Int還是String玻蝌,它們也是AnyAnyObject類型啊蟹肘。

let array: [Any] = [1, "string"]

這樣確實是可以的,但這樣是極不安全的灶伊,我們將其以Any的方式存入數(shù)組疆前,是一種類型提升,這樣會丟失很多原本具有的數(shù)據(jù)聘萨。若你從該數(shù)組中取出string竹椒,它便不具備原本String具有的能力了,包括屬性和方法等米辐。此時胸完,若你調(diào)用這些屬性或方法的話,程序就會出問題翘贮。

其實赊窥,數(shù)組中存入的元素,并不一定必須得是相同類型的狸页,也可以是實現(xiàn)同一協(xié)議的不同類型锨能。

像下面這樣扯再,因為IntString本身都是實現(xiàn)了CustomStringConvertible協(xié)議的。我們可以將數(shù)組申明為『實現(xiàn)了CustomStringConvertible協(xié)議』的類型址遇。

        let array: [CustomStringConvertible] = [1, "string"]
        
        for item in array {
            print(item.description);
        }

public protocol CustomStringConvertible {

    public var description: String { get }
}

還有另一種做法是使用enum可以帶有值的特點熄阻,將類型信息封裝到特定的enum中。下面定義了一個枚舉AnyType倔约。

enum AnyType {
        case IntType(Int)
        case StringType(String)
    }
let mixedArr = [AnyType.IntType(1), AnyType.StringType("string")]
        
        for item in mixedArr {
            switch item {
            case let .IntType(i):
                print(i)
            case let .StringType(str):
                print(str)
            }
        }
        

屬性觀察:

Swift讓屬性觀察這件事變得異常簡單秃殉。下面代碼觀察了People類的count屬性,若其值小于0浸剩,則打印提示信息钾军。

class People: NSObject {

    var count: Int {
        willSet {
            print("count----willSet")
        }
        didSet {
            print("count----didSet")
            if(count<0){
                print("count不能小于0")
            }
        }
    }
    
    override init() {
        count = 0
    }
}

let people = People()
people.count = -10

需要注意的是,Swift中的屬性有『存儲屬性』和『計算屬性』之分绢要。前者會在內(nèi)存中實際分配地址來存儲屬性吏恭,而后者并不是實際存于內(nèi)存的,它只是通過提供getset兩個方法來訪問袖扛,讀寫該屬性(它和普通的方法很類似)砸泛。

Swift中的『計算型屬性』是無法使用willSet/didSet屬性觀察的十籍,也就是說在定義屬性時蛆封,不能同時出現(xiàn)setwillSet/didSet。因為要監(jiān)聽計算型屬性勾栗,我們完全可以在set里面添加監(jiān)聽屬性的處理代碼惨篱。

有時,我們往往需要觀察一個屬性围俘,但是砸讳,這個屬性是別人定義的,我們不便直接在源代碼里寫didSet用以監(jiān)聽界牡。此時簿寂,子類化該類,重寫其屬性宿亡,在重寫中對該屬性添加didSet監(jiān)聽是個很好的解決方案常遂。
更值得說的是: 子類化該類,重寫其屬性挽荠,然后添加didSet監(jiān)聽克胳,竟然可以用在父類是計算型屬性的情況下。也就是說圈匆,這也是解決Swift中計算型屬性無法寫didSet監(jiān)聽的一種方案了漠另,即把didSet寫到子類重寫的屬性中去。


單例的最正確寫法:

用兩個關(guān)鍵字static let修飾跃赚,可以限制sharedInstance是全局且不可變的笆搓,這就有了『單例』的意思了。但是還不夠,還要堵住其他構(gòu)造途徑满败,防止調(diào)用其他構(gòu)造器創(chuàng)建實例窘奏,所以在原本的init方法前加上了private關(guān)鍵字。

class UserInfoManager: NSObject {
    static let sharedInstance = UserInfoManager()
    private override init() {}
}
let userInfo = UserInfoManager.sharedInstance

@UIApplicationMain:

對于一個Objective-C的iOS項目葫录,Xcode會自動幫我們生成一個main.m文件着裹,其中有個main函數(shù)。

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

main函數(shù)里調(diào)用了UIKitUIApplicationMain方法米同,這個方法根據(jù)第三個參數(shù)初始化一個UIApplication或者子類的對象并開始接收事件(默認(rèn)傳入的是nil骇扇,意味使用默認(rèn)的UIApplication)。最后一個參數(shù)指定了AppDelegate類作為委托面粮,用來接收didFinishLaunchingWithOptions:applicationDidEnterBackground:等有關(guān)程序生命周期的方法少孝。

后兩個參數(shù)都可以傳入自定義的子類來完成更加個性化的需求。

另外熬苍,main函數(shù)雖然標(biāo)明返回一個int稍走,但是它不會真正返回。它會一直存在于內(nèi)存中柴底,直到用戶或系統(tǒng)將其強(qiáng)制終止婿脸。

..... 現(xiàn)在,我們來看看在Swift中情況是怎樣的柄驻。

可以看到狐树,在Swift的iOS項目中找不到main.m文件,但是卻在AppDelegate類開頭多了個@UIApplicationMain標(biāo)簽鸿脓。其實抑钟,這個標(biāo)簽的作用就是上面所說的main函數(shù)的作用:
初始化一個默認(rèn)為UIApplication類的實例來接收事件,指定AppDelegate為委托來接收程序生命周期方法野哭。

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }
...
...
}

所以說在塔,Swift的iOS項目中,并不是不需要main函數(shù)拨黔,而是通過添加@UIApplicationMain標(biāo)簽蛔溃,Xcode幫我們自動處理了main函數(shù)的邏輯。

當(dāng)然蓉驹,這個標(biāo)簽并不是必須的城榛,若你需要指定子類化的UIApplicationAppDelegate,則可以自己給項目中添加個main.m文件态兴,實現(xiàn)main函數(shù)狠持,并指定這兩個子類化的實例為參數(shù)。


如何動態(tài)地獲取一個實例的類型:

方法一瞻润,若類是繼承于NSObject類的喘垂,則我們可以利用OC的運行時:

public func object_getClass(_ obj: Any!) -> Swift.AnyClass!
        let people = People()
        let peoType: AnyClass! = object_getClass(people)
        print(peoType)
        // log ----> People

方法二:用一個全局的函數(shù)type(of:)甜刻,如下:

        let people = People()
        let peoType = type(of: people)
        print(peoType)
        // log ----> People

// type(of:)方法是Swift3.0新增的,代替了前期版本中的dynamicType屬性(Swift3.0之前正勒,使用該屬性可返回該對象的類型)得院。


自省:

自收抡辍:向一個對象發(fā)出詢問祥绞,以確定它是不是屬于某個類,這種操作就稱為“自省”鸭限。

OC中我們是這樣判斷一個對象是不是屬于某個類的:

if([_type isKindOfClass:[NSString class]]){
            
}

Swift中蜕径,若該類是繼承自NSObject的,則也有上面相應(yīng)的兩個方法:

class People: NSObject {
    
}
        let peo = People()
        if peo.isKind(of: People.self) {
            print("isKind")
        }
        if peo.isMember(of: People.self) {
           print("isMember")
        }

除此外败京,Swift提供了更強(qiáng)大簡潔的關(guān)鍵字is兜喻,同樣能達(dá)判斷類型的效果。
而且is的強(qiáng)大在于赡麦,它不僅適用于class朴皆,在structenum中,它同樣是可用的泛粹。

        if peo is People {
            print("isKind")
        }

KVO:

Swift中也可以使用KVO,但是僅限于在NSObject子類中遂铡。因為KVO是基于KVC和動態(tài)派發(fā)技術(shù)的,而這些都是NSObject運行時的概念戚扳。另外忧便,由于Swift為了提高效率族吻,默認(rèn)禁止了動態(tài)派發(fā)帽借,因此想用Swift使用KVO的話,還要將被觀測的對象標(biāo)為dynamic超歌。

簡單來說砍艾,Swift要使用KVO有兩個限制:
1.被觀測的對象屬于NSObject類;2.被觀測的對象屬性被標(biāo)為dynamic巍举。

下面的代碼脆荷,我們觀察People類里的money屬性,它即為被觀測的對象懊悯,所以要將其標(biāo)為dynamic蜓谋。

class People: NSObject {
    dynamic var money = 0 // 標(biāo)為dynamic
    
}

peoplemoney屬性添加觀察,并重寫回調(diào)方法炭分,在其中拿到改變后的新值桃焕。并且,一定要記得在deinit方法中移除觀察捧毛。

private var myContext = 0

class ViewController: UIViewController {
    
    var people = People()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 添加觀察
        people.addObserver(self, forKeyPath: "money", options: .new, context: &myContext)
        people.money = 3
    }
    
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if let change = change, context == &myContext{
            let newValue = change[NSKeyValueChangeKey.newKey]
            if let newValue = newValue {
                print(newValue)
            }
        }
    }
    
    deinit {
        people.removeObserver(self, forKeyPath: "money")
    }
  
}

但是观堂,在實際開發(fā)過程中让网,我們往往會遇到不符合上述兩點的情況港令,那在這種情況下骏掀,我們還能不能使用KVO呢根欧?
若被觀測的對象不繼承自NSObject的話隐轩,那真的無法使用KVO,只能自己利用“屬性觀察”自己實現(xiàn)一套觀察機(jī)制(在didSet里發(fā)送通知炭臭,通知外界屬性值已改變)奶镶。
若被觀測的對象我們無法直接標(biāo)為dynamic羹奉,比如系統(tǒng)類的對象鲫尊。那我們可以子類化該類笔横,重寫該屬性惜犀,重寫時將其標(biāo)為dynamic

如下面的例子狠裹,假如我們要對Peoplemoney屬性進(jìn)行觀測虽界,但是又不方便或不允許將money屬性標(biāo)為dynamic,所以我們新建繼承自PeopleChildPeople類涛菠,在其中重寫money時將其標(biāo)為dynamic莉御。

class People: NSObject {
    var money = 0
    
}

class ChildPeople: People {
    
    dynamic override var money: Int {
        get {
            return super.money
        }
        set {
            super.money = newValue
        }
    }
}

判等:

我們可以實現(xiàn)Equatable中的上面方法,來完成自定義對象判等邏輯俗冻。NSObject實現(xiàn)了Equatable協(xié)議礁叔,若類是繼承自NSObject的,則不需我們自己實現(xiàn)該協(xié)議迄薄。

像下面代碼琅关,我們自定義了People對象的判等邏輯:只要倆人的錢一樣多,就相等讥蔽。

class People {
    var money = 0
    
    init(mon: Int){
        money = mon
    }
}

extension People: Equatable {
    
    public static func ==(lhs: People, rhs: People) -> Bool {
        return lhs.money == lhs.money
    }
}

若類僅僅是繼承自NSObject,而不自己實現(xiàn)該協(xié)議方法涣易,則==操作符默認(rèn)是NSObject里的實現(xiàn),即對指針引用對象內(nèi)存地址的比較冶伞。除非倆引用同一塊內(nèi)存地址新症,否則不相等。

Swift里是用===來比較引用的內(nèi)存地址是否相等响禽。

下面創(chuàng)建的people1people2內(nèi)存地址是不同的徒爹,所以不會打印東西。

        let people1 = People(mon: 10)
        let people2 = People(mon: 10)
        if people1===people2 {
            print("===")
        }
屏幕快照 2017-07-03 下午3.08.01.png

類簇:

字符串格式化:

OC的字符串可以通過占位符%@/%f/%d等芋类,將多個元素拼接成新的字符串隆嗅。

    NSString *name = @"wang66";
    NSString *str = [NSString stringWithFormat:@"%@%@", @"name =", name];
    NSLog(@"%@",str);

Swift的字符串中則不需要占位符了,直接可以在字符串中插值侯繁。

        let name = "wang66"
        let str = "name = \(name)"
        print(str)
        // log ----> name = wang66

這樣確實非常簡潔了胖喳,但是若是出現(xiàn)將小數(shù)保留兩位小數(shù)的需求時該怎么辦呢?巫击,OC中是這樣的:

    CGFloat distance = 12.21424;
    NSString *str = [NSString stringWithFormat:@"%0.2f%@", distance,@"km"];
    NSLog(@"%@",str);

但是在Swift中就不能繼續(xù)簡潔了禀晓,而是要用``String(format:)

        let distance = 12.26578
        let distanceStr = String(format: "%0.2f", distance)
        let str = "\(distanceStr)km"
        print(str)
//         log ----> 12.27km


Options:

我們從UIView的一個動畫方法說起精续,下面這個執(zhí)行動畫方法有個options參數(shù),意為“選項”粹懒,用以配置動畫重付。在OC中是這樣的:

    [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionCurveEaseOut animations:^{
        NSLog(@"動畫進(jìn)行中...");
    } completion:^(BOOL finished) {
        NSLog(@"動畫完成...");
    }];

options參數(shù)是枚舉類型的,可以以|將多個枚舉值連接凫乖,組合使用确垫。UIViewAnimationOptions的定義如下,因為該參數(shù)允許組合枚舉各值帽芽,所以被定義成了支持掩碼位移的NS_OPTIONS:(它和NS_ENUM的區(qū)別主要是它自動支持掩碼位移)

typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {
    UIViewAnimationOptionLayoutSubviews            = 1 <<  0,
    UIViewAnimationOptionAllowUserInteraction      = 1 <<  1, // turn on user interaction while animating
    UIViewAnimationOptionBeginFromCurrentState     = 1 <<  2, // start all views from current value, not initial value
    UIViewAnimationOptionRepeat                    = 1 <<  3, // repeat animation indefinitely
    UIViewAnimationOptionAutoreverse               = 1 <<  4, // if repeat, run animation back and forth
    UIViewAnimationOptionOverrideInheritedDuration = 1 <<  5, // ignore nested duration
    UIViewAnimationOptionOverrideInheritedCurve    = 1 <<  6, // ignore nested curve
    UIViewAnimationOptionAllowAnimatedContent      = 1 <<  7, // animate contents (applies to transitions only)
    UIViewAnimationOptionShowHideTransitionViews   = 1 <<  8, // flip to/from hidden state instead of adding/removing
    UIViewAnimationOptionOverrideInheritedOptions  = 1 <<  9, // do not inherit any options or animation type

而在Swift中删掀,options參數(shù)的情況卻大有不同。與上面OC對應(yīng)的方法导街,在Swift中是這樣的:

        UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseIn, .curveEaseOut], animations: {
            print("動畫進(jìn)行中...")
        }) { isFinshed in
            print("動畫結(jié)束...")
        }

Swift的枚舉無法支持位移賦值披泪。所以options并不是枚舉,而是一個實現(xiàn)OptionSet協(xié)議的struct搬瑰,各個選項值為staticget屬性款票。
要達(dá)到像OC中那樣多個選項值options|符號組合,在Swift中泽论,我們以集合包裝每個選項值艾少。 就像這樣:[.curveEaseIn, .curveEaseOut]

public struct UIViewAnimationOptions : OptionSet {

    public init(rawValue: UInt)

    public static var layoutSubviews: UIViewAnimationOptions { get }

    public static var allowUserInteraction: UIViewAnimationOptions { get } // turn on user interaction while animating

    public static var beginFromCurrentState: UIViewAnimationOptions { get } // start all views from current value, not initial value

    public static var `repeat`: UIViewAnimationOptions { get } // repeat animation indefinitely

    public static var autoreverse: UIViewAnimationOptions { get } // if repeat, run animation back and forth


weak delegate:

"委托代理"模式在iOS開發(fā)中可謂是最常用的模式,我們都知道翼悴,為了避免委托和代理對象互相引用缚够,無法釋放的問題,我們一般將委托的delegate屬性標(biāo)為weak弱引用鹦赎,主動示弱谍椅,以打破互相引用的僵局。

但是我們在Swift中钙姊,我們不能直接在任何一個delegate屬性前面加weak關(guān)鍵字修飾毯辅。因為Swift中的協(xié)議是可以被除了class外的structenum來實現(xiàn)的,而后兩者它們是值類型煞额,它們不是通過引用計數(shù)規(guī)則來管理內(nèi)存的,所以當(dāng)然不能以weak沾谜,這個ARC里的東西修飾膊毁。

所以,在Swift中使用“委托代理模式”基跑,首先要在定義協(xié)議時將其申明為只能被class實現(xiàn)婚温。

protocol DemoDelegate: class {
    func demoFunction()
}

或者,還有方案二:將定義的協(xié)議用@objc申明為Objective-C的媳否。因為在Objective-C中栅螟,協(xié)議只能被class實現(xiàn)荆秦。

@objc protocol DemoDelegate {
    func demoFunction()
}

Swift 命令行工具:

啟動REPL(Read-Eval-Print Loop)環(huán)境: 在終端輸入:xcrun swift來啟動。

屏幕快照 2017-07-05 下午2.00.31.png

然后就可以“交互式編程”了力图,在終端每輸入代碼步绸,然后回車,就會實時編譯執(zhí)行吃媒。

屏幕快照 2017-07-05 下午2.05.45.png

試試定義一個方法瓤介,并調(diào)用∽改牵可以看到它甚至還可以反饋給我們錯誤提示刑桑,提示我“調(diào)用myFunction(5)方法時缺少參數(shù)標(biāo)簽num∧贾郏”

屏幕快照 2017-07-05 下午2.07.14.png

打印對象祠斧,自定義description:

我們打印一下People的對象people

        let people = People(name: "wang66", mobile: "18693133051", address: "白石洲")
        print(people)
        // log ----> <LearnAlamofireDemo.People: 0x6080000d6960>

可以看到打印信息只有對象的類型People和內(nèi)存地址拱礁。但是這樣的信息幾乎沒什么用梁肿。

打印對象后展示什么信息,我們是可以定制的觅彰。

只要這個類實現(xiàn)CustomStringConvertible協(xié)議吩蔑,然后重寫description屬性,需要展示什么就return什么填抬。

public protocol CustomStringConvertible {

    public var description: String { get }
}

比如烛芬,我們在拓展中實現(xiàn)了自定制的description屬性:

class People {
    var name: String?
    var mobile: String?
    var address: String?
    
    init(name: String?, mobile: String?, address: String?) {
        self.name = name
        self.mobile = mobile
        self.address = address
    }
}

extension People: CustomStringConvertible {
    var description: String {
        get {
            return "[\(type(of:self)): name=\(self.name ?? "") | mobile=\(self.mobile ?? "") | address=\(self.address ?? "") ]"
        }
    }
    
}

打印結(jié)果如下,非常完美飒责。

        let people = People(name: "wang66", mobile: "18693133051", address: "白石洲")
        print(people)
        // log ----> [People: name=wang66 | mobile=18693133051 | address=白石洲 ]

斷言 assert:

有時我們寫的方法是有數(shù)據(jù)傳入限制的赘娄,但是當(dāng)我寫的代碼別人調(diào)用,或者以后我自己調(diào)用時宏蛉,可能都不熟悉這個方法具體需要傳入什么條件的數(shù)據(jù)遣臼,這有可能讓大家浪費不必要的時間。最好拾并,在調(diào)用傳入數(shù)據(jù)時有反饋提示揍堰。

斷言,可以很好地解決這個問題嗅义。當(dāng)調(diào)用者傳入的數(shù)據(jù)不符合條件時屏歹,編譯不會通過,且會打印出提示信息之碗。

printYourAge(age: -10)
    func printYourAge(age: Int) {
        assert(age >= 0, "年齡都是正數(shù)")
        print(age)
    }
屏幕快照 2017-07-05 下午3.18.13.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蝙眶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子褪那,更是在濱河造成了極大的恐慌幽纷,老刑警劉巖式塌,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異友浸,居然都是意外死亡峰尝,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門尾菇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來境析,“玉大人,你說我怎么就攤上這事派诬±拖” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵默赂,是天一觀的道長沛鸵。 經(jīng)常有香客問我,道長缆八,這世上最難降的妖魔是什么曲掰? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮奈辰,結(jié)果婚禮上栏妖,老公的妹妹穿的比我還像新娘。我一直安慰自己奖恰,他們只是感情好吊趾,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瑟啃,像睡著了一般论泛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛹屿,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天屁奏,我揣著相機(jī)與錄音,去河邊找鬼错负。 笑死坟瓢,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的湿颅。 我是一名探鬼主播载绿,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼油航!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起怀浆,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤谊囚,失蹤者是張志新(化名)和其女友劉穎怕享,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體镰踏,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡函筋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了奠伪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跌帐。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖绊率,靈堂內(nèi)的尸體忽然破棺而出谨敛,到底是詐尸還是另有隱情,我是刑警寧澤滤否,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布脸狸,位于F島的核電站,受9級特大地震影響藐俺,放射性物質(zhì)發(fā)生泄漏炊甲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一欲芹、第九天 我趴在偏房一處隱蔽的房頂上張望卿啡。 院中可真熱鬧,春花似錦菱父、人聲如沸颈娜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽讯沈。三九已至,卻和暖如春穿香,著一層夾襖步出監(jiān)牢的瞬間袜蚕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工亩钟, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留乓梨,地道東北人。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓清酥,卻偏偏與公主長得像扶镀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子焰轻,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354

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

  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,961評論 6 13
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫臭觉、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,095評論 4 62
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,802評論 1 10
  • 1、臟讀 臟讀是指在一個事務(wù)處理過程里讀取了另一個未提交的事務(wù)中的數(shù)據(jù)蝠筑。 當(dāng)一個事務(wù)正在多次修改某個數(shù)據(jù)狞膘,而在這個...
    yeying12321閱讀 317評論 0 0
  • 1944年,她穿著鮮艷的紅裙子 掠過年輕人的口哨什乙,在子彈中跳舞 二戰(zhàn)的戰(zhàn)火燒掉了她的房子 在灑滿月光的草棚里挽封,她放...
    蔣菱閱讀 267評論 0 1