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倍になる。 )
- 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した新しい配列を作る
- Shallow 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)