みなさんiOSアプリ開発わくわくしていますかー??
iOSアプリを作っていくうえでは、Swiftは避けて通れないものです。
※Objective-Cもあるけど、理由がない限りわざわざお勉強する必要はないと思っています。
Swiftを一つずつ紹介している記事が見当たらなかったので、Swiftのお作法をこちらの記事でご紹介していきます。
対象読者
- 他のプログラミング言語に多少触れたことがある方
- Swift言語に触れたことがない方
- モバイルアプリ開発が初めての方
- これからスマホアプリを開発していきたい方
- iOS案件のプロジェクトに携わる予定の方
注意
- ご紹介する内容は、こちらの書籍を参考にしております。
記載内容には十分に配慮しておりますが、万が一抵触する部分がありましたらお申し付けください。 - Playgroundsで動作済みのソースコードを記載しています。
- バージョン5.3.2での動作を確認しています。
- Swiftを実行するには、Xcodeが必須です。
AppStoreでダウンロードできますので事前に行なっておいてください。
※この記事ではダウンロード&インストール、設定等は触れません。
Swiftリファレンス
Appleが公式にSwiftに関するリファレンスを公開しています。一度は目を通しておくといいと思います。私には理解できませんでしたが...
Swiftコミュニティーが分かりやすくまとめたサイトがありますので、こちらもオススメです。日本語への翻訳をすると、ちょっとした参考書レベルの内容が得られます。
(こっちを見たほうがいいじゃんとか言わないの。)
定数と変数
変数を定義する場合は、var
を使用する。
定数を定義する場合には、let
を使用する。
※定数は定義時の値から値を変更できない
var str_var = "Hello"
let str_let = "world"
str_let = "World" // エラー発生
print(str_var) // Hello
print(str_let) // world
演算
他にも様々な演算子がありますが、ここでは割愛します。
気になる方は調べてみてください。
var x = 5
var y = 3
print(x + y) //加算
print(x - y) //減算
print(x * y) //乗算
print(x / y) //除算
print(x % y) //剰余
print(x > y) //より上
print(x <= y) //以下
型の定義
Swiftは型を指定せずに変数・定数を定義可能です。(型推論を行うため)
少ない記述でプログラミングが行うことが可能です。
var age_1:Int = 20 //型宣言と初期値を記述
var age_2 = 32 //初期値から型を推論
age_2 = 19 //varで宣言した変数の変更
定数も同様です。
let name_1:String = "HCS" //後で値を変更するとエラーになる
let name_2 = "hcs" //初期値から型を推論
型変換
Double型以外の型からDouble型への変換にはDouble()
を使用する。
Int型以外の型からInt型への変換にはInt()
で可能。
同様に、String()
,Float()
が存在する。
※型変換できない場合は、nilが代入される。(後術)
let i:Int = 5
var a:Double = Double(i) //iの値をDouble型に変換
var j:Int = Int(a * 1.25) //jの値は6.25
let f = Float(-9.120)
let y = Int(f) //yの値は-9となり、小数点以下は切り捨てられる
var t:Double = 4 //実数のインスタンスが作られて代入される
var s = t * 10 //実数の変数tと演算をする実数インスタンスが作られる
文字列
文字列を結合するには、+演算子、+=演算子や.append関数も利用できる。
また、文字列の中に変数を埋め込みたい場合や、特殊文字を表示する場合には、バックスラッシュを使用することで実現可能。
let name = "情報太郎"
let msg = "こんにちは、" + name + "さん。" //こんにちは、情報太郎さん。
var homework = "情報"
homework += "「データ構造とアルゴリズム」" //homework = "情報「データ構造とアルゴリズム」"
homework.append("-->")
文字列中の特殊文字を表すにはバックスラッシュを使用することで実現できます。
let msg = "command=\u{2318}, option=\u{2325}" // "command=⌘, option=⌥"
文字列の中に変数や定数を埋め込むことができます。
埋め込むには、\(変数)
を利用することで実現できます。
let n = 8
let str = "\(n)の2乗は\(n * n)です。"
配列
他のプログラミング言語同様に配列が存在します。
配列に格納できる値の個数に制限はありません。
定義の仕方が幅広いので注意してください。
var a : [Int] = [2,2,2,2,2] //型宣言と初期値を記述
var a = [2,5,3,7,5] //初期値から型を推論
var a : Array<Int> = [1,3] //本来の定義の仕方
var s = [String]() //イニシャライザの呼び出し
var s:[String] = [] //型を指定した変数に空配列を代入
計算式も代入可能です。
var g = 1.2
var f = [g/2.0, g/0.3, g/0.04]
print(f) //[0.6, 4.0, 30.0]
配列にアクセスするには以下のように[]
を利用します。
添字はゼロオリジンなので注意してください。
let digits = ["00","01","02","03"]
print(digits[2]) //02を出力
print(digits.count) //配列の個数を表す
配列に要素を追加するには、.append()
を利用します。
また+演算子や+=演算子も利用できます。
//.append関数を利用
var array = ["①","②","③"]
array.append("④")
print(array)
//+と+=演算子を利用
let m = array + ["5","6"]
print(m)
array += ["Ⅴ","Ⅵ"]
print(array)
インクリメントとデクリメント
Swiftでは++
や--
とは記述できない
var a = 0
a += 1 //a_4のインクリメント
a -= 1 //a_4のデクリメント
Unicode
Unicodeを変数名として使用可能です。(実際は使わないけど)
let 用紙の幅 = 50.0
var 左の余白割合 = 0.10
var 右の余白割合 = 0.08
var 本文横幅 = 用紙の幅 * (1.0 - 左の余白割合 - 右の余白割合)
ジェネリクス(型パラメータ)
型をパラメータとしてプログラムに記述するための機能があります。
他のプログラミング言語と同様ですね。
//指定したジェネリクス型でn分のオプショナル配列を返す関数
func getNilArary<T>(n:Int) -> [T?] {
return [T?]( repeating:nil, count:n )
}
let hoge:[Int?] = f(n:10)
配列も通常は省略しているが、型パラメータを使用している。
var a:[Int] //通常はこちらの記法
var a:Array<Int> //このようにも書ける(本来の記法)
モジュールのインポート
モジュール(ライブラリ)をインポートすることで様々なクラスやメソッドを利用できる。
インポートするにはimport
句を使用する。
import UIKit //UIKitフレームワークのインポート
import PlaygroundSupport //playgroundで使用するためのフレームワーク
// UIKitモジュールを使用することでGUI部品を利用できる。
let color = UIColor.green //緑色を取得
let image = UIImage(named: "sample.png") //ローカルの画像を取得
let imageView = UIImageView(image: image) //画像をビュー(画面に表示するためのレイヤー)クラスに変換
if
他のプログラミング言語同様に制御構文が存在します。
else句は任意なので省略可能です。
条件式に()
は不要なので注意。
if x > y {
print("x>yは真です。")
} else {
print("x>yは偽です?")
}
while
繰り返し制御が可能です。
ループから抜けるためのbreak文や次の繰り返しを開始するためのcontinueが使用可能です。
while x < y {
//繰り返したい処理
}
repeat-while
while文は評価した後で繰り返し処理を行いますが、repeat-while文は最低一度は繰り返し処理を実行するという違いがあります。
Javaのdo-while文と同じです。
repeat {
//繰り返したい処理
} while x < y
for-in
繰り返しの回数が決まっている場合に、for-in文を使用することが可能となっています。
範囲や集合を表す式から1つずつ取り出し、繰り返しの処理を行います。
forの後ろに定義された定数は暗黙的に、letが記述されていることになり、値を変更できないので注意してください。
この定数はfor-in文の中でのみ有効であるため、スコープ外からは参照できないので注意。
・範囲型については以下をご覧ください。
for i in 1..<3 { } i(定数)の値は1,2となり、{}の中を2回実行
for k in 1...3 { } k(定数)の値は1,2,3となって、{}の中を3回実行
//九九の表を作成するプログラム
for i in 1 ..< 10 {
var l = ""
for j in 1 ..< 10 {
let r = i * j
if r < 10 { l += "\t" }
l += "\(r)"
}
print(l)
}
where
句を利用することで、くり返しに条件を付与することが可能。
//for-in文で4と7の倍数を表示しないプログラム
for i in 1..<64 where q % 4 != 0 && q % 7 != 0 {
print(i,terminator: " ")
}
配列の中を取り出し、逐次繰り返すことも可能
//配列から一致する文字列を探すプログラム
let name = "taro"
let group = ["kojiro","itiro","jiro","taro","musashi"]
for s in group {
if name == s {
print("\(s)が見つかりました")
//繰り返しをやめる
break
}
}
switch
他言語と大きく違う点は以下です。
- 分岐先の文の実行が終了しても、breakを記述する必要はない
- default句は必ず書かなければならない
- 分岐に使用する値の型に、文字列や構造体やクラスを使用することが可能
var num = 0
switch num {
case 0:
print("what") //breakがなくてもよい
case 1,2:
print("ohh") //複数を記述する場合はこのように記述
case 3,4:
print("me")
case 6:
break //breakを記述してもよい
default:
print("you") //最後にdefaultを書く
}
関数
他言語と大きく違いはありませんが、関数定義が独特であるため注意が必要です。
//単純な関数count()とreset()
var total = 0
func count(i:Int) -> Int { //整数の引数を1つとり、整数を返す
total += i
return total
}
func reset() { //引数も戻り値もなし
total = 0
}
reset() //グローバル変数の初期化
count(i: 5) //呼び出し時には、
print("\(count(i: 10))")
func getMessage() -> String {
return "現在の値は\(total)です。"
}
//こうも書ける(関数単体がreturnだけの場合は、return句も省略可能)
func getMessage() -> String { "現在の値は\(total)です。" }
引数ラベル
関数の引数は適切でわかりやすいものにしておくことが好ましいとされています。
他言語は関数呼び出しを行う際に変数や式を並べるのみでプログラムを読んでも引数の意味が分かりにくいです。
たとえば、カタログ番号29090の商品を15万円で1個購入するという呼び出しを、一般的には以下のように記述します。
buy(29090, 150000, 1)
Swiftでは引数にキーワードを明示して関数を呼び出すという方法が使われます。
そうすることで、関数定義を見ずともプログラムが書くことができ、効率化!というわけです。
//引数ラベルを持つ関数定義の例
func buy(product:Int, price:Int, quantity:Int) {
print("Product:\(product), amount = \(price * quantity)")
}
buy(product: 29090, price: 150000, quantity: 1)
//長方形の縦と横の長さで面積を計算するプログラム①
func getArea(h:Double, w:Double) -> Double {
return h * w
}
//引数ラベル(h:やw:)が表示されることで、呼び出しの際に引数間違いを防ぐことができる
let result = getArea(h: 5.0, w: 12.5)
//長方形の縦と横の長さで面積を計算するプログラム②
func getArea(height h:Double, width w:Double) -> Double {
return h * w
}
//引数ラベルを明示的に書き足したパターン(height,widthが引数ラベル、h,wが仮引数となる)
let result = getArea(height: 5.0, width: 12.5)
結果を無視する_(アンダースコア)
戻り値を利用しない場合や変数、定数として扱う必要がない場合に利用する。
_
は結果を無視するという意味になる。
//下線の特殊な記法(関数の結果を無視する)
_ = area_a(h: 10.5, w: 12.5)
_ = area_b(height: 10.5, width: 13)
//仮引数の省略(_を記述することで仮引数を省略可能)
func compare(_ a:Int, _ b:Int, _:Bool) {
// 比較の処理
}
compare(1, 2, false)
//添字を使用しないのあれば以下のように記述可能
for _ in 1...10 {
// くり返しの処理
}
inout引数
関数の実引数はコピーされて関数に渡される。関数内での処理によって呼び出し側の変数の値を変えたい時は、inout引数を使用することで実現できる。
//値渡しと参照渡し(inout)
func swap(_ x:inout Int,_ y:inout Int) {
let tmp = x
x = y
y = tmp
}
var swapX = 100
var swapY = 0
swap(&swapX, &swapY)
print("swapX",swapX,"swapY",swapY)
オーバロード
引数の型や数、戻り値の型が異なることで、同じ関数名を定義可能となる。
func overLoad(a:String) {
print(a)
}
func overLoad(a:String) -> String {
return a
}
func overLoad(a:Int) -> String {
return String(a)
}
タプル
タプルとは、複数個のデータを組みにしてまとめたものことを指す。
関連し合う複数の値をまとめて扱いたいが、構造体やクラスを定義するほどではない場合に重宝する。
プログラムの中でデータを渡したり、一時的に保管したりするような用途で扱うべきであり、タプルを元にして複雑なデータ構造を作るべきではないとされている。
タプル型は値型のデータであるため、代入にたびに新しいインスタンスが生成される。
let m = ("dog.jpg",161_022) //ファイル名とバイト数
let cat: (String,Int,Int) = ("cat.jpg",1024,764) //型宣言をした場合
var img : (String,Int,Int) = cat //互いの要素の個数と型が同じであれば代入可能
//「.0」のような記法を使うことでタプルにアクセス可能。数字に変数を指定することはできないので注意。
print(img.0,img.1,img.2)
//BIMを計算するプログラム
func BMI(tall:Double, weight:Double) -> (Double,Double) {
let v = 22.0 //理想的な値
let t = tall * tall / 10000.0 //cm を m に変換
let index = weight / t //BMIを計算
return (index, v * t) //目標体重も計算して返す
}
let result = BMI(tall: 170, weight: 55) //戻り値はタプル型
print(result)
オプショナル型
Swiftでは扱う値が存在しない場合は、nil
という特殊な値を用意している。
例えば整数の場合、変数や式の型はInt型だが、nilを値として持つことがある場合はInt?という型で扱う。
nilを通常の値と誤って使用してしまうことを防止する目的で導入された。(ぬるぽ防止)
var a : Int = 0 // 整数のみ代入可能
var b : Int? = 10 // 整数+nilのみ代入可能
b = nil // 代入可能
let olympic = "2020"
var year : Int? = Int(olympic) // 2020が返される
var city : Int? = Int("Tokyo") // 整数として評価できないため、nilが返る
//以下でも同じことになる
var year_alt : Optional<Int> = Int(olympic) //2020が返される
オプショナル型のアンラップ
オプショナルInt型(Int?)の値は整数かnilであるが、値がInt型ではないため、そのままInt型の変数に値を代入できない。
Int?型からInt型の値を取り出すように、オプショナル型からデータを取り出すことをアンラップという。
アンラップのためには、オプショナル型に対して「!」という記号を使用する
let olympicYear1 : Int? = Int("2020")
let next1 : Int = olympicYear1! + 4 //アンラップが必要
//オプショナル型の変数の値がnilだった場合は、実行時にエラーとなる。
let olympicYear2 : Int? = Int("令和2年") //olympicYear2の値は、nil
//let next2 : Int = olympicYear2! + 4 //実行時エラーとなる
nilチェック
オプショナル型の変数、または定数は、比較の演算子「==」または「!=」を使って、格納されている値を調べることが可能。
この時、アンラップする必要がないため実行時エラーにはならない。
また、オプショナル型の値がnilでない場合に役立つ、オプショナルバインディングという記法が用意されている。
//比較演算子を利用したやり方
var nagano : Int? = Int("1995")
if nagano != nil { //naganoがnilでない場合
print("長野オリンピックは\(nagano!)年に開催されました") //ここでアンラップする
} else {
print("エラー") //naganoがnilだった場合
}
//オプショナルバインディングを利用したやり方
let tokyo : Int? = Int("2020")
if let t = tokyo { //この書き方がオプショナルバインディング!(varでもOK!)
print("東京オリンピックは\(t)年に開催されるはずでした") //tはInt型。アンラップは不要!
} else {
print("エラー") //tokyoがnilだった場合
}
//オプショナル型を引数とする関数
func nickname(_ name:String?, age:Int) -> String {
if let nick = name {
return "浪速の" + nick + "\(age)歳"
}
return "浪速の名無し\(age)歳"
}
print(nickname(nil, age: 33))
print(nickname("情報太郎", age:21))
あとがき
細かく記載できていなくてすみません。(タイトル詐欺だろって思わないで!)
時間があれば更新するかもしれませんので、それまではしばしお待ちください。