小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文同时参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
前言
我喜欢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修饰的变量去接受它,再做逻辑处理。
例子如下:
-
我们一般使用
guard let
去进行解包,但是其实用guard var
也是可以的,如果的你的解包的变量需要变化的话,说白了还是业务决定用法。 -
经验固然重要,同时不能一味跟着经验走。毕竟OC和Swift的不同点实在太多了。
对于let
与var
的用法,大伙又有什么心得与体会呢,欢迎讨论与抛砖。
我们下期见。