阅读 555
Swift:let与var

Swift:let与var

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文同时参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

前言

我喜欢Swift这门编码语言是因为它足够简洁,用尽可能少的单词,去传达足够多的意思。不像Dart:有的时候我还得考虑用final还是用const琢磨一下。

更准确的说是,Swift简洁又不简单

今天给大家带来的是let与var的用法。

读完本篇,相信你编写Swift代码时,对于到底是使用let还是var来修饰一个变量,也能上一个台阶。

用let?还是用var?

我们都知道Swift中用let修饰不可变变量,用var修饰可变变量。

可是往往经验也会引导我们陷入一个误区。

我们先来一个OC的例子做引子,因为早些年编写Swift代码,基本上都是从OC的逻辑上搬运过来的:

- (NSString *)getNameWithSex:(BOOL)isMan {
    NSString *name;
    if (isMan) {
        name = @"season";
    }else {
        name = @"soso";
    }
    return  name;
}
复制代码

很简单的例子,函数入参是否是男性,如果是男性,那么名字就是season,否则名字是soso。

想想如果用Swift写,会什么写的呢,下面这种写法肯定没问题:

func getName(isMan: Bool) -> String {
    var name: String
    
    if isMan {
        name = "season"
    }else {
        name = "soso"
    }
    return name

}

let aName = getName(isMan: true)
print(aName)
复制代码

打印结果:

season
复制代码

你会说,这么简单,肯定没有问题。

那么请思考:函数中的var name: String改成let name: String,函数可不可正常运行呢?

如果对比OC的代码思路和经验,name这个String是可变的啊,它明明可能赋值为season也有可能赋值为soso,肯定要用var修饰呀。

不过实际运行时却会出乎你的意料:

func getName(isMan: Bool) -> String {
    let name: String
    
    if isMan {
        name = "season"
    }else {
        name = "soso"
    }
    return name

}

let aName = getName(isMan: true)
print(aName)
复制代码

打印结果:

season
复制代码

没有报错,打印正常。

如果这么写还可以理解:let name = isMan ? "season" : "soso"

可是明明在if和else中进行了不同的赋值,为何却可以用let

虽然在做赋值,但是if或者else只会进去一个,赋值具有唯一性,不可能同时既赋值season又赋值soso,只是以往的经验误导我们罢了,因为OC中变量都是可变的,我们被经验带歪了。

其实在很多开源代码中这种赋值屡见不鲜,只是我们没有仔细思考罢了,下面这段代码是我之前阅读ObjectMapper源码学习到的:

/// Convert a JSON String into an Object using NSJSONSerialization
public static func parseJSONString(JSONString: String) -> Any? {
    let data = JSONString.data(using: String.Encoding.utf8, allowLossyConversion: true)
    if let data = data {
        let parsedJSON: Any?
        do {
            parsedJSON = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)
        } catch let error {
            print(error)
            parsedJSON = nil
        }
        return parsedJSON
    }
    return nil
}
复制代码

是不是和我举的例子如出一辙,这个例子还包含了可选类型,而且还是在进行了do-catch赋值操作,也是用的let

总结

  • Swift推荐我们尽量用let去修饰变量,不变的变量永远比可变的变量更加安全与可靠。

    在编写代码的时候,你可以先一股脑的对变量都使用let修饰,当发现需要使用var修饰的时候,放心编译会给你报错的

  • 我们在用for in循环,以及函数的入参的时候,其实这些参数都是默认用let修饰的,如果你想让它们变成可变,请先用var修饰的变量去接受它,再做逻辑处理。

例子如下:

image.png

image.png

  • 我们一般使用guard let去进行解包,但是其实用guard var也是可以的,如果的你的解包的变量需要变化的话,说白了还是业务决定用法。

  • 经验固然重要,同时不能一味跟着经验走。毕竟OC和Swift的不同点实在太多了。

对于letvar的用法,大伙又有什么心得与体会呢,欢迎讨论与抛砖。

我们下期见。

文章分类
iOS
文章标签