##モチベーション
勉強したいからです!!
StanfordのDeveloping iOS Apps with Swiftを参考にしました
##SwiftによるiPhoneアプリ開発について
- オブジェクト指向開発です!!
- MVCデザインパターンを採用しています
- データベース、グラフィック、マルチメディア、マルチスレッド、アニメーション、ネットワーク、などをサポート!!
- アプリストアでプロダクトを売ることができます!!
オブジェクト指向開発なので、オブジェクト指向の知識が必要です。
オブジェクト指向が理解できないと、何やっているかわかりません。
Swiftは高水準言語なので、その下に幾つかの階層があります。
最下層にCore OSのレイヤーがあります。
FreeBSDをベースにして作られているようですね。Socketなどもあるようです。
その上にCore Serviceのレイヤーなどもあるようですね。ここにはSQLiteやNetworkingなどもあります。
Mediaレイヤーなどもありますね。
最上位層にCocoa Touchレイヤーがあります。
まあ、ここら辺はSwiftプログラミングにはあまり関係がないので、Stanfordのコンテンツでもさらっと流してますね。
使うツールはXcode6、XCodeではないですよ。cは小文字です。
使われるフレームワークは
- Foundation
- Core Data
- UIKit
- Core Motion
- Map Kit
ですね。
個人的にはCore Dataの使い方を覚えたいところですが、Stanfordのコンテンツでは出てこないみたいですね。Udemyなどのタダのコンテンツであったと思うので、それを使いたいと思います。
では、プログラミングを始めていきたいと思います。
Xcodeを立ち上げて
メニュー→File→New→Projectで、Xcodeが立ち上がりますね。
iOS→Application→Single View Applicationを選択します。
Product Name:
Organization Name:
Organization Identifier:
Bundle Identifier:
Language:
Devices:
User Core Data
など設定するところがあります。
Product Name:は読んで字の通りプロダクトの名前、デフォルトではこの名前がアイコンに表示されるので注意してください。
Language はSwiftとObjective-Cが選択できるようになってますね。今回はSwiftを選択しました。
Deviceは、iPhone、iPad、Universalが選べるようです。
今回はUniversalを選択しました。
書いていて思うのが、技術本ってのは読んでいても仕方ないもので、自分で技術本を書くことこそ勉強になるのだと思います。
さすがに出版は大変だし、それだったら無料で公開したほうがいいと思いますね。
ただ、ソフト構築するときに記事を拾い読んでいって、ソフト構築のヒントにするという使い方がこの記事の正しい使い方だと思うのです。
だから、読んでいる皆さんも、技術ブログ書きましょう。技術力上がりますよ。
次にフォルダを選択します。適当なフォルダを選んで保存しましょう。
こうしてナビゲーションエリアに出てくるのが、
ViewController.swift
ですね。
Objective-Cでは、ファイルは.hファイルと.mファイルに分かれていて、.hはパブリック、.mはプライベートな部分になるのですが、Swiftでは一つのファイルにまとまるんですね。
さて、この
ViewController.swift
ですが、明らかにこれはあまり良くないファイル名です。
この場合のいいファイル名とは
FooViewController.swift
BarViewController.swift
CaliculatorViewController.swift
のように、先頭にちゃんとなんのファイルか記述されているものですね。
ViewController.swift
だけでは、UIViewControllerを継承した以上の意味は持ち得ないですよね。
これは、後で書き換えます。
Stanfordのコンテンツでは、この後Labelの貼り方などの説明をしていますが、ここら辺はまあ、本やテキストで勉強することではないですね。図と言葉で説明してもさっぱりわからないと思うので、これは元の動画をみてください。英語理解できなくてもわかるし、技術者なら英語ぐらいやりましょう。
iPhone開発においてはスタティックなUIによってUIを設計することができるようです。まあ、だからと言って、アプリ開発においてコード記述が不必要になるわけではありません。
ここで気になるのが、StoryBoardのUIが正方形なことです。正方形なiOSデバイスなんて現時点では存在しないですよね?
これは、Constraintsを使って、実行するときに画面を縮小させて、一つのUIで複数のデバイス、角度に対応するようにしています。
具体的には、右クリックで調整する対象のUIから別のUIにラインを引っ張って行って、整合性が取られているなら青い線になり、矛盾していたら黄色い線になるようです。
では、一つ一つ説明してくことにします。
まず、View ControllerにUILabelを張りましょう。全体のサイズをView Controllerの左端少し残したところから右端少し残したところにしましょう
フォントサイズを29にしましょう。書いてある内容を'0'にして、ALignmentを左詰めにしましょう。
実行してみます
みごとに真っ白ですね〜
では、何が問題だったのか。それは、「Constraints」を設定していなかったから、0がはみ出してしまったんですね。
UILabelからControlキーを押しながらドラッグして、View Controllerの右端でドロップし、Trailing Space to Container Marginを選択してください。
これはまあ、UILabelの右端とView Controllerの右端との間隔を一定にするものですね。
Standordの解説では、This lets me pin the trailing space after my label to the margin of the containerと言ってますね。
つまり、この後続のスペースを、Labelとcontainer(ここではUIViewController)とで固定する(pin)ということですね。
でも、黄色の項目が出てしまいます。つまり、あなたは位置を決めるのに十分な情報を与えていないということですね。
同じように左側もやっていきましょう。
上側もやっていきます。
まだオレンジが残ってますね〜
ここクリックしてください
ここクリック
今回はUpdate Frameで解決しますね。それは、Labelのサイズが正しくなかったということですから、LabelのサイズをConstraintsの設定に合わせてやる。つまり、Update Frameをかけることで解決します。
これがAuto Layoutの機能ですね。
これで正常に実行できるはずです。
回転とかさせてみてください。
では、ここを選択してみてください
アシスタントエディタが開くはずです。ここら辺の詳しい使い方はStanfordの元のビデオ見てもらったほうがわかりやすいかもしれません。
ViewController.swiftを開くと以下のようなコードになっていますね
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
一応一つ一つ説明していくと、ViewControllerはUIViewControllerを継承しています。
import UIKitは、iPhoneのUIの部分をインポートします。
viewDidLoadは、ビューが、つまり、View Controllerがロードされた後、表示されるときに呼び出されるものです。
didReceiveMemoryWarning() 関数は、メモリが少なくなったときに呼び出されるものです。僕は使ったことないです。
overrideは、基底クラスからオーバーライドされたものであるのでこういうキーワードがつきます。
この二つの関数はいらないので、削除して以下のようにしてください
import UIKit
class ViewController: UIViewController {
}
で、Outletコネクションでつないでください
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var display: UILabel!
}
これベタ書きしてもダメですよ。Labelからコードへドラッグして行って、接続する必要があります。
ここで、「weak」というキーワードが出てきてます。これは、ViewControllerから「弱い参照」しかしてないということです。これは、Automatic Reference Countingによるガベージコレクションの一種で、まあ、UI絡みのものはStoryBoardから強い参照を受けているので、一般的にコードからは弱い参照です。
一般的にそうだというだけで、コードから強い参照を受けることもあり得ます。
オブジェクトは、必ず現在存在しているオブジェクトの少なくとも一つから「強い参照」を受けないとガベージコレクトされてしまいます。
「弱い参照」「強い参照」については、Objective-Cから引き継いでいるようですね。
ちなみに、Swiftでは、すべてのオブジェクトはヒープ領域にあります。そして、オブジェクトをさすのはポインタ、つまり、
@IBOutlet weak var display: UILabel!
これはポインタということになりますね。
次に、ボタンを置いてサイズを24にします。
次にアクション接続してください。
設定は、anyObjectではなくUIButton、Outlet接続ではなくAction接続、その他の設定は同じです。
@IBAction func appendDigit(sender: UIButton) {
}
さて、このアクション接続したUIButtonですが、アクション接続はコピーしたUIButtonにも有効です。
以下のような配置になりました
コードを書いていきましょう
@IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle
println("digit = \(digit)")
}
コードを書いて実行すると、コンソールに以下のようなものが出てきますね
digit = Optional("8")
digit = Optional("5")
digit = Optional("2")
digit = Optional("3")
ここで、Optionalという言葉が出てきますね。Optionalとはなんでしょうか?
http://qiita.com/cotrpepe/items/518c4476ca957a42f5f1
このサイトでは、nilの代入を許す型だと書いてあります。
nilの代入とはなんでしょうか。
例えば、ボタンのタイトルが何も書かれていなかった場合、nilになりますね。出力は以下のようになります。
digit = nil
digit = nil
では、digitの型はなんでしょうか。digitの型は、Optionalを押したままdigitをクリックすればわかるのですが、String?型、つまり、Optionalです。nilになることが可能な型です。
では、Optionalではない型にするにはどうすればいいでしょうか。それは、currentTitleの後に!をつけることです。
@IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
println("digit = \(digit)")
}
これでOptionalでない型にすることができました
digit = 9
digit = 8
digit = 6
では、タイトルのないボタンをクリックするとどうなるか。以下のようになります
fatal error: unexpectedly found nil while unwrapping an Optional value
エラーが出ますね。プログラムがクラッシュします。
つまり、これは、プログラムをクラッシュさせることによって、プログラムにバグがあることを明示することになります。
これ以前はプログラムが正しくセットされていないとnilのまま漂ってたんですね。これはやばいです。
@IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
display.text = display.text! + digit
println("digit = \(digit)")
}
display.text!もOptionalだから、アンラップする必要があります。
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var display: UILabel!
var userIsInTheMiddleOfTypingANumber: Bool= true
@IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
display.text = display.text! + digit
println("digit = \(digit)")
}
}
さて、
var userIsInTheMiddleOfTypingANumber: Bool= true
の=trueを記述しないとエラーが出ます。初期化する必要があるんですね。
ちなみに僕は今仕事がないです。お仕事頼みたいときは、ご連絡ください。