【Swift】基本構文を復習!タプルや変数の使い方、型の注意点

この記事からわかること

  • Swift基本構文
  • タプルとは?
  • 変数使い方
  • 厳格な値の型を扱う上での注意点
  • タプルと配列の違い
  • オプショナル型とは?

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

Swiftを学び出した私ですが、他のプログラミング言語と構文や変数の使い方が混じらないように整理しながらまとめていきたいと思います。

Swift:公式リファレンス

Swift:日本語リファレンス

Swiftの変数の宣言方法

変数の初期値を宣言する

var user = "ame"

変数の型のみ宣言する

var user:String

変数の型と初期値を宣言する

var user:String = "ame"

Swiftでは宣言された型とは異なる型の値を入れようとするとエラーになります。

var user:String = "ame"
user = 2
error: cannot assign value of type 'Int' to type 'String'

また型宣言をしていない変数は初期値に格納された値の型が自動的に宣言されます。これを型推論と呼びます。

var user = "ame"  // この時点で String型になる
user = 2
error: cannot assign value of type 'Int' to type 'String'

型変換(キャスト)

変数から値を取り出すときにデフォルトの型とは別の型に変換する(キャスト)こともできます。キャストするには型名(変数)の形式で記述します。

var num:Int
num = 20
var str = String(num) // "20"

数値型から文字列型への変換は容易に行えますが、文字列から数値へ変換する場合は注意が必要です。数値に変換できない文字列を渡されてしまうとエラーや予期せぬ挙動を起こす原因になってしまうのでその時は関数の中に使えるguard 〜 else構文が役に立ちます。

var str:String
str = "3"  // "swift"などが渡される可能性もある場合

func numCheck () -> Bool{
    guard Int(str) != nil else {
        // 文字列の場合
        return false
    }
    // 数値の場合
    return true
}

if(numCheck()){
    print("数値だよ")
}else{
    print("文字列だよ")
}

Int(str)で型変換に成功した時のみ数値に変換された処理を実行できるようになります。この構文はオプショナルバインディング(後述のOptional型をアンラップする)の方法の1つです。

Swiftの変数の型の種類

データ型

型名 概要
String 文字列型 "swift"
Character 文字型(1文字) "s"
Int 整数型※ 23
Double 浮動小数点数型 5.3
Bool 真偽型 true

Character型は1文字1文字に対する型であり、String型はCharacter型の集合です。

※Int(整数型)に関しては「データ長」と「符号の有無」によってさらに型名が分かれています

符号有り 符号無し データ長
Int UInt 環境によって変化(32ビット〜64ビット)
Int8 UInt8 8ビット
Int16 UInt16 16ビット
Int32 UInt32 32ビット
Int64 UInt64 64ビット

データ長を指定すると格納できる数値の大きさに制限がかかり、超えてしまうとオーバーフローが発生しパースエラーになります。符号無し(U付き)UInt○であれば「2の○乗」の値がMAX値になります。(例:UInt8 = 2の8乗 = MAX:256)

var score:Int8 = 127 // OK
var score:Int8 = 128 
error: integer literal '128' overflows when stored into 'Int8'

コレクション型

型名 概要
Array 配列型 ["ame","kasa"]
Dictionary 辞書型 ["name":"ame","age":2]
Set Set型 ["ame","kasa"]

配列や辞書型(連想配列)などはコレクション型と呼ばれます。Set型は記述方法は配列と同じですが、順序がなく重複のないデータを扱うための型です。なので重複のある配列をSet型で定義すると重複値は自動で削除されてしまいます。

var student:Set = ["ame","ame","kasa"]
print(student) //  ["ame","kasa"]

computedプロパティ

computedプロパティ(コンピューテッドプロパティ)とは計算された値を返す変数です。宣言方法は特に変わりませんがreturnを使って値を返す書式になります。クロージャ内に記述するステートメント(コード)が1行の場合はreturn自体を省略することも可能です。

var num:Int {
  return 5
}
print(num) // 5

computedプロパティは中に式や処理埋め込むことが可能です。その計算結果や処理結果をreturnで返します。

var num:Int {
  let result = 2 + 5
  return result
}

上記の構文は省略された形で省略していない形で表すと下記のようになります。computedプロパティの正しい構文はget{}と後述するset{}が用意されています。get{}の中でreturnした値が変数を参照した時に取得できる値になります。get{}のみを記述した場合は読み取り専用の変数になりget{}を省略することができます。

var num:Int {
  get {
    let result = 2 + 5
    return result
  }
}

set{}を使って、値を渡して任意の計算を施した結果を返すことも可能です。例えば下記はsaleを参照すると50円割引された値を返し、saleに値を格納すると割引されていない値を返します。

var price = 200

var sale:Int {
  get {
    price - 50  
  }

  set (num) {
    price = num + 50
  }

}
print(price) // 200 割引前
print(sale)  // 150 割引後 get{}が実行
sale = 500   // 割引後     set{}が実行
print(price) // 550 割引前
// priceと saleは常に割引の差がある状態の値が格納

定数を宣言する

定数とは宣言後値を変えられない値のことです。変数はvarでしたが、定数はletを使って宣言します。

let user = "ame"

宣言後に値を書き換えようとするとパースエラーになります。

let user = "ame"
user = "kasa"  // 書き換えを試みる
error: cannot assign to value: 'user' is a 'let' constant

変数同士や変数と文字を結合する

変数同士の結合(String)

var greeting = "Hello"
var user = "ame"
let result = greeting + user // "Helloame"

変数と文字列の結合(String)

var greeting = "Hello"
let result = greeting + "太郎" // "Hello太郎"

変数(Int)と文字列の結合

数値と文字列を結合させる場合はそのまま結合するとパースエラーになってしまいます。

var score:Int = 80
let result = "点数は" + score + "です"
error: cannot convert value of type 'Int' to expected argument type 'String'

その場合はInt型をString型に型変換(キャスト)して結合します。その場合はString(値)で変換可能です。

var score:Int = 80
let result = "点数は" + String(score) + "です"

変数を文字列に埋め込む

変数の結合を意識せずとも\(変数名)を使えば文字列の中に埋め込むこともできます。この場合は変数の型を意識することなく結合することが可能です。

var user = "ame"
let result = "こんにちは\(user)さん"

改行を含んだ文字列を格納する

"""〜"""で文字列を囲むとその中に改行を含んだ見た目通りの文字列を格納することができます。"〜"でも\n(改行コード)を使えば改行を含んだ文字列を作成することができます。

var str = """
こんにちは。
これは改行を含んだ
文字列です。
"""
var str = "こんにちは\nこれは改行を含んだ\n文字列です"

タプルとは?使い方や注意点

Swiftにはタプル(tuple)という配列のような複数値を保持できる変数が存在します。(〜)を使ってタプルは格納します。

var user = ("ame",25,"Swift")

型宣言とエラー

var user:(String,Int,String) = ("ame",25,"Swift")

また型宣言をしていない場合は型推論で型が決定します。型の違う値を入れようとしたり、タプルの個数に合わない値を入れようとするとパースエラーになります。

var user = ("ame",25,"Swift")
// 型違いを格納
user = ("ame",25,175) //error:cannot assign value of type '(String, Int, Int)' to type '(String, Int, String)'
// 個数の合わないタプルを格納
user = ("kasa",18)    //error:cannot assign value of type '(String, Int)' to type '(String, Int, String)'

タプルの要素を取得する

タプルの中の要素を取得するには要素番号(0から始まるインデックス)を使って個別に取得することができます。

var user = ("ame",25,"Swift")
print(user.0) // ame
print(user.1) // 25

タプルの要素にラベルをつけて取得する

タプル宣言時に要素のラベルをつけることで変数.ラベル名でアクセスすることができるようになります。

var user = (name:"ame",age:25,language:"Swift")
print(user.name) // ame
print(user.language) // Swift
// 要素ごとに値を変更することも可能
user.name = "kasa"
print(user.name) // kasa

タプルから値を取り出す(アンパック)

タプルの中から値を取り出すことをアンパック(展開)と言います。アンパックするには一度タプルを受ける変数を用意します。受け取りたくない値は_を使って個数調整を行うことで個数違いによるエラーを防ぐことができます。

var user = ("ame",25,"Swift")
var (name,age,_) = user
let result = "名前は" + name + "歳は" + String(age) + "です。"

Swiftの配列

タプルと少し似ていますがSwiftでは配列も扱うことができます。型宣言をしない場合は型推論で型が決定します。

var language:[String]
language = ["HTML","CSS","JavaScript","PHP","Swift"]
// 1行で宣言と初期値の設定も可能
var language:[String] = ["HTML","CSS","JavaScript","PHP","Swift"]

配列の要素を取得する

配列の中の要素には配列名[要素番号]でアクセスできます。

var language = ["HTML","CSS","JavaScript","PHP","Swift"]
print(language[0]) // HTML

language[0] = "HTML5"
print(language[0]) // HTML5

配列の要素にレンジを持たせてアクセスする

配列の要素には要素番号にレンジ(幅)を持たせて参照することもできます。その場合は要素番号...要素番号の形式でレンジを持たせることができます。

var language = ["HTML","CSS","JavaScript","PHP","Swift"]
print(language[0...3]) // ["HTML", "CSS", "JavaScript", "PHP"]

// 要素の個数が合わなくても上書き可能
language[0...3] = ["HTML5"]
print(language) // ["HTML5", "Swift"]

配列に要素を追加する

最初に宣言した要素数に加えて追加したい場合は配列.append(要素)を使って追加していきます。

var language = ["HTML","CSS","JavaScript","PHP","Swift"]
language.append("C++")
print(language) // ["HTML", "CSS", "JavaScript", "PHP", "Swift", "C++"]

配列に複数の要素を追加する

var language = ["HTML","CSS","JavaScript","PHP","Swift"]
language.append(contentsOf:["C++","SQL"])
print(language) // ["HTML", "CSS", "JavaScript", "PHP", "Swift", "C++", "SQL"]

連想配列の作り方とprintエラー

配列にもラベルをつけて連想配列(辞書型)にすることも可能です。しかしprint()を使う場合は「Expression implicitly coerced from 'String?' to 'Any'」と言ったWarning(警告)が出てしまうので??(NULL合体演算子)でエスケープできます。

var language = ["a":"HTML","b":"CSS"]
let result = language["a"] // HTML
print(result) // Expression implicitly coerced from 'String?' to 'Any'
// ↓これで解決
print(result ?? "")

タプルと配列の違い

タプルと配列は似ている部分が多く混同しがちです。両者の違いを見比べてみましょう。

タプル 配列
囲い文字 ( 〜 ) [ 〜 ]
ラベルの付け方 (name:"ame") ["name":"ame"]
要素の取り出し方 tuple.0 array[0]
型宣言 tuple:(String,Int) array:[String]

両者を扱う上での違いとポイント

// 問題なし
var language = ["HTML","CSS"]
for lang in language {
    print(lang)
}

// error: for-in loop requires '(String, String)' to conform to 'Sequence'
var language = ("HTML","CSS")
for lang in language {
    print(lang)
}

Optional(オプショナル)型とnil

Optional(オプショナル)型とは空の状態(nil)を格納できる変数の型式です。Swiftでは値が空であることに厳格で通常ではnilを参照しようとするとエラーを起こしてしまいます。

nilを通常の変数に格納する

通常の変数にnilを格納しようとするとエラーになります。

var bird: String
bird = nil // expression failed to parse : nil' cannot be assigned to type 'String'

nilを許容する変数の宣言方法

型名の後に?をつけるとnilを許容するOptional型として宣言されます。通常の変数通り宣言した型に準じた値を格納することもできますが、出力する場合はOptional(値)となってしまいます。

var bird: String?
bird = nil
bird = "アマツバメ"
print(bird) // Optional("アマツバメ")
// 警告:Expression implicitly coerced from 'String?' to 'Any'

これは変数birdがOptional型になったことで「nilかもしれない値(オプショナルバリュー)」になっているからです。そのまま使用するとエラーになる可能性があるから注意してねということですね!

アンラップ

オプショナルバリューを出力する際はOptional型を解除(アンラップ)しないといけません。変数の後ろに!をつけるとその値を強制的にアンラップすることができます。

var bird: String?
bird = "アマツバメ"
print(bird!) // アマツバメ

??演算子

??演算子を使用するとnilだった場合に代わりの値を出力することができます。

ar bird: String?
print(bird ?? "アマツバメ")

オプショナルバインディング

オプショナルバリュー(nilかもしれない値)をエラーを起こさないように安全にアンラップする方法がオプショナルバインディングです。種類はいくつかありますが、値がnilかどうかを識別し処理を分岐させるという点は同じです。

guard〜else構文

guard〜else構文関数の中でオプショナルバリューを扱う時に使用できるオプショナルバインディングです。変数の中に値を格納する際にnilかどうかをチェックし処理を分岐させます。nilだった場合はその時点で関数の処理を中断させ、nilでない時は値をアンラップして格納したあと後続の処理を続けます。

guard let 変数 = オプショナルバリュー else {
// nilだった場合の処理
return  // ここで処理が中断される
}
// nilではなかった場合の処理

変数の宣言はletでもvarでもOKですが、後続の処理で変数自体を使わない場合はのValue '変数' was defined but never used; consider replacing with boolean testような警告が出てしまうのでnilかどうかを確かめる構文に変えておきます。

guard オプショナルバリュー != nil else {
// nilだった場合の処理
return
}

if〜else構文

guard文はnilだった場合に処理を中断させましたがif分のオプショナルバインディングは主に後続の処理を分岐させる場合に使用されます。基本的な使い方はguard文と同じです。

if let 変数 = オプショナルバリュー {
// nilではなかった場合の処理
} else {
// nilだった場合の処理
}

関数

Swiftでの関数はfuncで定義します。

func 関数名 () {
  処理
}

定義すれば関数名()と記述するだけで特定の処理を実行させることができます。

func printFoo() {
  print("foo")
}

printFoo() // foo

関数を実行して戻り値を受け取ることも可能です。その際は戻り値の型を明示的に指定しないとエラー(Unexpected non-void return value in void function.Did you mean to add a return type?)になります。

func 関数 () -> 戻り値の型{
    return 戻り値
}
func backFoo () -> String{
    return "foo"
}
print(backFoo()) // foo

関数に引数を渡す

関数に外から値(引数)を渡すこともできます。定義するときに引数名とその型を、呼び出す時には引数名:値の形式で指定しないとエラーになってしまいます。

func printHello (user : String) {
  print("こんにちは\(user)さん")
}

printHello(user :"ame") // こんにちはameさん

引数に初期値を指定する

引数には初期値を指定することもできます。 初期値は上書きすることもできるので、設定していれば外部から値を渡さない場合の処理と外部から受け取る2つのパターンに対応した関数にすることができます。

func printHello (user : String = "ame") {
  print("こんにちは\(user)さん")
}

printHello() // こんにちはameさん
printHello(user :"kasa") // こんにちはkasaさん

呼び出し時に引数名を省略する

引数名の定義時に_をつけると呼び出し時の引数名を省略できます。

func printHello (_ user : String) {
  print("こんにちは\(user)さん")
}

printHello("ame") // こんにちはameさん

呼び出し時に引数名を別名にする

外部引数名 引数名 : 型の形式で定義すると呼び出し時の引数名を任意のものに変更することができます。

func printHello (customer user : String) {
  print("こんにちは\(user)さん")
}

printHello(customer : "ame") // こんにちはameさん

私がSwift UI学習に使用した参考書

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index