代々木で働く19歳エンジニアのブログ

思ったこととか、技術的なこと書きます。

Swift ざっくり文法 (2)

  • Tuple ( タプル )
let product: (String, Int) = ("Swift", 2015)
let kingaku = (1000, 80) // 型推論で(Int, Int)に決まる
kingaku = (1060,  "hoge") // error: cannot call value of non-function type '(Int, Int)'
let data = (1000, 80)
let (price, _) = data
print(price)

不要な値は、_ で無視できる。

let data = (1000, 80)
print(data.0)

indexでaccess

let kingaku = (price: 1000, tax: 80)
let seikyuugaku = kingaku.price + kingaku.tax
print(seikyuugaku)

ラベル付け

  • Range

    • ..< 終了値を含まない
    • ... 終了値を含む
  • Bitwise Operators

    • 2進数 接頭辞に 0b
    • 16進数 接頭辞に 0x

    • Bit Shift

      • 指定した方向に桁をシフトする演算( 10進数の数値を左を一桁シフトすると値が10倍になるように2進数の値を左へ1桁シフトすると値が2倍になる。 )
let v: UInt8 = 0b00000101
let v2 = v<<1
print(v, v2) // 5, 10
  • Bitwise operation
演算式 説明
a & b ビット積、各桁を比較し、両方の桁が1ならば1
a b | ビット和、各桁を比較し、どちらかの桁が1ならば1
a ^ b 排他的ビット和、各桁を比較し、片方が1の桁だけ1
~a ビット否定、各桁の1と0を反転

16進数#40E0D0 からビット積とビットシフトを使って、RGBを取り出して、0~255 の値に変換し、さらに255 で割って0~1にしてビューの背景色に指定

    let RGB: UInt32 = 0x40E0D0 // turquoise(64, 224, 208)
    let red = (RGB & 0xFF0000) >> 16 // 上位二桁
    let green = (RGB & 0x00FF00) >> 16 // 中央二桁
    let blue = RGB & 0x0000FF // 下二桁
    
    let R = CGFloat(red)/255
    let G = CGFloat(green)/255
    let B = CGFloat(blue)/255
    view.backgroundColor = UIColor(red: R, green: G, blue: B, alpha: 1)

ビット否定

let v: UInt8 = 0b00001010
let v2 = ~v
print(v, v2) //10 245
  • if statementでは以下のような書き方が可能
- if ((sugaku>=40) && (eigo>=60) && ((suugaku+eigo)>=120)) {
+ if sugaku>=40, eigo>=60, (suugaku+eigo)>=120 {
  • Switch statement
    • swiftのswitch statementは、breakがなくても抜けてくれる。
    • 意図的に処理を次のcase文に渡したい場合は、fallthrough キーワードを書く。

    • value binding

let size = (4, 10)
switch size {
    case (0, 0):
        print("hoge")
    case (5...10, 5...10):
        print("bar")
    case (5...10, let height): //
        print("height:" + "\(height)")
    case (let width, 5...10):
        print("width:" + "\(width)")
    default:
        print("foo")
}

where で、値の振り分けに条件式を使えるようになる。

let size = (45, 40, 100)
switch size {
    case let (width, height, _) where (width>=60) || (height>=60):
        print("hoge")
    case let (_, _, weight) where (weight>=80):
        print("bar")
default:
    print("foo")
}

caseに当てはまらない値があり得る場合には、最後のdefaultは必ず必要だが、caseに当てはまらない値がない場合はdefaultを省略可能

let aPoint = (50, 100)
switch aPoint {
    case (0, 0):
        print("中心点")
    case (0, _):
        print("x軸上の点")
    case (_, 0): //
        print("y軸上の点")
    case (x, y):
        print("点(\(x), \(y))")
}
  • 単に処理を任意の回数繰り返したい時( rubyでいうところの、timesみたいな感じ )
for _ in 1...15 {
    let num = arc4random_uniform(100)
    print(num, terminator:  ",")
}
  • for-in でstringから一文字ずつ取り出す
let message = "ありがとう"
for char in message {
    print(char)
}
// あ
// り
// が
// と
// う
  • 飛び飛びで繰り返す for-in stride()
for num in stride(from: 10, to: 30, by: 3) {
    print(num, terminator: ",")
}
// 10, 13, 16, 19, 22, 25, 28
  • 他の言語で言うところのdo-while は、swiftだとrepeat-while
  • loop ( for-in, while, repeat-while ) には、labelが付けられる
xloop: for x in 0...3 {
    yloop: for y in 0...3 {
        if (x<y) {
            print("------")
            continue xloop // yloopを中断して、xloopに抜ける
        }
        print((x, y))
    }
}
let vlist:Array = [[4, 2], [5], [9, 8, 10], [6, 8, -9], [4, 2], [9, 3]]
outloop: for alist in vlist {
    inloop: for v in alist {
        if v<0 {
            print(alist)
            break outloop // inloop だけでなく、outloopも中断する。
        }
    }
}
  • 複数行のString literal ( swift4から )
"""
swift4
swift3
swift4
"""
  • Array
let colors:[String] = ["red", "blue", "green"]
let hoge:[Any] = ["ed", "bl", 3]
var numList:Array<Int> = [12, 34, 56, 79, 59]
var resultList:Array<Bool>
resultList = [true, false, true, false]

型推論

var stringList = ["foo", "bar", "baz"]
// stringList は、型推論で[String]に設定されているため、それ以外の型を入れようとするとエラー
stringList = [3, 4, 6] // error: cannot convert value of type 'Int' to expected element type 'String'

空のArray

var resultList:Array<Bool>
resultList = []
var resultList = [Bool]()
var resultList = Array<Double>()

Repeating

var stars = String(repeating: "★", count: 7) // "★★★★★★★"
var resultList = Array<Bool>(repeating: true, count: 5) // [true, true, true, true, true]

配列を別の変数に代入すると、変数には配列の参照ではなく、コピー(複製)が作られて入る。

var array1 = [1, 2, 3]
let array2 = array1
// ここまではシャローコピー
array1[0] = 99
// ここでディープコピー
print("array \(array1)")
print("array \(array2)")
  • Copyの種類

    • Shallow Copy
      • 元の配列の参照をコピーしただけで実際には同じ配列を指した別名の配列を作る
    • Deep copy
      • 同じ値をもった完全に新しい別の配列を作る
    • Lazy copy in Swift
      • 配列を一旦Shallow Copyして、配列の要素や値を変更しようとした時点で自動的にDeep copyした新しい配列を作る
  • Set

    • 配列と違ってSetは同じ値を重複して持つことができず、値には順番がない。
let colorSet:Set<String> = ["red", "green", "blue", "green"]
print(colorSet) // ["green", "red", "blue"]
print(type(of: colorSet)) // Set<String>

Array -> Set, Set -> Array

var colorArray = ["red", "green", "blue", "green"]
print(colorArray, type(of: colorArray)) // ["red", "green", "blue", "green"] Array<String>
let colorSet = Set(colorArray)
colorArray = Array(colorSet)
print(colorSet, type(of: colorSet)) // ["blue", "green", "red"] Set<String>
print(colorArray, type(of: colorArray)) // ["blue", "green", "red"] Array<String>
  • 空のSet
var numSet:Set<Int> = []
  • Setに値を追加しても、重複していれば、同じ値は入らない。
var numSet:Set<Int> = []
numSet.insert(3)
numSet.insert(5)
numSet.insert(7)
numSet.insert(9)
numSet.insert(5)
print(numSet) // [5, 7, 3, 9]
  • Closure
let ageArray = [21, 30, 28, 35, 45, 52, 33]
let age30to39 = ageArray.filter({(age: Int) -> Bool in
    return (age>=30)&&(age<40)
})
print(age30to39)
  • dictionary
    • キーは、全てが同じ型で重複しない一意なものでないといけない。
let sizeTable = ["S": 47, "M": 52, "L": 55]
let sizeTable:[String:Int] = ["S": 47, "M": 52, "L": 55]
let sizeTable:Dictionary<String, Int> = ["S": 47, "M": 52, "L": 55]

空のdictionary

let sizeTable:[String:Int] = [:]
let sizeTable = [String:Int]()
let sizeTable = Dictionary<String, Int>()

TupleからDictionaryを作る

let a = ("A", 1)
let b = ("B", 2)
let c = ("C", 3)
let abcDic = Dictionary(dictionaryLiteral: a, b, c)
print(abcDic)

reference from

https://www.amazon.co.jp/dp/4800711843