02 Swift元組/!與?簡單介紹/字符串

1.元組

1.1什么是元組

在其他語言中很早就有元組這個概念, 但是對于OC程序員來說這是一個新的概念
官方定義:元組(tuples)把多個值組合成一個復合值.
元組內的值可以是任意類型, 并不需要是相同的類型.
自定義(我定義):將多個相同對或者不同類型的值用一個小括號起來就是一個元組.

1.2定義元組(代碼):

let student = ("jianshu", 30, 22.2)
print(student)
print(student.0)
print(student.1)
print(student.2)

其實元組定義其實和結構體很像, 只是不需要提前定義類型.
元組其實是復合類型, 小括號中可以寫任何類型
也可以指定數據類型
如果指定餓了數據類型, 那么對應的必須是其他定的數據類型, 否則會報錯.

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是通過傳入指針或者返回結構體的方式來返回多個值的, 而有了元組之后就可以實現讓一個函數返回多個值

2 Swift可選值

**使用可選類型(optionals)來處理值可能缺失的情況. **
C和Objective-C中沒有可選類型這個概念
最接近的是OC中的一個特性,
一個方法要么返回一個對象, 要么返回nil, nil表示"缺少一個合法的對象"
可選值:optionals有兩種狀態

1.有值
2.沒有值

?表示兩種狀態, 一種是有值(有具體的某個值), 一種是沒有值(沒有代表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)")
}

輸出結果: 有值: Optionals(10)

var optValue: Int?
var optValue: Int? = nil
if optValue != nil
{
    print("有值:\(optValue)")
}else
{
    print("沒有值:\(optValue)")
}

輸出結果:沒有值:nil

var optValue: Int? = nil
if optValue != nil
{
    print("有值:\(optValue)")
}else
{
    print("沒有值:\(optValue)")
}

輸出結果:沒有值:nil

2.2提取可選類型的值(使用!強制解析)

將optValue中的整型值強制拿出來賦值給變量result, 換句話說就是告訴編譯器optValue一定有值
因為可選類型有兩種狀態有值和沒有值, 所以需要告訴編譯器到底有沒有值
需要注意的是如果強制解析optValue
但是optValue中沒有值時會引發一個運行時錯誤

var optValue: Int? = 9
var result: Int = optValue!
print(result)

輸出結果:9

var optValue: Int?
var result: Int = optValue!
print(result)

結果為報錯:
fatal error:
unexpectedly found nil while unwrapping an Optional value

2.3可選綁定

為了更安全的解析可選類型的值, 一般情況下使用可選綁定
如果optValue沒有值就不會做任何操作
如果optValue有值會返回true并將optValue的值賦值給result執行大括號中的內容

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值的時候需要在具體的操作,比如調用方法、屬性、下標索引等前面需要加上一個?,如果是nil值,也就是Optional.None,會跳過后面的操作不執行,如果有值,就是Optional.Some,可能就會拆包(unwrap),然后對拆包后的值執行后面的操作,來保證執行這個操作的安全性,比如:

let hashValue = strValue?.hashValue

strValue是Optional的字符串,如果strValue是nil,則hashValue也為nil,如果strValue不為nil,hashValue就是strValue字符串的哈希值(其實也是用Optional wrap后的值)

另外,?還可以用在安全地調用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,所以它的具體實現有沒有download方法是不確定的。Swift提供了一種在參數括號前加上一個?的方式來安全地調用protocol的optional方法。

另外如果你需要像下面這樣向下轉型(Downcast),可能會用到 as?:

 if let dataSource = object as?         UITableViewDataSource {
let rowsInFirstSection  = dataSource.tableView(tableView, numberOfRowsInSection: 0)
}

到這里我們看到了?的幾種使用場景:
1.聲明Optional值變量
2.用在對Optional值操作中,用來判斷是否能響應后面的操作
3.用于安全調用protocol的optional方法
4.使用 as? 向下轉型(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的,盡情調用吧” ,比如這種情況:

if strValue {
    let hashValue = strValue!.hashValue
}

{}里的strValue一定是非nil的,所以就能直接加上!,強制拆包(unwrap)并執行后面的操作。 當然如果不加判斷,strValue不小心為nil的話,就會出錯,crash掉。

考慮下這一種情況,我們有一個自定義的MyViewController類,類中有一個屬性是myLabel,myLabel是在viewDidLoad中進行初始化。因為是在viewDidLoad中初始化,所以不能直接聲明為普通值:var myLabel : UILabel,因為非Optional的變量必須在聲明時或者構造器中進行初始化,但我們是想在viewDidLoad中初始化,所以就只能聲明為Optional:var myLabel: UILabel?, 雖然我們確定在viewDidLoad中會初始化,并且在ViewController的生命周期內不會置為nil,但是在對myLabel操作時,每次依然要加上!來強制拆包(在讀取值的時候,也可以用?,謝謝iPresent在回復中提醒),比如:

myLabel!.text = "text"
myLabel!.frame = CGRectMake(0, 0, 10, 10)
...

對于這種類型的值,我們可以直接這么聲明:var myLabel: UILabel!, 果然是高(hao)大(gui)上(yi)的語法!, 這種是特殊的Optional,稱為Implicitly Unwrapped Optionals, 直譯就是隱式拆包的Optional,就等于說你每次對這種類型的值操作時,都會自動在操作前補上一個!進行拆包,然后在執行后面的操作,當然如果該值是nil,也一樣會報錯crash掉。

var myLabel: UILabel! //!相當于下面這種寫法的語法糖
var myLabel: ImplicitlyUnwrappedOptional<UILabel>
那么!大概也有兩種使用場景

1.強制對Optional值進行拆包(unwrap)
2.聲明Implicitly Unwrapped Optionals值,一般用于類中的屬性


解釋二:
從IB中拖線的控件對應的變量:

// 系統自帶
@IBOutlet weak var display: UILabel!

// 如果這樣
@IBOutlet weak var display: UILabel?

?表示display是一個可選類型(optionals),!表示對可選類型進行強制解包,如果解包的變量是nil,程序就會崩潰.
系統自帶的相當于在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中的字符占一個字節, 因為它只包含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結尾的, 例如

char *StringV = "abc\0def";
printf("%s", StringV);

輸出結果:abc

OC語言中的字符串也是一\0結尾的 例子就不再舉了
Swift中的字符串和C語言/OC語言中的字符串是不一樣的

var StringV = "abc\0def"
print(StringV)

輸出結果:abcdef
將兩個字符串合并在一起:
OC

NSMutableString *str1 = [NSMutableString stringWithString:@"abc"];
NSString *str2 = @"def";
[str1 appendString: str2];
NSLog(@"%@", str1);

輸出結果:abcdef

Swift:

var str1 = "jian"
var str2 = "shu"
var str = str1 + str2
print(str)

輸出結果: 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(@"不相等");
}

輸出結果: 相等

Swift:

Swift: (== , != , >= , <= )這些是Swift中字符串的比較符號, 和C語言的strcmp一樣的是逐一比較

var str1 = "abc"
var str2 = "abc"
if str1 == str2
{
    print("相等")
}else{
    print("不相等")
}

輸出結果: 相等

var str1 = "abc"
var str2 = "adc"
if str1 >= str2
{
    print("大于等于")
}else{
    print("不大于等于")
}

輸出結果: 大于等于

3.4大小寫轉換

OC:

NSString *str = @"abc";
NSLog(@"%@", [str uppercaseString]);
NSLog(@"%@", [str lowercaseString]);

輸出結果: ABC
abc

Swift:

var str = "abc"
print(str.uppercaseString)
print(str.lowercaseString)

輸出結果: ABC
abc

3.5轉換成基本數據類型

OC:

NSString *str = @"250";
NSInteger number = [str integerValue];
NSLog(@"%tu", number);

輸出結果: 250

如果str不能轉換為整數, 那么可選類型返回nil
str = "250sb" 不能轉換所以可能為nil
這句話, 我也不是很理解,望各位讀者見諒, 如果有自己的想法, 歡迎評價

var str = "250"
var number: Int? = Int(str)
if number != nil
{
    // Swift以前的版本中的printIn會自動拆包, 現在的不會
    print(number!)
}

作者說

本片文章介紹的知識點并不是多, 主要就是關于!與? 他們的使用, 目前的我, 也沒有辦法熟練的使用, 只是當報錯的時候, 再解決, 抱歉.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容