1.元組
1.1什么是元組
在其他語言中很早就有元組這個概念, 但是對于OC程序員來說這是一個新的概念
官方定義:元組(tuples)把多個值組合成一個復合值.
元組內(nèi)的值可以是任意類型, 并不需要是相同的類型.
自定義(我定義):將多個相同對或者不同類型的值用一個小括號起來就是一個元組.
1.2定義元組(代碼):
let student = ("jianshu", 30, 22.2)
print(student)
print(student.0)
print(student.1)
print(student.2)
其實元組定義其實和結(jié)構(gòu)體很像, 只是不需要提前定義類型.
元組其實是復合類型, 小括號中可以寫任何類型
也可以指定數(shù)據(jù)類型
如果指定餓了數(shù)據(jù)類型, 那么對應的必須是其他定的數(shù)據(jù)類型, 否則會報錯.
let student: (String, Int, Double) = ("jianshu", 30, 22.2)
1.3定義元組其他方式
指定元組元素的名稱
let student = (name:"jianshu", age = 30, score: 43)
print(student.name)
print(student.age)
print(student.score)
通過指定的名稱提取元組對應的值, 會將對應的值賦值給對應位置的名稱
let (name, age, score) = ("jianshu", 30, 43)
print(name)
print(age)
print(score)
如果不關心元組中的某一個值可以利用_
通配符來忽略提取
let student = ("jianshu", 30, 43)
let (name, age, _) = student
print(name)
print(age)
1.4外話
在以前沒有元組之前C和OC是通過傳入指針或者返回結(jié)構(gòu)體的方式來返回多個值的, 而有了元組之后就可以實現(xiàn)讓一個函數(shù)返回多個值
2 Swift可選值
**使用可選類型(optionals)來處理值可能缺失的情況. **
C和Objective-C中沒有可選類型這個概念
最接近的是OC中的一個特性,
一個方法要么返回一個對象, 要么返回nil
, nil
表示"缺少一個合法的對象"
可選值:optionals有兩種狀態(tài)
1.有值
2.沒有值
?表示兩種狀態(tài), 一種是有值(有具體的某個值), 一種是沒有值(沒有代表nil
), 當?
修飾時,表示這個變量可能為nil
// 有值
var optValue: Int? = 9
// 沒有值
var optValue: Int?
var optValue: Int? = nil
2.1可選值可以利用if語句來進行判斷
var optValue: Int? = 10
if optValue != nil
{
print("有值:\(optValue)")
}else
{
print("沒有值:\(optValue)")
}
輸出結(jié)果: 有值: Optionals(10)
var optValue: Int?
var optValue: Int? = nil
if optValue != nil
{
print("有值:\(optValue)")
}else
{
print("沒有值:\(optValue)")
}
輸出結(jié)果:沒有值:nil
var optValue: Int? = nil
if optValue != nil
{
print("有值:\(optValue)")
}else
{
print("沒有值:\(optValue)")
}
輸出結(jié)果:沒有值:nil
2.2提取可選類型的值(使用!強制解析)
將optValue中的整型值強制拿出來賦值給變量result, 換句話說就是告訴編譯器optValue一定有值
因為可選類型有兩種狀態(tài)有值和沒有值, 所以需要告訴編譯器到底有沒有值
需要注意的是如果強制解析optValue
但是optValue中沒有值時會引發(fā)一個運行時錯誤
var optValue: Int? = 9
var result: Int = optValue!
print(result)
輸出結(jié)果:9
var optValue: Int?
var result: Int = optValue!
print(result)
結(jié)果為報錯:
fatal error:
unexpectedly found nil while unwrapping an Optional value
2.3可選綁定
為了更安全的解析可選類型的值, 一般情況下使用可選綁定
如果optValue沒有值就不會做任何操作
如果optValue有值會返回true并將optValue的值賦值給result執(zhí)行大括號中的內(nèi)容
var optValue: Int? = 9
if let result = optValue
{
print(result)
}
2.4!與?詳解
解釋一:
Optional其實是個enum攀细,里面有None和Some兩種類型。其實所謂的nil就是Optional.None, 非nil就是Optional.Some, 然后會通過Some(T)包裝(wrap)原始值,這也是為什么在使用Optional的時候要拆包(從enum里取出來原始值)的原因, 也是PlayGround會把Optional值顯示為類似{Some "hello world"}的原因,這里是enum Optional的定義:
enum Optional<T> : LogicValue, Reflectable {
case None
case Some(T)
init()
init(_ some: T)
/// Allow use in a Boolean context.
func getLogicValue() -> Bool
/// Haskell's fmap, which was mis-named
func map<U>(f: (T) -> U) -> U?
func getMirror() -> Mirror
}
聲明為Optional只需要在類型后面緊跟一個?即可哥力。如:
var strValue: String? //?相當于下面這種寫法的語法糖
var strValue: Optional<String>
上面這個Optional的聲明未巫,意思不是”我聲明了一個Optional的String值”, 而是”我聲明了一個Optional類型值,它可能包含一個String值筋栋,也可能什么都不包含”,也就是說實際上我們聲明的是Optional類型正驻,而不是聲明了一個String類型弊攘,這一點需要銘記在心仔涩。
建議再讀一遍上段文字扑浸。
一旦聲明為Optional的,如果不顯式的賦值就會有個默認值nil择浊。判斷一個Optional的值是否有值伤靠,可以用if來判斷:
if strValue {
//do sth with strValue
}
然后怎么使用Optional值呢捣域?文檔中也有提到說,在使用Optional值的時候需要在具體的操作宴合,比如調(diào)用方法焕梅、屬性、下標索引等前面需要加上一個?卦洽,如果是nil值贞言,也就是Optional.None,會跳過后面的操作不執(zhí)行阀蒂,如果有值该窗,就是Optional.Some,可能就會拆包(unwrap)蚤霞,然后對拆包后的值執(zhí)行后面的操作酗失,來保證執(zhí)行這個操作的安全性,比如:
let hashValue = strValue?.hashValue
strValue是Optional的字符串争便,如果strValue是nil级零,則hashValue也為nil,如果strValue不為nil,hashValue就是strValue字符串的哈希值(其實也是用Optional wrap后的值)
另外奏纪,?還可以用在安全地調(diào)用protocol類型方法上鉴嗤,比如:
@objc protocol Downloadable {
@optional func download(toPath: String) -> Bool;
}
@objc class Content: Downloadable {
//download method not be implemented
}
var delegate: Downloadable = Downloadable()
delegate.download?("some path")
因為上面的delegate是Downloadable類型的,它的download方法是optional序调,所以它的具體實現(xiàn)有沒有download方法是不確定的醉锅。Swift提供了一種在參數(shù)括號前加上一個?的方式來安全地調(diào)用protocol的optional方法。
另外如果你需要像下面這樣向下轉(zhuǎn)型(Downcast)发绢,可能會用到 as?:
if let dataSource = object as? UITableViewDataSource {
let rowsInFirstSection = dataSource.tableView(tableView, numberOfRowsInSection: 0)
}
到這里我們看到了?的幾種使用場景:
1.聲明Optional值變量
2.用在對Optional值操作中硬耍,用來判斷是否能響應后面的操作
3.用于安全調(diào)用protocol的optional方法
4.使用 as? 向下轉(zhuǎn)型(Downcast)
另外,對于Optional值边酒,不能直接進行操作经柴,否則會報錯:
//error: 'String?' does not have a member named 'hashValue'
//let hashValue = strValue.hashValue
// ^ ~~~~~~~~~
let hashValue = strValue.hashValue
上面提到Optional值需要拆包(unwrap)后才能得到原來值,然后才能對其操作墩朦,那怎么來拆包呢坯认?拆包提到了幾種方法,一種是Optional Binding氓涣, 比如:
if let str = strValue {
let hashValue = str.hashValue
}
還有一種是在具體的操作前添加!符號牛哺,好吧,這又是什么詭異的語法?!
直接上例子劳吠,strValue是Optional的String:
let hashValue = strValue!.hashValue
這里的!表示“我確定這里的的strValue一定是非nil的引润,盡情調(diào)用吧” ,比如這種情況:
if strValue {
let hashValue = strValue!.hashValue
}
{}里的strValue一定是非nil的痒玩,所以就能直接加上!淳附,強制拆包(unwrap)并執(zhí)行后面的操作。 當然如果不加判斷凰荚,strValue不小心為nil的話燃观,就會出錯褒脯,crash掉便瑟。
考慮下這一種情況,我們有一個自定義的MyViewController類番川,類中有一個屬性是myLabel到涂,myLabel是在viewDidLoad中進行初始化。因為是在viewDidLoad中初始化颁督,所以不能直接聲明為普通值:var myLabel : UILabel践啄,因為非Optional的變量必須在聲明時或者構(gòu)造器中進行初始化,但我們是想在viewDidLoad中初始化沉御,所以就只能聲明為Optional:var myLabel: UILabel?, 雖然我們確定在viewDidLoad中會初始化屿讽,并且在ViewController的生命周期內(nèi)不會置為nil,但是在對myLabel操作時,每次依然要加上!來強制拆包(在讀取值的時候伐谈,也可以用?烂完,謝謝iPresent在回復中提醒),比如:
myLabel!.text = "text"
myLabel!.frame = CGRectMake(0, 0, 10, 10)
...
對于這種類型的值诵棵,我們可以直接這么聲明:var myLabel: UILabel!, 果然是高(hao)大(gui)上(yi)的語法!, 這種是特殊的Optional抠蚣,稱為Implicitly Unwrapped Optionals, 直譯就是隱式拆包的Optional,就等于說你每次對這種類型的值操作時履澳,都會自動在操作前補上一個!進行拆包嘶窄,然后在執(zhí)行后面的操作,當然如果該值是nil距贷,也一樣會報錯crash掉柄冲。
var myLabel: UILabel! //!相當于下面這種寫法的語法糖
var myLabel: ImplicitlyUnwrappedOptional<UILabel>
那么!大概也有兩種使用場景
1.強制對Optional值進行拆包(unwrap)
2.聲明Implicitly Unwrapped Optionals值,一般用于類中的屬性
解釋二:
從IB中拖線的控件對應的變量:
// 系統(tǒng)自帶
@IBOutlet weak var display: UILabel!
// 如果這樣
@IBOutlet weak var display: UILabel?
?表示display是一個可選類型(optionals)忠蝗,!表示對可選類型進行強制解包羊初,如果解包的變量是nil,程序就會崩潰.
系統(tǒng)自帶的相當于在xib解檔賦值的時候什湘,進行了強制解包长赞;而后面修改后,賦值時沒有進行強制解包闽撤,所以后面使用display時得哆,需要這樣使用以獲取其屬性--
display!.text
以上的兩種解釋第一種比較詳細, 第二種凡是有做過一些小程序的人, 都能理解,簡單易懂
3 swift字符和字符串
3.1字符
// OC當中的字符
char charValue = 'a';
// swift當中的字符
var charValue: Character = "a"
Swift和OC字符不一樣
1.Swift是用雙引號
2.Swift中的字符類型和OC的也不一樣
OC中的字符占一個字節(jié), 因為它只包含ASCII表中字符
而Swift中的字符除了可以存儲ASCII表中的字符還可以存儲Unicode字符,
OC的字符是遵守ASCII標準的. Swift的字符是遵守Unicode標準的
所以可以存放世界上所有國家語言的字符(大部分)
// OC中
char charValue = '高';// 錯誤
// Swift中
var charValue: Character = "高' // 正確
注意:
雙引號只能存放一個字符, 如下寫法是錯誤的
var charValue : Character = "ab"
3.2字符串
C:
char *stringV = "ab";
char *stringV2 = "cd";
OC:
NSString *stringV = "ab";
Swift:
var stringV = "ab"
var stringV:String = "ab"
C語言中的字符串都是以\0結(jié)尾的, 例如
char *StringV = "abc\0def";
printf("%s", StringV);
輸出結(jié)果:abc
OC語言中的字符串也是一\0結(jié)尾的 例子就不再舉了
Swift中的字符串和C語言/OC語言中的字符串是不一樣的
var StringV = "abc\0def"
print(StringV)
輸出結(jié)果:abcdef
將兩個字符串合并在一起:
OC
NSMutableString *str1 = [NSMutableString stringWithString:@"abc"];
NSString *str2 = @"def";
[str1 appendString: str2];
NSLog(@"%@", str1);
輸出結(jié)果:abcdef
Swift:
var str1 = "jian"
var str2 = "shu"
var str = str1 + str2
print(str)
輸出結(jié)果: jianshu
3.3字符串比較
OC:
// 方法一:
NSString *str1 = @"abc";
NSString *str2 = @"abc";
if ([str1 compare: Str2] == NSOrderedSame)
{
NSLog(@"相等");
}else{
NSLog(@"不相等");
}
// 方法二:
NSString *str1 = @"abc";
NSString *str2 = @"abc";
if([str1 isEqualToString: str2])
{
NSLog(@"相等")
}else{
NSLog(@"不相等");
}
輸出結(jié)果: 相等
Swift:
Swift: (== , != , >= , <= )這些是Swift中字符串的比較符號, 和C語言的strcmp一樣的是逐一比較
var str1 = "abc"
var str2 = "abc"
if str1 == str2
{
print("相等")
}else{
print("不相等")
}
輸出結(jié)果: 相等
var str1 = "abc"
var str2 = "adc"
if str1 >= str2
{
print("大于等于")
}else{
print("不大于等于")
}
輸出結(jié)果: 大于等于
3.4大小寫轉(zhuǎn)換
OC:
NSString *str = @"abc";
NSLog(@"%@", [str uppercaseString]);
NSLog(@"%@", [str lowercaseString]);
輸出結(jié)果: ABC
abc
Swift:
var str = "abc"
print(str.uppercaseString)
print(str.lowercaseString)
輸出結(jié)果: ABC
abc
3.5轉(zhuǎn)換成基本數(shù)據(jù)類型
OC:
NSString *str = @"250";
NSInteger number = [str integerValue];
NSLog(@"%tu", number);
輸出結(jié)果: 250
如果str不能轉(zhuǎn)換為整數(shù), 那么可選類型返回nil
str = "250sb" 不能轉(zhuǎn)換所以可能為nil
這句話, 我也不是很理解,望各位讀者見諒, 如果有自己的想法, 歡迎評價
var str = "250"
var number: Int? = Int(str)
if number != nil
{
// Swift以前的版本中的printIn會自動拆包, 現(xiàn)在的不會
print(number!)
}
作者說
本片文章介紹的知識點并不是多, 主要就是關于!與? 他們的使用, 目前的我, 也沒有辦法熟練的使用, 只是當報錯的時候, 再解決, 抱歉.