search
LoginSignup
3

More than 3 years have passed since last update.

posted at

updated at

忘備録-Swiftの関数

趣味でIOSアプリ開発をかじっていた自分が、改めてSwiftを勉強し始めた際に、曖昧に理解していたところや知らなかったところをメモしています。

参考文献

この記事は以下の書籍の情報を参考にして執筆しました。

関数の概要

func 関数名(仮引数: 型) -> 型{
文…
}
関数内の処理で呼び出し元から値を使わない場合、「仮引数: 型」は記述しない。
関数から戻り値を返さない場合、「 -> 型」は記述しない。

returnの省略

関数本体がreturn1行だけの時はreturnを省略することができる。

func add(a: Int, b: Int) -> Int{
  return a+b
}
print(add(a:3, b:5))        //8
func add(a: Int, b: Int) -> Int{
  a+b
}
print(add(a:3, b:5))        //8

引数ラベルの指定

func 関数名(引数ラベル名 仮引数: 型)で引数ラベルを指定することができる。

func area(height h: Int, weight w: Int) -> Int{
  h * w
}
print(area(height: 3, weight: 5))    //15

引数ラベルの省略

引数ラベルの代わりに「 _ 」を使用することで引数ラベルを省略できる。

func add(_ a: Int, _ b: Int) -> Int{
  a+b
}
print(add(3, 5))    //8

inout引数

SwiftにはC言語のようなポインタ変数がない。代わりにinout引数を使うことで、呼び出し側の変数を変更できる。

func swap(_ a: inout Int, _ b: inout Int) {
  let t = a; a = b; b = t
}

inout引数を使用して関数を呼び出す際は「 & 」をつけて呼び出しを行う。

var x = 10
var y = 3
print(swap(&x, &y))
print("x = \(x) , y = \(y)")        //x = 3 , y = 10

引数ラベルを使ったオーバーロードの定義

引数ラベルで異なる引数を定義することで同名で別の関数を定義することができる。

func swap(_ a: inout Int, _ b: inout Int) {
  let t = a; a = b; b = t
}
func swap(little a: inout Int, great b: inout Int) {
  if b > a{
    let t = a; a = b; b = t
  }
}
var x = 10
var y = 3
print(swap(&x, &y))
print("x = \(x) , y = \(y)")
print(swap(little: &x, great: &y))      //x = 3 , y = 10
print("x = \(x) , y = \(y)")        //x = 10 , y = 3

関数の引数に規定値を設定する

仮引数に規定値を指定することができる。規定値を指定する場合、呼び出し時に省略することが可能。

func setSeparator(color: String = "Black", width: CGFloat){
    //線を追加する処理
}
//色はデフォルト値でいい
setSeparator(width: 200)
//色は赤がいい
setSeparator(color:"red", width: 200)

返り値を使わない場合を許す指定

次のようにBool型を返す関数があったとしても通常返り値を使いたくないのであれば関数定義の直前に@discardableResultをつけることでコンパイルできるようになり、帰り値を使わなくてもエラーにならない。

@discardableResult func hello(name: String) -> Bool{
    var b: Bool = false
    if name == ""{
      print("Hello NANASHIsan")
      b = false
    } else {
      print("Hello\(name)san")
      b = true

    }
    return b
  }
hello("hoge")

キーワード付きのタプル

タプル : 複数のデータを組みにしてまとめたもの。
要素を取り出す時は番号で位置を指名することができる。
タプルは同じ型を持つ変数に代入できる。

let book = ("hoge hoge book", 276)
print("\(book.0)のページ数\(book.1)")
let (title, page) = book
print("\(title)のページ数\(page)")

一部変数だけ取得することも可能

let book = ("hoge hoge book", 276)
let (title, _) = book
print("\(title)読んだ")

要素を取り出す時にキーワード指定で取り出すことができる。
キーワードのついたタプルは同じキーワードがついたタプルかキーワード指定のないタプル間でしか代入できない。
ただしキャストするとキーワード情報がリセットされるので代入できるようになる。

let book = (title: "hoge hoge book", page: 276)
print("\(book.title)のページ数\(book.page)")
let v1: (String, Int) = book
let v2: (title: String, page: Int) = book
let v3: (bookName: String, count: Int) = book   //エラー
let v4: (bookName: String, count: Int) = book as(String, Int)

演算子の定義

概要
・二項演算子
infix operator 演算子 : 優先度グループ名(省略可能)
・前置演算子
prefix operator 演算子
・後置演算子
postfix operator 演算子

Swiftでは自分で演算子を定義することができる。ただ、どのような演算子を定義するかによって定義方法が異なる。
(1)全く新しい演算子の定義。
(2)既存の演算子に別の使い方を定義。
(a)これまで単項演算子として使用されていたものに、二項演算氏の役割を定義。またはその逆。
(b)これまでとは違うデータ型(の組み合わせ)に対して適応可能にする。

(1),(2)-(a)の場合、演算子として使う記号と使い方(前置演算子/後置演算子/二項演算子)を定義する必要がある。
この宣言はどの関数の定義にも属さずトップレベルで行う必要がある。
(2)-(b)の場合、改めて宣言する必要がない。

二項演算子の定義

infix operator  : RangeFormationPrecedence

func (a: Int,b: Int) -> String {
  String(a) + String(b)
}
print(2019)    //2019

単項演算子の定義(前置演算子、後置演算子)

postfix operator %    //後置演算子を定義

postfix func % (n: Double) -> Double {
  n * 0.01
}
print(10250%)    //102.5

演算子として独自定義できない文字列

= , -> , . , // , /* , */ , ? ,
前置演算子として定義できない。
& , >
後置演算子として定義できない。
< , !

演算子として使える文字列

下記のASCEII文字列の記号
/ , - , + , ! , * , % , , | , ^ , ~
Unicode文字列の記号
→ , Δ , ★ , (etc…)
組み合わせとして使用できる記号
= , ? , ! , > , < , &
これらを1つまたは複数組み合わせて定義する。
また「.」から始まる場合のみ、「.」を使用可能。
優先度グループの定義

優先度グループの定義

優先度 : 1つの式に異なる演算子が複数あった場合に、どちらが先に解釈されるかを示します。
(記号例は一部抜粋。他にもあるので注意。)

グループ名 記号例
BitwiseShiftPrecedence << , &>>
MultiplicationPrecedence * , /
AdditionPrecedence + , - , ^
RangeFormationPrecedence ..<
CastingPrecedence is , as
NilCoalescingPrecedence ??
ComparisonPrecedence < , >=
LogicalConjunctionPrecedence &&
LogicalDisjunctionPrecedence ||
TernaryPrecedence con , ?
AssignmentPrecedence = , += , %=

演算子の優先度を独自に定義することもできる。

precedencegroup HogeGroup {
    associativity: none    //結合規則
    higherThan: LogicalDisjunctionPrecedence    //優先度
    lowerThan: LogicalConjunctionPrecedence    //優先度
    assignment: false    //代入演算子
}
infix operator .%% : HogeGroup
func .%% (a: Double , b: Double) -> String {
    String((a+b)*0.1)
}
print(3000 .%% 4400)

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
What you can do with signing up
3