Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

AndroidエンジニアがSwiftをゼロから爆速学習した時のメモ

はじめに

タイトルの通り。面倒なこと全部すっ飛ばしてkotlin脳をSwift脳にコンバートするためにとったメモ。読んだ本はswift実践入門

あと関係ないですがちょうどFF14の漆黒のヴィランズ終わったところなのでたとえがソレっぽいです。

言語の基礎

変数宣言

kotlin
val enemyId = 10
var name : String = "フィリア"
swift
let enemyId = 10
var name : String = "フィリア"

ポイント

  • val -> let になった
  • 型推論の方法は同じ
  • varも同じ

関数周り(関数宣言と_)

kotlin
fun updateStatus(str:Int, int:Int, dex:Int) = ..

/*呼び出し*/
updateStatus(1,2, dex = 3)
swift
func updateStatus(str:Int,_ int:Int, dex:Int) = ..

/*呼び出し*/
updateStatus(1,2, dex: 3) //OK
updateStatus(1,2,3) //NG

ポイント

  • 関数宣言はfunfunc
  • 第二引数以降は「_」が宣言時についていないと呼び出し時にラベル指定が必須になる
  • ラベル指定が=:
  • 参考ページ

null,nullable

kotlin
val weaponId: Int? = null
val weaponName: String? = "ガンブレード"
val nullWeapon: String? = null

val nonNullWeapon = nullWeapon ?: "ガンブレード"
val connectWeapon = weaponName!! + nullWeapon!! 
swift
let weaponId: Optional<Int> = nil
let weaponId: Int? = nil
let weaponName: String? = "ガンブレード"
let nullWeapon: String? = nil


let nonNullWeapon = nullWeapon ?? "ガンブレード"
let connectWeapon = weaponName! + nullWeapon!

ポイント

  • null -> nilになった
  • kotlinでは?で表現してたOptionalを明示的にOptionalとしても書ける
  • ?:??になった
  • 強制アンラップは!!!
  • その他は大体同じっぽい?

Optional

swift
let none = Optional<Int>.none
let some = Optional<Int>.some(1)

ポイント

  • noneはOptionalで値がないケース、Scalaっぽい?
  • someはOptionalで値があるケース、Scalaっぽい?

ジェネリクス的なやつ

kotlin
fun addDamage<T : Enemy>(enemy: T) = ..
swift
func addDamage<T : Enemy>(_ enemy : T) = ..

ポイント

  • 書き方一緒

Listとか

kotlin
val enemyNames = listOf("フィリア", "ティターニア", "イノセント") //不変リスト
val itemLists = arrayOf("エーテル", "エクスエーテル") //可変リスト
itemLists.add("ハイエーテル")
swift
let enemyNames = ["フィリア", "ティターニア", "イノセント"]

let itemLists = Array<String>()
itemLists.append("エーテル")
itemLists.append("エクスエーテル")
itemLists.append("ハイエーテル")

ポイント

  • 不変リストは配列っぽい書き方
  • 可変リストはJavaっぽい書き方

連想配列(Dictionary)

kotlin
val enemyMap = mapOf(Pair(1,"ティターニア"), Pair(2,"フィリア"))
enemyMap[1] //ティターニア
swift
let enemyDic = [1: "ティターニア", 2: "フィリア"]
enemyDic[2] //フィリア

ポイント

  • 配列っぽい感じに書く。JSONっぽいかも?

型まわりの制約

kotlin
val hp:Int = 1234
val mp:Long = hp //NG
val mp:Long = Long(hp) //OK
swift
let hp:Int = 1234
let mp:Int64 = hp //NG
let mp :Int64 = Int64(hp) //OK

ポイント

  • kotlinと同じ。型が違ったら代入できない。要キャスト

Tuple

kotlin
val pair = Pair(1,2)
pair.first //1
swift
let tuple2 = Tuple(1,2)
tuple2.0 //1
let tuple3 = Tuple(1,2,"そろそろFF14ネタ疲れてきた")
tuple3.2 //そろそろFF14ネタ疲れてきた

ポイント
- 2個からTupleになったよ、3個でもTupleだよ。Scalaっぽい

制御文周り

kotlin側はもういいよね...

if文

swift
if value <= 3 {

} else if value >= 3 {

} else {
}

ポイント
- 括弧がないぞー!

if-let

swift
let name = Optional("ティターニア")

if let n = name {
  print("名前は\(n)です")
} else {
  print(nameless")
}

ポイント

  • letっぽいけどIf文っぽい。特に違和感はない、と思う

guard

kotlin
fun someFunc() {
  val v = -1

  require(v > 0)
}
swift
func someFunc() {
  let v = -1

  guard v > 0 else {
   return
  }

}

ポイント

  • kotlinのrequireと似てる。kotlinはIllegalExp投げるけどSwiftはReturnするだけ

switch,where

swift
let optA: Int? = 1

switch optA {
  case .some(let a) where a > 10:
    //10より大きく、aが存在
  default:
   //10以下かaが存在しない
}

ポイント

  • whereつけると条件式も追加できるぞ。kotlinなら内側にif書くしかなかったやつ

ループ制御(for,for-calse, while, repeat-while)

swift
for elem in array { //foreachっぽいやつ
  print(elem)
}

for case 2..3 in array { //独特
}

while i>3 { //普通
}

repeat {
} while j>3 //いわゆるdo-while

ポイント

  • 特になし。そのまんま

制御構文(fallthrough,break,continue,return,throw)

swift
let a = 1
switch a {
 case 1:
   print("case1")
   fallthrough
 case 2:
   print("case2")
 default:
   print("def")
}

//出力結果
case1
case2

ポイント
- fallthroughを使うと次に制御が飛ばせる。Obj-Cの兼ね合いで仕方なく追加された匂いがプンプンする。基本使用禁止だろう
- break,continue,return,throwはkotlinと全く同じ

ラベル

swift
label: for elem in [1,2,3] {
  for nestedElem in [12,3,4] {
    print("moge")
    break label
  }
}

ポイント

  • kotlinで言うところのreturn@~に近い挙動。指定したlabelのループを抜ける

遅延実行(defer)

swift
var count = 0

fun someFunc() -> Int {
  defer {
    count++
    print("second")
  }
  print("first")
  return count
}

print("call func")
someFunc()

//実行結果
call func
first
second

ポイント

  • 関数スコープを抜ける時に実行される。んだけど、これ制御複雑になるから基本禁止では・・?
  • 参考になりそうなページ

関数的なやつら

基本構文

swift
func 関数名(引数名1: , 引数名2:) -> 戻り値の型 {
}

ポイント

  • :->になった

デフォルト引数

swift
func greet(user: String = "nameless") {
}
  print("hello \(user)")

ポイント

  • kotlinと同じ

インアウト引数

swift
func greet(user; inout String) {
  if user.isEmpty `
     user = "nameless"
  }
  print("hello\(user)")
}

var user: String = ""
greet(user: &User)
print(\(user))

//実行結果
hellonameless
nameless

ポイント

  • いわゆる参照渡し。Obj-Cの名残がプンプンする。つまり闇なので使わない方が良い

可変長引数

swift
func print(strings: String...) {

}

ポイント

  • kotlinと同じで...をつける

オーバーロード

swift
func getV():Int

func getV(i:Int):Int

func getV():String

ポイント
- 引数違いのオーバーロードの他に、戻り値が違うだけでもオーバーロードできる

クロージャ

基本構文

swift
{(引数名1 : , 引数名2 : ...) -> 戻り値の型 in 
  //処理
}

let triple = {(x:Int) -> Int in
  x * 3
}

let quad = {(x:Int) -> Int in
  print(\(x))
  return x * 4
}

triple(3) //9
quad(3) //12

let closure:(Int) -> Int
func someFunction(x:(Int)->Int) {}

someFunction(closure)

var lengthCal: (String)->Int

lengthCal = {string in //型推論してくれるぞ
  return string.conut
}

lengthCal("abc") //3

let lengthOfString = {(string:String)->Int in
  return string.count
}

lengthOfString("abcd") //4

let isEqual:(Int,Int) -> Bool = {
  return $0 == $1
}

ポイント
- kotlinで言うところの関数変数っぽいやつ
- 処理が2行以上になるならreturn必須(quad)
- 関数の引数にも使えるぞ!(someFunction)
- 型推論も仕事してくれるぞ(lengthCal)
- もちろん「クロージャを引数にとるクロージャ」もいける。(lengthOfString)
- デフォルト引数は使えないぞ!
- 引数名すら省略できるぞ!(isEqual)

関数引数としてのクロージャと属性指定

基本構文

swift
func 関数名(引数名: @属性名 クロージャの型) {
}

属性

  • escaping→引数のクロージャが関数のスコープ外で保持される可能性を示す
  • autoclosure→遅延評価を実現するための属性。付けると遅延評価してくれる

トレイリングクロージャ

swift
func execute(param: Int,_ process:(Stirng)->Void) {
}

execute(1, {string in 
  print($0)
})

execute(1) { string in
  print($0)
}

ポイント

  • カリー化(部分適応だっけ・・・?)
  • AndroidStudioならサジェッションがくるやーつ

型とかその辺の話

swift
struct 構造体名 {
let value = 123
  func printVal() {
    print(self.value)
  }
static let signiture = "send from iPhone"
}

class クラス名 {
  class ver signiture = "send form Android"
}

enum 列挙型 {
}

ポイント

  • structがあるぞ。structは値渡し、classは参照渡し
  • 自身へのアクセスはthis->selfになってるぞ
  • structの場合はcompanion Objectはないけどstaticがあるぞ。意味はJavaのStaticと同じだ!(変数だけでなくメソッドにも使えるぞ)
  • 上記のstaticと同じ使い方ができるのがclassプロパティだ。違いはクラスの方はオーバーライドできるぞ!(staticはオーバーライドできない)
  • クラスとか構造体の中の変数はプロパティと呼んでるぞ、C#と同じだ!

プロパティオブザーバ

swfit
var プロパティ名 = 初期値 {
 willSet {
   //プロパティ変更前に実行される処理新しい値はnewValue変数としてアクセスできる
 }
 didSet {
   プロパティ変更後に実行される
 }
}

ポイント

  • kotlinにはなかった機能・・・かな、多分。
  • 挙動は書かれている通り。ログとか仕込む?

レイジーストアドプロパティ

swift
lazy var インスタンスプロパティ名:  = 
static lazy var インスタンスプロパティ名:  = 

struct SomeStr {
  lazy var lazyV: Int {
    print("generate lazyV")
    return 2
  }
}

ポイント

  • SomeStrがインスタンス化された時ではなく、lazyVを参照した時に初期化される
  • kotlinのlateinit varby lazyを足して2で割ったような挙動

コンピューテッドプロパティ

swift
var プロパティ名:  { 
  get {
  }
  set {
  }
}

ポイント

  • kotlinのやつと一緒
  • set省略できる

イニシャライザ

swift

struct Greeting {
  let to: String

  init(to:String) {
    selft.to = to
  }
}

struct Greeting2 {
  let to: String
  init?(to:Optional<String>) {
   self.to = to ?? nil
  }
}

class Mail {
  let from:String
  let to:String
  let title:String

  init(from:String, to:String, title:String) {
    //初期化
  }

  convinience init(from: String, to:String {
    self.init(from:from, to:to, title:"mogmeoge")
  }

  deinit {
    //クリーンナップ処理
  }
}

let greeting = Greeting("some one")

ポイント

  • kotlinのinit関数とコンストラクタを足して2で割ったような機能。
  • 初期化の失敗がある場合はinit?にする。失敗するときはnilを返す
  • convinience をつけるといわゆるセカンダリコンストラクタ
  • 全て初期化されているならばinit関数は不要(kotlinと同じ)
  • deinitはいわゆるonDestroyみたいなやつ。インスタンス破棄時に呼ばれるぞ

サブスクリプト

コレクションの要素へのアクセスに使う

subscript(引数) -> 戻り値の型 { 
  get {
  }
  set {
  }
}

struct Progression {
  var numbers:[Int]
  subscript(index: Int)->Int {
    get {
      return numbers[index]
    }
    set {
      numbers[index] = newValue
    }
  }
}

ポイント

  • なぜコレクションだけ特別扱いしてしまったのか、コレガワカラナイ

エクステンション

kotlin
fun String.log() {
    print(this)
}
"test".log()
swift
extension String {
    func log() {
        print(self)
    }
    var enclosedString: String { 
       return "[ \(self) ]"
}
"test".log()

ポイント

  • extention修飾子をつける必要がある
  • もちろん定数に対しても拡張できる
  • 参考ページ

型の種類

値渡し、参照渡し

  • struct→値渡し
  • class→参照渡し

列挙型

enum Weekday {
     case sunday
     case monday
     case tuesday
     case wednesday
     case thursday
     case friday
     case saturday

     init?(japaneseName: String) {
         switch japaneseName {
         case "日": self = .sunday
         case "月": self = .monday
         case "火": self = .tuesday
         case "水": self = .wednesday
         case "木": self = .thursday
         case "金": self = .friday
         case "土": self = .saturday
         default: return nil
         }
     }
 }

enum 型名: ローバリューの型 {
  case ケース1 = ローバリュー
  case ケース2 = ローバリュー
  ..
}

ポイント

  • initを用意するとkotlinでparserを書くのとと同じ感じ。こっちの方がスマートか?
  • ローバリューはenum Weekday(val name)的なやつと一緒.Enumの要素と値を紐づける

プロトコル

いわゆるinterfaceクラス

基本構文

protocol プロトコル名 {
  //定義
}

struct 構造体名 : プロトコル1, プロトコル2... {
  //中身
}

class クラス名 : スーパークラス名, プロトコル1, プロトコル2 {
  クラスの定義
}

extension エクステンションを定義する対象の型 : プロトコル名 {
  //定義
}

ポイント

  • 素直な感じなのでそのまんま

プロパティ

protocol プトロコル名 {
  var プロパティ名: 型 {get set }
}

protocol SomeProtocol {
  var id:Int {get}
}
struct SomeStr1: SomeProtocol {
  var id:Int
}

struct SomeStr2: SomeProtocol {
  let id: Int
}
struct SomeStr3: SomeProtocol { 
  var id: Int {
     return 1
  }
}

ポイント

  • プロトコルでのプロパティは常にvar(継承先でそこはハンドリングするスタンス)
  • setもプロトコルに書かれている場合、letには適応できない

メソッド

protocol プロトコル名 {
  funcj 関数名(引数) -> 戻りの型
}

protocol SomeProtocol {
     mutating func someMutatingMethod()
     func someMethod()
 }

struct SomeStr: SomeProtocol {
 var number:Int
  mutaing func someMutatingMethod() -> Void {
    number = 1
  }

  func someMethod() {
    number = 1 //コンパイルエラー
  }
}

class SomeStr: SomeProtocol {
 var number:Int
  func someMutatingMethod() -> Void {
    number = 1
  }

  func someMethod() {
    number = 1 //OK
  }
}

ポイント

  • structは値渡しになるので、プロパティを更新するときはmutaingが必要
  • classは参照渡しなのでどちらも不要

連想型

protocol プロトコル名 {
  associatedtype 連想型名

  var プロパティ名: 連想型名
  func メソッド名(引数連想型名)
  func メソッド名() -> 連想型名
}

protocol SomeProtocol {
     associatedtype AssociatedType

     // 連想型はプロパティやメソッドでも使用可能
     var value: AssociatedType { get }
     func someMethod(value: AssociatedType) -> AssociatedType{
       return 1
     }
 }

//typealiasで指定
struct SomeStr1 : SomeProtocol {
  typealias AssiosicatedType = Int

  var value: AssosiatedType
  func someMEthod(value: AssosicatedType) -> AssociatedType {
   return 1
  }
}

//自動型推論
struct SomeStr2 : SomeProtocol {
  typealias AssiosicatedType = Int

  var value: Int
  func someMEthod(value: Int) -> Int {
   return 1
  }
}

// ネスト型AssociatedTypeを定義することで要求を満たす
 struct SomeStruct3 : SomeProtocol {
     struct AssociatedType {}

     var value: AssociatedType
     func someMethod(value: AssociatedType) -> AssociatedType {
         return AssociatedType()
     }
 }

ポイント

  • ジェネリクスに近い機能。歴史的背景を感じる
  • プロトコルって言うくらいだからインタフェースと言うよりも型に依存しない処理だけを表現するのに使うイメージが強い

制約系

protocol プロトコル名 {
  associatedtype 連想型名 : プロトコル名またはスーパークラス名 where 連想型の制約
}

protocol Container {
     associatedtype Content
 }

 protocol SomeData {
     associatedtype Value
     associatedtype ValueContainer: Container where
         ValueContainer.Content: Equatable, ValueContainer.Content == Value
 }

ポイント

  • where句の後ろは連想型の制約を書く

デフォルトの型指定

protocol SomeProtocol {
  associatedtype AT = Int
}

ポイント

  • protocolの時点で指定する。これでデフォルトはIntになる

プロトコルの継承周り

//プロトコルの継承
protocol プロトコルA : プロトコルB, プロトコルC...{
}

//クラス専用プロトコル
protocol プロトコル名: class {
} 

ポイント

  • ほぼKotlinと一緒
  • structとclassの2つがあるために、クラス専用プロトコルの宣言なんてものがあるぞ

エクステンション

extension プロトコル名 {
  実装(Not 定義)
}

extention プロトコル名 where 型制約 {
  型制約を満たす場合に有効になるエクステンション
}

ポイント

  • 既存のプロトコルに対して実装Extensionできる
  • 型制約をつけた場合、条件を満たした場合のみ使える

標準ライブラリのプロトコル

  • Equatable -> イコール
  • Comparable -> 比較
  • Iterator -> イテレータ
  • Sequence -> 要素の列挙のためのプロトコル
  • Collection -> サブスクリプトによる要素へのアクセス
  • Encodable,Decodable,Codable -> エンコード、デコード

ジェネリクス

基本構文

func 関数名<型引数> (引数名: 型引数) -> 戻り値の型 {
}

func someMethod<T> (value:T) -> T {
}

struct 構造体名<型引数> {
}

struct GenericStr<T> {
  var property:T
}

class クラス名<型引数> {
}

class GenericClass<T> {
  func someFunc(x: T) {}
}

enum 列挙型<型引数> {
}

enum GenericEnum<T> {
  case SomeCace(T)
}

ポイント

  • kotlinと同じ
  • ただしprotocolはassociatedtypeによって型が表現されるため、ジェネリクスが使えるのはstruct,class,enumの3つだけ

型制約

func 関数名<型引数: プロトコル名やスーパークラス名(引数)->戻り値の型 {
}

func 関数名<型引数: プロトコル名(引数)->戻り値の型 where 連想型: プロトコルやスーパークラス {
}

func 関数名<型引数1 : プロトコル1, 型引数2 : プロトコル2>(引数) -> 戻り値の型
     where プロトコル1の連想型 == プロトコル2の連想型 {

     関数呼び出し時に実行される文
 } 

ポイント

  • kotlinと(ほとんど)一緒
  • protocolが特殊運用になってるので、こっちもプロトコルについては特殊な記法になる
  • where句の後ろに連想型の制約を記載する

モジュール

考え方はkotlinのマルチモジュールと同じ

アクセス修飾子

  • open->モジュール内外で全てのアクセスOK
  • public->モジュール内外で全てのアクセスOK。ただしモジュール外での継承やオーバーライドは禁止
  • internal->同一モジュール内のみ(kotlinのinternalと同じ).デフォルトのアクセスレベル
  • fileprivate->同一ファイル内のみアクセス許可
  • private->対象の要素が属しているスコープ内のみ許可(kotlinのprivateと同じ)

コメントについて

// 通常コメント
/*
*  通常コメント
*/

/// ドキュメントコメント
/**
* ドキュメントコメント
*/

ポイント

  • 通常コメントはkotlinと一緒
  • ドキュメントコメントはkotlinで言うところのjavadocに近い. QuickHelpから見えるようになる

型の設計指針

struct or class

  • 基本structを使え
  • structのletがkotlinのvalに当たる。classのletはkotlinのvalと同等では無い。
  • deinit使いたいときはclassがいいかもよ
  • abstract calssという概念が存在しないので、表現する場合はprotocolを使う必要がある
    • abstractクラスとして表現していた「継承先で共通に使える実装」はprotocolのextensionで実装する
  • classの継承は共通のストアドプロパティを使いたいときくらいにしか使わない

Optional

  • kotlinと同じ設計思想

イベント通知回り

デリゲートパターン

  • 普通のデリゲートパターン。protocolで宣言する
  • 命名規則はdid<動詞>will<動詞><動詞>がいつ実行されるかを表現している.
  • 慣習的にUIKitで提供されているDelegateは第1引数がデリゲート元のオブジェクトを渡す。これは名前空間としてオブジェクトを区別するため
  • だいたいUIKitで提供されるやつがデリゲートパターンになっている

弱参照の解消

weakを変数の前につけると弱参照になる。弱参照になるとARCの参照カウントが0のまま更新されないようになる。

これはdelegateパターンを使うと第1引数にデリゲート元のオブジェクトを渡すために循環参照になる。そのため、delegateオブジェクトにweakを作って弱参照にする必要がある。

クロージャ(キャプチャリスト)

{[weak または unowned 変数名または定数名](引数) -> 戻り値 in 
  //処理
}

class SomeClass {
  let id: Int

  init(id: Int) {
     self.id = id
  }
}
let object1 = SomeClass(id:42)
let object2 = SomeClass(id:43)

let closure = { [weak object1, unowned object2] () -> Void in 
  print(type(of: object1))
  print(type(of: object2))
}

closure()

//実行結果
Optional<SomeClass>
SomeClass

ポイント

  • weakはメモリ解放を前提とした弱参照.メモリ解放が前提(つまりnilの可能性がある)のでOptionalになる。クロージャ内でオブジェクトにアクセスする時点で解放されていたらnilが返る
  • unownedはメモリ解放を想定しない弱参照.つまり参照時点では必ず参照元が存在している前提なのでオブジェクトそのまま。クロージャ内でオブジェクトにアクセスする時点で解放されていたらエラーになる
  • 使い所はkotlinと同じ感覚でOK。(コルーチンとはちょっと違うかな)

使い分け

循環参照を招かない場合

  • クロージャの実行時に参照するインスタンスが必ず存在する→キャプチャリストを使わない
  • クロージャの実行時に参照するインスタンスが存在しなくても良い場合→weak

循環参照を招く場合(大雑把にはclosureの中でselfを参照してるかつclocure外でclosureのインスタンスを保持している)

  • 参照するインスタンスが先に解放される可能性がある→weak
  • 参照するインスタンスが先に解放される可能性がない→unowned or weak

escaping属性

escapingをつけるとselfが必須になる=循環参照に気付きやすくする。逆に言えばescapingがない=循環参照がない、となる


var c: (() -> Void)? = nil

func execute(_ closure: @escaping () -> Void) {
         closure()
         c = closure
     }

オブザーバー

どっちかってーっとイベントハンドラーの実装に近い。(≠RxのObserver)。イベントハンドラに登録(addObserver)して、登録された同名のイベントハンドラに通知をし(post)、登録されたイベントハンドラに通知を受け取る(handle)、終わったら登録解除(removeObserver)。

割とやりたい放題できるので危険な香りがする。

selectorと@objc

#selectorはObj-Cのセレクタ型のオブジェクトにデータを渡すための修飾子。つけるとselector型になる感じ.クラスキャストに近い?

@objcはメソッドにつけるとObj-Cからアクセスできるようになる.selectorとセットで使う感じ

#selector(型名.メソッド名)

@objc func メソッド名

class SomeClass {
  @objc func someMethod() {}
}

let selector = #selector(SomeClass.someMethod)

非同期処理

RxSwiftでよくね?

エラー処理

Result<T,Error>,do-catch,defer

Result<T,Error>型で返すパターンと、do-catchで実現するパターンがある。Resultは非同期の処理用、do-catchは同期の処理用。

do {
  defer {
    doを抜けたら実行される
  }
   throw 的な何か
} catch {
  エラー処理.定数errorが参照できる
}

ポイント

  • Resultは関数型のResultと同じ設計方針で同じ使い方
  • do-catchは御察しの通りtry-catchと同じ
  • deferはfinallyに近い。必ず実行される系(ただしタイミングは違う)

throw,try,try!,try?

func 関数名(引数) throws -> 戻りの型 {
  throwの可能性のある処理
}

func someMethod throw -> Int {
   throw XXError
}

do { 
  let i = try someMethod()
} catch {

}

let i = try! someMethod() // Int or エラー

if let i = try? someMethod() {} //Optional<Int>

ポイント

  • javaでのメソッドの呼び元にエラーを返すやつ。
  • イニシャライザにも使える
  • 呼び元はエラーの発生する可能性のあるメソッドを呼ぶ場合はtryが必要になる
  • try!はエラーが絶対に発生しないぞ!という強い意志のもの実行する。do-catchが不要になる
  • try?はOptionalが返るようになる。do-catchは不要になる

rethrow

クロージャーがエラーを吐く場合はrethrowを使う。

struct SomeError: Error {}

 func rethorwingFunction(_ throwingClosure: () throws -> Void) rethrows {
     try throwingClosure()
 }

 do {
     try rethorwingFunction {
         throw SomeError()
     }
 } catch {
     error // SomeError
 }

ポイント

  • 普通のthrowと一緒な使い方.
  • クロージャがthrow投げるときに使う

fatalError,Never

func randomInt() -> Int {
  fatalError("未実装だぞ")
}


いわゆるアプリ終了系のエラー.`Never`は値を返さずそれ以降の処理を実行しない(ちなみにVoidは空のTupleを返す).

## `assert`,`assertionFailure`
いわゆるアサーション

```swift
func format(minute:Int, second: Int) -> String {
   assert(second < 60, "secondは60みまんで")
   return "〜〜"
}

func printSeason(month:Int) {
  swiftch month { 
   ..
   default:
     assersionFailure("呼ばれたらダメなやつ")
  }
}

ポイント

  • assertはリリース時には無効になる
  • 実行されたらアプリが終了する
  • assertionFailureは呼ばれること自体がNGなやつ
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
9
Help us understand the problem. What are the problem?