讓不懂程式設計的人愛上iPhone開發(2018秋iOS12+Swift4.2+Xcode10版)-04
休息的怎樣了?是否已經迫不及待的想要繼續新的學習了呢?
好吧,接下來我們就做點實際的事情。
新增其它控制元件
到目前為止,我們的介面上只有以背景和一個按鈕,接下來還是新增一些其它介面控制元件吧。下面是我們所建立的介面的最終效果。

如你所見,我在部分標籤處放了一些佔位用的數值(比如999)。之所以這樣做,是為了方便檢視標籤實際使用時在介面上的顯示效果。玩家的得分可能會非常高(永遠不要低估或高估玩家的智商~),因此最好預留足夠的空間。
好了,現在該你自己出手了。如果你是個設計人員,相信你會喜歡下面的操作。開啟Main.storyboard,嘗試從Xcode的物件庫拖曳不同的控制元件放到檢視上。也不用那麼精確。
實際上,要新增的三種介面元素是Label,Button和Slider。
需要注意的是,在這些標籤裡面我放了一些佔位用的標籤(比如999999),這樣是為了預留足夠多的空間,以便玩家實際體驗的時候有足夠的發揮空間~
為了調整介面中UI控制元件元素的設定,我們需要用到所謂的Attributes inspector。我們可以在Xcode的右側面板中找到該檢視,也就是Inspector(檢視)檢視。

Inspector(檢視)檢視中會顯示所選中的視覺元素的各種屬性,其中Attributes inspector可以用來更改表情的背景顏色,或是按鈕上的文字大小。另外我們之前曾在Connections inspector檢視中檢查按鈕的動作方法連線。當你逐漸熟悉Interface Builder之後,可能會用到各種Inspector檢視。
提示:
1.需要注意的是,類似”i”形狀的介面元素其實也是一個Button,只是需要把它的型別設定為Info Light。

2.如何設定滑動條的數值。
選中Slider,切換到Attributes Inspector,把它的最小數值設為1,最大數值設為100,當前數值設為50.

當你完成以上操作後,介面已經有了12個使用者介面元素:1個滑動條,3個按鈕,還有一堆標籤。怎麼樣,很有成就感吧。
點選Run執行應用,然後好好玩上一會兒。除了之前的按鈕,其它控制元件現在還做不了具體的事情,不過起碼你可以拖著滑動條來回玩。

到目前為止,我們已經完成了介面的基本佈局,而且不需要寫一行程式碼。如果你是一個設計師,肯定要為此歡呼雀躍。可惜好日子到頭了,很快我們就需要使用Swift編寫程式碼讓這些控制元件變得可互動。
喬幫主到目前為止對你的工作還比較滿意,暫時沒有召喚你去天國猛批一頓的意思。
不過按照他一向的完美標準,你還有很多工作要做。

讓滑動條變得可互動
在我們to-do list上的下一個待辦專案是:當玩家觸碰按鈕時讀取滑動條上的數值。
如果你在Interface Builder的時候沒有故意搞一些麻煩,比如裝作不經意間把按鈕和showAlert動作的關聯取消,那麼此時就可以更改程式碼讓應用在彈出警告框中顯示滑動條的數值。(如果你的確取消了按鈕到動作的關聯,那麼首先需要再次將其關聯起來。)
還記得如何在檢視控制器中新增一個動作,從而讓它可以識別使用者對按鈕的觸碰嗎?對於滑動條我們可以做同樣的事情。一旦使用者拖曳滑動條的手柄,就會觸發這個動作。
要實現這一切,跟之前的操作幾乎完全相同。
首先在Xcode中點選ViewController.swift,然後在最後一個花括號前面新增下面的程式碼:
@IBAction func sliderMoved(_ slider: UISlider){ print("滑動條的當前數值是: \(slider.value)") }
再次強調:輸入程式碼的時候一定要注意全形和半形的切換,特別是程式碼中既有中文又有英文的時候,要切記程式碼一律用半形,要列印或輸出的中文(包含標點)才用全形。這個問題是新手開發者甚至是部分老手很容易犯的錯誤。
注意到此時@IBAction func sliderMoved(slider:UISlider)這行程式碼的左側有個空心圓,代表它還沒有跟storyboard中的介面元素關聯起來。
此時在Xcode中點選Main.storyboard,按住Ctrl鍵不放,點選滑鼠左鍵從檢視中的slider滑動條上拖一條線到物件面板(Outline pane)的View Controller(注意不是View Controller Scene)上,然後從彈出選單中選擇sliderMoved:。
此時如果你通過Xcode右側的面板切換到Connections inspector,就可以看到sliderMoved:動作和滑動條的Value Changed事件關聯在一起。

這就意味著每當滑動條的數值發生變化時(使用者拖動滑動條),就會呼叫sliderMoved()方法。
再次提醒大家,在Interface Builder的canvas左側,是所謂的Document Outline,其中列出了當前檢視中的所有視覺元素。

記住,如果你看不到Document Outline,可以點選Xcode視窗底部的小圖示來顯示:

現在點選Run運行遊戲,然後拖動滑動條看看反應。
一旦你開始拖動,Xcode視窗會在底部開啟一個新面板,也就是傳說中的Debug Area(除錯區),然後顯示下面的資訊:

如果你把滑動條拖到最左邊,會看到上面顯示的數值變成1.0,如果拖到最右邊,那麼顯示的數值變成100.0.
print()函式可以幫忙我們瞭解應用的邏輯是否正常。它的作用就是在Debug除錯區顯示一條文字資訊。這裡我們用它來驗證滑動條是否和指定的動作關聯在一起。在我每次要新增新的功能前,我都會用print()來確保之前一切都OK.
提醒:
你是否注意到sliderMoved:方法的名稱後面有一個冒號,而showAlert卻沒有?這是因為sliderMoved:方法有一個引數slider,而showAlert則沒有任何引數。如果某個動作方法有一個引數,那麼Interface Builder就會在名稱後面新增一個冒號。很快我們就將瞭解更多關於引數的問題。
科普時間
好了,馬上又要到科普時間了。這樣免得你太累,不過如果還是那句話,如果你對理論知識無愛,可以跳過去無視。
首先我們來科普幾個東西,所謂的iOS開發,App Store,Mac開發,Xcode,Objective-C, Swift,Cocoa, Cocoa Touch究竟是什麼關係。
在我初學蘋果開發的時候,經常把這些東西搞混,因為早期的各種程式設計書籍中既有iOS開發,又有Objective-C開發,還有Cocoa 開發。
程式猿最NB之處,同時也是最讓人討厭的地方就是,喜歡用各種術語,各種縮寫讓你覺得自己是個白痴。雖然我們的目標不是成為最NB的程式猿,但瞭解一些相關的開發術語沒有壞處。
我並不指望你一下子就看懂它們的真正用處和區別,但起碼先留下點印象,然後在後面的教程中再逐步熟悉。對於教程中的其它抽象概念,哥也是類似的做法,先簡單介紹,然後讓你反覆接觸,直到徹底進入你的盜夢空間。

iOS開發,在2010年推出iPad之前其實就是iPhone開發。所以很多早期的iOS教程都寫的是iPhone應用開發。相信大家都知道2007年macworld上幫主的那次驚天地泣鬼神的神級演講,如果沒看過的強烈建議去重溫一下,絕對是我心目中商業產品釋出演講中無可爭議的第一。
2008年前第三方只允許開發Safari上的網頁應用。2008年開始,蘋果在當時的SVP Scott Forstall的帶領下向開發者正式推出了iPhone SDK,並直接打造了一個完整的生態系統。
2010年幫主釋出了耶穌之本iPad,同年的WWDC上將iPhone OS更名為iOS。iOS基於Mac OS X系統開發,但針對移動裝置特有的硬體特性做了大量的改善和優化。
如今的iOS開發泛指針對所有安裝了iOS作業系統的裝置(當然只限蘋果生產)開發應用或遊戲。主要包括:iPhone全系列,iPod touch全系列,iPad全系列。當然,相信還在用iPod touch的童鞋已經不多了,這又是一條註定會消失在歷史中的產品線~

目前除了iOS,還有了針對Apple Watch的Watch OS,還有針對Apple TV的TV OS,不過它們都是基於iOS衍生而來的~
App Store,顧名思義就是蘋果賣針對iOS裝置上應用和遊戲的軟體商城。
Mac開發,指的是開發Mac作業系統下的應用和遊戲軟體。在iOS和App Store取得了巨大的成功後,蘋果把iOS的一些成功特性開始反哺給Mac作業系統,同時在2011年推出Mac版的 App Store。
不過目前看來Mac開發並沒有吸引足夠多的開發者。也沒有多少非常成功的案例。
Cocoa和Cocoa Touch上一次的內容中提過,同樣是程式設計環境,一個用於Mac開發,一個用於iOS開發。
Swift和Objective-C屬於程式語言,和C,C++,Java,C#,Javascript,PHP,Python,Ruby等相似。
Xcode是Mac 平臺下的軟體開發環境,可以開發Mac和iOS應用。
如果和其它開發平臺做一下對比,可能很多人就明白了。
Xcode類似於Visual Studio或者Eclipse
Swift和Objective-C類似於C,C++,Java,C#這些開發語言,
Cocoa 和Cocoa Touch 類似於微軟開發中的MFC或.NET.
Swift/Objective-C和Cocoa/Cocoa Touch的關係類似於C++和MFC,或者C#和.NET的關係。
繼續科普-什麼是字串
在剛才的print()那行程式碼裡,我們用到了這樣的一個東西,
"滑動條的當前數值是: \(slider.value)"
這就是個字串,到目前為止我們已經用了好幾個類似的東西。比如UIAlertController(提示對話方塊)裡面的就是字串。
通常來說,這樣一連串的文字被成為字串,因為我們可以把文字看做字母,數字,標點符號的一個序列,就好像用串在一起的珠子。

在我們開發應用的過程中,將會大量使用字串,所以很快你就會熟悉它的用法。
在Swift裡面,為了建立一個字串,只需要把文字放到雙引號裡面就好了。這個@符號很重要!如果你之前用其它的程式語言寫過程式碼,或許在生成字串的時候可以使用雙引號或單引號(比如python),但是Swift只能使用雙引號。
而且很重要的一點是你必須使用半形輸入,不要使用中文輸入法的全形雙引號。
總結一下:
// 在Swift 中正確使用字串的方法:
"I am a good string"
// 下面都是錯的:
'I should have double quotes'
''Two single quotes do not make a double quote’'
“My quotes are too fancy”
@"I am an Objective-C string"
在print()這行程式碼裡面,用到的字串是"滑動條的當前數值是: \(slider.value)”
所有在符號 \(…)之間的字串都是特殊的佔位符。
比如下面的這個佔位符:"滑動條的當前數值是:: X”,這裡的X將被滑動條的數值所替代。
讓變數來幫忙
在除錯面板中用print()列印資訊對於開發和測試非常有用,不過玩家對這種訊息可是毫無興趣。因此讓我們來改進一下這個動作方法,讓它在一個提示對話方塊裡面顯示滑動條的數值。那麼我們該如何把滑動條的數值送給showAlert()呢?
當我們在sliderMoved()中讀取滑動條的數值時,一旦這個動作方法結束,這個資料資訊也就丟失了。我們需要記住這個資料,直到玩家觸碰了按鈕為止。
幸運的是,Swift(其它語言也是)為我們提供了一個很好的工具-變數。
在Xcode中開啟ViewController.swift,在class ViewController這行程式碼的下面新增一行程式碼:
var currentValue: Int = 0
新增完成後的程式碼如下:
import UIKit class ViewController: UIViewController { var currentValue: Int = 0 //定義了一個變數 override func viewDidLoad() { … } override func didReceiveMemoryWarning() { … } @IBAction func showAlert(){ … } @IBAction func sliderMoved(slider: UISlider){ … } }
注意:上面唯一添加註釋的程式碼是剛剛新新增的程式碼,其它一切都保持不變。省略號…其實就是之前的程式碼內容,千萬不要以為哥把那些程式碼都刪掉了。如果你不確定的話,最簡單的方式就是參考本章的參考專案原始碼,對比下就知道了~
現在我們就添加了一個名為currentValue的變數到檢視控制器中。變數被新增到方法的上面,通常我們需要讓這行程式碼縮排顯示,使用tab鍵或者用空格鍵。
至於使用兩個空格還是4個空格取決於你的個人習慣,我們可以通過Xcode的偏好設定來設定這一點。在Xcode的頂部選單中點選 Xcode -Preferences..-Text Editing ,然後跳轉到 Indentation 選項卡即可。
還記得幫主當年的話嗎?由內到外都要美。哪怕是程式碼的縮排顯示這樣小的細節,以後也會給你節省很多時間,讓你讀程式碼沒那麼累。更重要的是,真正的美,由內到外。

很多偷懶的程式猿在這方面都過於隨意,我毫不奇怪他們的程式碼裡面經常會出現各種bug。這個無關技術,和心態有關。用心做,才能成為食神;用心演,才能成為喜劇之王~

很多事情談不上需要多高深的技巧,談不上拼爹和乾爹,談不上苦逼和潛規則,唯用心與否而已。
在之前的教程中曾提過檢視控制器,或是任何一個物件都有自己的資料和功能。
showAlert()和sliderMoved()動作就是功能的典型例子,而currentValue變數則是資料的一部分。
通過使用變數,可以讓我們的應用擁有記憶。你可以把變數看做是儲存某個資料的臨時儲物箱。正如儲物箱有各種型別和尺寸的一樣,資料也五花八門。
你不能把東西扔到儲物箱裡面然後撒手不管,因為經常會放入一些新的東西。當你的應用需要記住一些變化時,就需要把舊的資料拿出來,然後把新的資料放進去。
這就是變數( variable )的本質-變( vary )。比如說,每次玩家拖動滑動條的時候,我們都會使用滑動條的當前位置來更新currentValue。

儲物箱的大小和變數可以儲存的數值種類由datatype(資料型別)決定。這裡我們指定currentValue這個變數的資料型別為Int(也就是 integer ),意味著儲物箱裡面可以放入整數(又稱為 integer ),範圍在正負20億之間。Int是最經常用到的資料型別,不過很快我們會接觸到其它的型別。
變數就象小孩的玩具積木一樣:

我們需要把正確的形狀放到正確的儲物箱裡面。儲物箱就是變數,而它的資料型別(datatype)決定了裡面能放什麼形狀的東西。形狀就是你可以放入變數的可能數值。
我們可以隨後更改每個箱子裡面的內容,可以拿出藍色的方塊積木,放進紅色的方塊積木,但前提是它們都是方塊形狀的。你不能把方塊積木放到一個圓孔裡面去:數值的資料型別和變數的資料型別必須是匹配的。
剛才也說了,變數是一個臨時的儲物箱。既然是臨時,那麼能儲存多久呢?每個變數都有自己的生命週期(或者叫scope,術語狗滾粗),它的生命長短取決於你在程式的哪個位置定義變數。在這裡,currentValue的宣告和它的擁有者一樣長,它的擁有者是ViewController。它們的命運交織在一起。在這裡,只要我們不退出應用,這個檢視控制器,還有currentValue就會活著。當然,很快我們就會了解到壽命很短的變數。
在程式這樣一個虛擬世界中,每個變數,每個檢視控制器都是一個虛擬的生命。世界毀了,所有的生命都會消亡。世界沒有毀,有的生命也會消亡。這方面似乎可以和人類與宇宙的關係類比。
八卦時間:
剛才在談到變數的時候,舉了個例子,說是’不能把方塊積木放到一個圓孔裡面去’,英文原文是,you can’t put a square in a round hole
這讓我想到了蘋果著名的品牌廣告Think Different的臺詞,人跟變數終究還是不同的。
變數不能做到隨心所欲不逾矩,而人需要與眾不同。

Think Different
Here's to the crazy ones.獻給狂放不羈的一群人
The misfits. 他們是:不和主流的怪才
The rebels. 叛逆傳統的勇士
The troublemakers. 製造麻煩的一小撮
The round pegs in the square holes. 方鑿圓枘、特立獨行
The ones who see things differently. 他們觀察問題與眾不同
They are not fond of rules. 他們不喜歡條條框框
And they have no respect for the status quo. 更不把正統放在眼裡
You can quote them, 你可以引用他們,
disagree with them, 也可以否決他們,
glorify or vilify them. 讚揚或是詆譭他們
About the only thing you can't do, 但只有一件事你不能做
is ignore them. 那就是漠視他們
Because they change things. 因為他們改變了事物
They push the human race forward. 他們推動了人類的程序
And while some see them as the crazy ones, 雖然有些人把他們當作瘋子
We see genius. 但我們看見的卻是天才
Because the people who are crazy enough to think 因為只有那些足夠瘋狂認為
they can change the world, 可以改變世界的人
Are the ones who do. 才能真正做到這一點
本人聯絡方式:
微信:iseedo
郵件: ofollow,noindex" target="_blank">[email protected]
QQ討論群: 375143733
如有疑問,請先發送郵件到我的郵箱: [email protected]
我會在收到郵件後儘早答覆。
也可以加微信,但可能不是很合適的答疑途徑。
另外,為了節省大家的寶貴時間,提高溝通效率,請在提問的時候儘量附上 專案原始碼以及以下資訊 :
1.開發環境(系統版本,Xcode和iOS版本)
2.問題描述及重現(想實現什麼效果,結果是怎樣的,具體涉及到什麼操作)
3.為解決問題所做的努力(做了哪些嘗試,分別是怎樣的結果)