0
1

More than 3 years have passed since last update.

Swift3入門

Last updated at Posted at 2020-05-09

はじめに

某プログラミング学習サイトの学習記録を記します。

共通操作

・範囲選択:Shiftを押しながらクリック
・複数行コメントアウト:Command /

01

・Xcodeでplaygraoundを新規作成する
・種類はBlankを選ぶ (他にはGame, Map, Single Viewがある)

02

・下記について、C言語と同じ
 ・コメント
 ・print関数
 ・文字列を""で囲むこと
 ・文末が;であること
・実行形式の選択は、□または△を長押しすることで変更できる
 短く押すと実行される。
・右ペインに実行結果が表示される

03:変数と定数

・変数:var
・定数:let

・例
 let msg:String; // 文字列型の定数msgを宣言
 msg = "hello"; // msgに"hello"を代入

 let msg = "hello"; // 型推論が行われmsgは文字列型となる

※:C言語と違い、

04:データ型

・下記はC言語と同じ
 ・Int:整数型
 ・Float, Double
 ・キャスト(型変換)
・Bool型:true / false

05:演算

・下記はC言語と同じ
 ・四則演算
 ・単項演算子(+=, *= /= -=)
 ・論理演算(&&, ||, !)
・文字列
 ・+で連結 "hello " + "world" → "hello world"
 ・()で数値を文字に変換できる。()の中で演算できる。
  (例) 変数yが15の時
    "y is (y)" → "y is 15"
    "2*y is (2*y)" → "2*y is 30"

06:分岐

・下記はC言語と同じ
 ・分岐(if, else, if else)
 ・比較(>, >=, <=, ==, !=)
 ・条件演算子(条件文 ? 真 : 偽)

07:switch

・switchの構文はC言語と同じ
 ・default, breakもC言語と同じ
・caseの作り方
 ・単一: (例) case 0:
・複数: (例) case 1, 2, 3:
 ・範囲: (例) case 4...6:
 ・範囲: (例) case 7..<9: 9を含まない
 ・比較: (例) case let n where n > 20; 20超の場合

08:while

・whileの構文はCと同じ
・C言語のdo whileと同じ機能が repeat whileで実現される
 repeat {
   実行文;
} while (条件)

09:for

・構文 for 変数 in データ範囲 {処理}
・例 for i in 0...5 {print(i); }
・break, continueはC言語と同じ。

10:オプショナル型

・nil:空白の値
・nilを代入可能とするには、Optinal型とする必要がある
 (例) let s:String = nil;      // ×
(例) let s:Optinal = nil; // ○
 (例) let s:String? = nil; // ○

・nilの判定
 (例)if (s != nil) {
print(s!); // unwrap
}
・unwrap:変数の後ろに!を付けてOptinal型から値を取り出すこと
・Optinal Binding:unwrapを行う別の方法
 (例) if let value = s { 処理}
  sがnilでない場合だけunwrapしてvalueに代入する
・さらに別の方法
 (例) print(s ?? "this is nnil");
 sがnilでなければsを、nilであれば文字列を表示する

11:配列

・データの型を[]で囲う
 (例) var scores:[Int] = [50, 40];  // 型を指定
 (例) var scores2 = [50, 40];     // 型推論して省略

・配列の要素を制御する
 (例) score[0] = 30;

・配列の要素数を数える:count関数
 (例) score.count

・配列が空かどうかを調べる:isEmpty関数
 (例) score.isEmpty

・空の配列を作成する
 (例) var names = String;

・末尾への要素追加
 (例) names.append = "abc";
 (例) names += ["def"];

12:タプル(異なる型のデータを扱える)

・(例) var items = ("apple", 5):
・(例) 読出:print(items.0);
・(例) 書込;items.1 = 3;
・変数名を宣言する
 (例) var items = ("apple", 5);
let (product, amount) = items;
・一部だけを変数宣言する
 (例) var items = ("apple", 5);
let (product, _) = items;
・初期化時に名前を付ける
 (例) var items = (product:"apple", amount:5);
print(items.product);

13:集合

・集合は、順序を持たず、値の重複を許さない
・宣言方法
 (例) var winners:Set = [3, 5, 8, 8];
(例) var winners:Set = [3, 5, 8, 8]; // 型推論
    print(winners); // [3, 5, 8]
・データを含むか判定する
 (例) winners.contais(3); // 3を含むならtrueを返す
・データを追加
 (例) winners.insert(10); // 10を追加
・データを削除
 (例) winners.remove(5); // 5を削除
・データ数を数える
 (例) winners.count; // データ数を返す

・空集合の作成
 (例) let s = Set();
    print(s.isEmpty); // trueを返す
・演算
 (例) let a:Set = [1, 3, 5, 8]
    let b:Set = [3, 5, 8, 9]
print(a.union(b)); // 和集合:[5,8,3,1,9]を返す
print(a.intersection(b)) // 直積 :[5,3,8]を返す
print(a.subtracting(b)); // 差  :[1]を返す

14:辞書(キーと値で管理するデータ)

・(例)キーが文字列、値が整数の場合
 var sales:Dictionary = ["MrA":300, "MrB":400]
var sales = ["MrA":300, "MrB":400]; // 型推論
・値の代入
 (例) sales["MrB"] = 500;
・値の取出し
 (例) print("sales["MrB"] ?? "n.a.") // MrBが存在しなければ"n.a."
   // キーに対する値が存在しない場合はOptional型のnilが返ってくる
・データの追加
 (例) sales["MrC"] = 100; // MrCを追加(代入と同じ)
・データ数を数える
 (例) print(sales.count)
・一覧を出力
 (例) for (key, value) in sales {
      print("(key):(value)")
    }
・空の辞書を作成する
 (例) let d = String:Int; // キー:String, 値:Intの空の辞書
    print(d.isEmpty); // trueを返す

15:関数

・引数と戻り値がなければC言語と同じ
・戻り値がある場合
 (例)
func sayHi() -> String { // 文字列を返す関数の宣言
   return "hi"      // 戻り値
 }
 print(sayHi()); // 戻り値を印字

16:引数

・関数名の後に(変数名:型)の形式で指定する
 (例) func sayHi(name: String) {
print("hi (name)")
}
sayHi(name: "A") // 結果:"hi A"

・変数名にラベルを付けることで、宣言時と違う変数名で実行する
 (例) func sayHi(from name: String) { // 変数nameにfromというラベルを付ける
print("hi (name)")
}

  sayHi(from: "B")   // 結果:"hi B"

・変数名のラベルを省略する
 (例) func sayHi(_ name: String) {
     print("hi (name)")
    }
    sayHi("C") // 結果:"hi C"

・変数の初期値を決める
 (例) func sayHi(_ name: String = "D") {
print("hi (name)")
}
sayHi() // 結果:"hi D", 引数は初期値を使用する

17:inoutキーワード

・引数を渡す際、アドレスを渡す場合にinoutキーワードが必要になる
 (例)
  func add10(x:inout Int) { // アドレス渡し
   x = x + 10; // inoutキーワードがなければエラーとなる
   print(x)
  }
  var i = 10;
  add10(x : &i); // アドレス渡し
  print(i); // 20

18:class

・宣言
 (例) class User {     // classの宣言
    let name:String   1/ propertyの定義
    var score:Int
    init() {      // propertyの初期化
     self.name = "me" // selfを使って代入
     self.score = 20
    }
   }

・インスタンス化して利用
 (例)
  let user:User = User(); // クラスUserのインスタンスuserを定義して初期値代入
  print(user.name); // インスタンスuserのnameを印字

19:イニシャライザ

・インスタンス毎に違う値を持たせる
 (例) class User {
     let name:String;
     var score:Int
     init (name:String, score:Int) { // 引数:String型のnameとInt型のScore
       self.name = name; // 引数nameをclassのnameに代入
       self.score = score;
     }
   }
   let tom = User(name:"tom", score:20);
   print(tom.name); // 結果:tom
   print(tom.score);   // 結果:20

・変数名を省略
  イニシャライザ:init(_ name :String, _ score:Int)
  インスタンス化:let tom = User("tom", 23);

・引数が渡されなかったときのイニシャライザを作成
 (例) class User {
     let name:String;
     var score:Int
     init (name:String, score:Int) {
       self.name = name; // 引数nameをclassのnameに代入
       self.score = score;
     }
     init () { // 引数を指定しない場合のイニシャライザ
       self.name = "no name"; // 引数nameをclassのnameに代入
       self.score = 0;
     }
   }

   let noname = User(); // 引数を指定しない
   print(noname.name); // "no name"
   print(noname.score

20:計算プロパティ(動的に計算可能なプロパティ)

・クラス内の変数にはget関数とset関数を追加できる
 (例)
  class User {
    let name:String;
    var score:Int
    var level:Int {
      get {
       return Int(self.score/10) // levelの取得時、scoreの1/10を返す
// return Int(score/10) // 自明な場合は、selfを省略可能
      }
      set {
       if newValue >= 0 { // 値をnewValueで受け取る
        score = newValue * 5; // 5倍してscoreに入力する
       }
}
   }
    // 戻り値だけの場合(getだけ)の場合の記述方法
    //var Int {
    // return Int(score/10);
    //}

 let u = User("MrA", 2);

   u.level = 5;
   print(u.score) // 結果:50

21:プロパティの値の変化前後

・willSet関数で変化前、didSet関数で変化後を監視できる
・(例)
  class User {
   var score:Int {
    willSet { // 変化前
print("(score) -> (newValue)")
   }
   didSet {  // 変化後
     print("Changed: (score - oldValue)")
   }
}
  let tom = User("tom", 2)
  tom.score = 53 // "2 -> 53, Changed:51
  tom.score = 20 // "53 -> 20, changed:-33

22:メソッド

・func 関数名(引数)
・例
 class User {

  let name:String
  var score:Int
  init(_ name : String, _ score:Int) {
   self.name = name;
   self.score = score;
  }
  func sayHi(_ msg:String) { // データ型の省略fs
   print("(msg) (name)")
  }
 }
 let tom = User("tom", 2)
 tom.sayHi("hola"); // 結果:"hola tom"

23:クラスの継承

// 親クラス(スーパークラス)
Class User {
 let name:String;
 var score :Int;
 init(_ name:String, _ score:Int) {
  self.name = name;
  self.score = score;
 }

 func sayHi() { // overrideを禁止したい場合は、「final func 関数名」とする
  print("hi (name)")
 }
}

// 子クラス(サブクラス)
class AdminUser:User { // class 子クラス名:親クラス名
 func sayHello() {
  print("hello (name)")
 }
 override func sayHi() { // override:親クラスのメソッドを上書き
  print("admin hi (name)")
 }
}

let tom = User("tom", 23);
let bob = AdminUser("bob", 30);
print(bob.name);  // 結果:bob
print(bob.score); // 結果:30
bob.sayHi(); // 結果:admin hi bob
bob.sayHello(); // 結果:hello bob

24:型プロパティ、型メソッド

・インスタンスではなく、クラスに直接関連するプロパティやメソッドはstaticを先頭に付ける
・(例)
Class User {
let name:String;
 var score:Int;
 static var count = 0; // クラスから直接扱う
 init(_ name:Stirng, _ score:Int) {
  self.name = name;
  self.score = score;
  User.count += 1; // イニシャライザはインスタンスから呼ばれるので、型プロパティへのアクセスにはクラス名を付ける
  }

 class func getInfo() {
  // static funcにするとoverrideを禁止できる
  print("(count) instances);
}

class AdminUser:User {
 override class func getInfo() {
  print("admin (count) instances")
}
}

User.getInfo(); // 結果:0
let a = User("a", 1);
User.getInfo(); // 結果:1

AdminUser.getInfo(); // 結果:1
let b = AdminUser("b", 2);
AdminUser.getInfo(); // 結果:2

25:型キャスト

・(例)
class User {
 let name : String;
 init(_ name : String) {
  self.name = name;
 }
}

class AdminUser : User{}

let tom = User("tom")
let bob = AdminUser("bob")

// 配列として扱う
let users:[User] = [tom, bob];

 // 「:[User]」は記述しなくても型推論してくれる
 // 親子クラスのため同じ種類として扱ってくれる

for user in users {
 // AdminUserの場合だけ表示する(1)
 if let u = user as? AdminUser // 「as?」で一語(スペース挿入禁止)
  // as?で変換可能か調べる。失敗ならnilが返ってくる
  // optional bindingを使う
// 成功時はAdminUser型のuserがuに代入される
  print(u.name); // 結果:bob
 }

 // AdminUserの場合だけ表示する(2)
 if user is AdminUser { // userがAdminUser型であるか確かめる
  let u = user as! AdminUser // as!でunwarpしてくれる
// AdminUser型のuserが返ってくる
  print(u.name); // 結果:bob
 }
}
// unwrap:optional型からデータを取り出すこと
// optional型:nilを格納できる型
// optional Binding:値がnilで内場合だけ値を取り出す

#26:プロトコル
・クラスに対して、実装が必須なプロパティやメソッドを定義する
・(例)

protocol Printable { // プロトコル定義
 var type:String { get } // 読み取り専用
 var count:Int {get set} // 読み書き可能
 func printout()      // 実装はクラスで行うので定義は不要

 // イニシャライザは不要
}

class User:Printable {
 let type = "Laser"
 let count = 0;
 let name:String;
 init(_ name:String) {
  self.name = name
 }
 func printout() {
  count += 1;
  print("(type) : (count)")
 }
}

let a = User("a")
a.printout(); // 結果「Laser:1」
a.printout(); // 結果「Laser:2」
a.printout(); // 結果「Laser:3」
a.printout(); // 結果「Laser:4」

27:エクステンションによる拡張

・既存の型に新しいプロパティやメソッドを追加する
・(例)
// String型を拡張し、文字列長を返す変数を追加する
extension String { // String型を拡張
 var length :Int { // lengthという変数を追加
  return self.characters.count // プロパティの一つであるcountを返す
 }
}

let msg = "hello"
print(msg.characters.count) // String型の元々の文字列長の取得
print(msg.length); // 新規に追加したlength変数による文字列長の取得

(例)
protocol Printable { // Printableのプロトコル(実装必須関数の定義)
 func printout()
}

extension Printable { // 既存のPrintableに
 func printout() { // 関数printoutを追加
  print("printing)
 }
}

// PrintableをUserクラスに適合させる
class User:Printable { // Printableのインスタンス
 let name:String
 init(_ name:String) {
  self.name = name;
 }
} // インスタンス内にprintout関数の実装が不要

let tom = User("tom")
tom.printout()

28:参照型と値型

・Int, doubleなどは値型
・Classは参照型
(例)
class User {
 var name:String;
 init(_ name:String) {
  self.name = name;
 }
}

var org = User("A)
var copy = org;
org.name = "B"
print(org.name) // 結果:B
print(copy.name) // 結果:B

29:構造体

・classと、ほぼ同じ機能を持つ。
・classが参照型であるのに対して構造体は値型である。
・classと違って継承が出来ない
・extension, protocolは使える
・メソッドでプロパティを変更するには、funcの前にmutatingを付ける

30::列挙型

・enum (型名) {
  case 値1
  case 値2
 }

・例
 enum Direction :Int {
  case right = 1
  case left = -1
 }
 print(Direction.rihgt.rawValue); // 値を取り出す
 var dir:Direction
 dir = .right // Direction.rightの省略形

 switch (dir) {
  case .right: print("right");
  case .left: print("left");
 }

31:ジェネリクス型

・データ型を汎用化させる
 関数名の後にを追加し、データ型をTとする。

・func getData(x:Int) { // 通常の書き方
・func getData(x:T) { // ジェネリクス型を使用
 print(x)
 }
 getData(x:"Hello") // 結果:"Hello"
 getData(x:2.3) // 結果:"2.3"

32:サブスクリプト

・サブスクリプト:インスタンスに対して、配列と同じようにインデックスを付ける
class Teams {
 var memvers = ["A", "B", "C"]; // サブスクリプトのアクセス対象のデータを用意
 subscript (index : Int) -> String { // indexに使う値の型と返値の型を指定
  get {                 // サブスクリプトで取得する時の処理
   return members[index] 
  }
  set {                 // サブスクリプトで設定する時の処理
   members.insert(newValue, at:index) // 設定値をnewValueで取得できる
  }
 }
}

var t = Team()
print(t[1]) // 結果:"B"
t[3] = "D"
print(t[3]) // 結果:"D"

33:guard

・異常処理を分かりやすく書くための仕組み

・guardを使わない書き方
func test(_ msg:String?) { // StringのOptional型
 if let s = msg { // nil判定
  print(s)
 } else {
  print("nil")
 }
}

・early return , early exitを使用する
func test(_ msg:String?) {
 if msg == nil {
  print("nil")
  return
 }
 print(msg!) // unwrapする
}

・guardを使う
func test(_ msg:String?) {
  // msgがnilでなければsに代入、sならelse以下を処理する
  guard let s = msg else {
   print("nil")
   return // guardの中では、returnを忘れるとエラーを出してくれる
  }
  print(s)
}

34:例外処理

// 例外の種類を列挙型で定義
enum LoginError:Error { // プロトコルを使用する
 case emptyName
 case shortName
}

class User {
 let name:String
 init(_ name:String) {
  self.name = name
 }

 // 例外が発生する可能性がある場合は関数名の後にthrowsを付ける
 func login() throws { 
  // nameが空でないときは無処理。空の時の処理を定義する
  guard name != "" else {
   throw LoginError.emptyName // 例外を投げる
  }
  guard name.count > 5 else {
   throw LoginError.shortName
  }
  print("success")
 }
}

let a = User("AAAAA") // 結果:short
let a = User("AAAAAA") // 結果:Success
let a = User(") // 結果:enter

// 例外が発生するときの書法
do {
 try a.login()
} catch LoginError.emptyName {
 print("enter")
} catch LoginError.shortName {
 print("short")
}

35:Optional Chaining

・Optinal型が連続する場合に安全にnilチェックする
class User {
 var name:String? = "" // nameがoptional型の場合
}

let user:User? // Userがoptional型の場合(Optional型を短く宣言する)
user = User()
user?.name = "a" // ※1
if let s = user?.name?.uppercased() { // ※1 ※2
 print(s)
}

// ※1:Optional Chaining:optional変数の後に?を付ける。
// nilの場合はnilを、nilでなければその値を含むOptional型を返す
// ※2:Optional Binding

36:暗黙的アンラップオプショナル (Implicity Unwarpped Optional)

・通常のOptinal型
 var msg:String? // Optional型(nilを取ることができる)
 msg = "a"

 if msg != nil { // nilチェック
  print(msg!) // Optional型をUnwap
 }

・暗黙的アンラップオプショナル(UnWrap不要)
 var msg:String! // 末尾を「?」ではなく「!」にする
 msg = "a"

 print(msg) // Unwrap不要(末尾の「!」不要)

以上

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1