詳細! Swift iPhoneアプリ開発 入門ノート Swift 1.1+Xcode 6.1+iOS 8.1対応
- 作者: 大重美幸
- 出版社/メーカー: ソーテック社
- 発売日: 2014/12/13
- メディア: 単行本
- この商品を含むブログ (2件) を見る
最近Swiftの勉強をしていて、詳細!Swiftを読みながらメモを書いた。
他のSwift本と読み比べはしてないので比較は出来ないけど、サンプル数多いし説明もわかりやすいので良いと思う。
以下のメモはブログに公開はしてるけど、自分が後で見返す際に書いたメモなので、他の誰が見てもよくわからないと思う。
数値の3桁区切り
- 数字はアンダースコア付けれる(可読性向上)
- 122_100_100 は 122100100と評価される
タプル
- 復数の値を扱える。型がバラバラでも良い。
- 配列と似ているが、タプルは追加や削除したりなどは出来ない。
- 変数の上書きは可能
let product = ("Swift",2014,10.2) var guest:(String, String, Int) = ("ほしかわ","star",22) guest = ("star","hoshi",11) println(guest) println(guest.0) println(guest.1)
- jsonみたいな書き方もできるみたいだ
let tapleLabel = (price:100,tax:8) let seikyugaku = tapleLabel.price + tapleLabel.tax println(seikyugaku)
演算子
- trueとfalseのトグル
flower.hidden = !flower.hidden
- 代入演算子にはいろいろある
- /=, %=, &&=, ||=
条件分岐
- switchでタプル使うとき、変数として値を受け取れる
let size = (4,10) switch size{ case(0,0): println("0,0") case(5...10,5...10): println("規定サイズ") case(5...10,let height): println("高さ異常\(height)") case(let width,5...10): println("横異常\(width)") default: println("どっちも異常") }
- switch で where 使える
- 詳細swift p.67
for文
- for in で辞書型を扱うとき、いい感じに扱える
let pokemon = [1:"ふしぎだね",2:"ふしぎそう",3:"ふしぎばな",4:"ひとかげ"] for (k,v) in pokemon{ println(v) } for pk in pokemon.keys{ println(pk) } for pv in pokemon.values{ println(pv) }
- for文に名前を付けてcontinueとかbreak出来る
xloop:for x in 1...10{ yloop:for y in 1...10{ if(x < y){ print("\n") continue xloop } print((x,y)) } }
ストリング
- 文字を繰り返すとか出来る
let stars = String(count:10,repeatedValue:Character("☆")) println(stars)
配列
- 繰り返しの配列とか作れる
var zeroList = [Double](count:10,repeatedValue:0.0) println(zeroList)
- ソート
- sortは破壊的
- sortedは非破壊的
- 抽出
- filterってかけて便利っぽい
let fil = zeroList.filter {$0 >= 5} println(fil) let nums = [10,20,30,40,35] let num0to10 = filter(nums,{(num30:Int) -> Bool in return (num30 >= 20) && (num30 < 35) }) println(num0to10)
- すべての値で演算を行う
let plusOnes = nums.map{$0+1} println(plusOnes)
辞書
- 空の配列を作る
let sizeTable:[String:Any] = [:] println(sizeTable) let initDict = [String:Any]() println(initDict)
オプショナル
var count:Int? let value = 250 * (count ?? 2) println(value)
- オプショナルバインディング
var str:String? = "Swift" if let mes = str{ println(mes + "world") }else{ println("hello world") }
class Player { var magic:Magic? = Magic() } class Magic { var spell:String = "puipui" } --------- var user:Player = Player() var spell = user.magic?.spell as String! println(spell)
関数
- 可変長引数的なやつ
func sum(numbers:Double...) -> Double{ var total:Double = 0 for num in numbers{ total += num } return total } println(sum(1,2,3,4,3,3,4,3,3))
- 引数に初期値を設定する
- 引数3つあって、そのうち1つだけ初期値なしとかも出来るけど、呼ぶときはフォーマット合わせる必要ある。
func customer(who:String = "客") -> String{ return who + "様こんちは" } println(customer(who:"ほしかわ")) println(customer())
- 関数の引数は基本的にletだけど、varと明示すれば書き換えられる
func price(var yen:Int) -> Int{ let tax = 1.08 yen = Int(floor(Double(yen)*tax)) return yen } println(price(100))
- 外部引数名
- 関数を使うときの引数を指定させる
- 外部引数名と引数名が同じの場合、#つけるといける
func bmi(weight kg:Double, height cm:Double)->Double{ if cm == 0 {return -1} var result = kg/pow(cm*0.01,2) result = round(result*10)/10.0 return result } func kngk(#tnk:UInt,ks:UInt) -> UInt{ return tnk*ks } println(bmi(weight:55,height:170)) println(kngk(tnk:250,ks:3))
- 引数や戻り値が配列の関数
- Array
のように型を指定する
- Array
func arrayByInt(#array:Array<Int>, num:Int) -> Array<Int>{ var result = Array<Int>() for value in array{ result.append(value*num) } return result } println(arrayByInt(array:[1,2,5,6,4,6],num:3))
- 関数のオーバーロード
- 関数名同じでも引数違えば問題なし
func calc(#a:Int, b:Int) -> Int{ return a + b; } func calc(#c:Int, d:Int) -> Int{ return c + d; } func calc(#a:Int, b:Int, c:Int) -> Int{ return a + b + c; } println(calc(a:1,b:2)) println(calc(c:1,d:2)) println(calc(a:1,b:2,c:3))
- ジェネリックな関数
- 引数の方を
()のように指定することで、型を未定のまま定義できる
- 引数の方を
func makeArray<T>(items:T ...) -> [T]{ var array = [T]() for item in items { array += [item] } return array } println(makeArray(3,5,3,3,5,"fa")) println(makeArray("23213","ffa","lfajf"))
- 関数の引数を関数にする
- 引数の関数の引数の型とかもかく
- 引数なのか関数なのかわけがわからなくなってきた
- 型をたくさん書くのだるい
func helloUser(user:String) -> String { return("\(user)さん、はろー") } func command(someFunc:String -> String,user:String) -> String{ let msg = someFunc(user) return msg } println(command(helloUser,user:"hoshikawa"))
- returnで関数を返すことも出来る
- 戻り値の型をちゃんと書くこと、それ以外はJSと似てる
- なのでソースコードは書かない
クロージャ
クロージャを引数として受け取るmap関数を使う
// クロージャ let closureNum = [1,4,0,5,2,4] let array1 = map(closureNum, {(let v:Int) -> Int in return v * 2 }) println(array1)
- 型推論が適用されるので型宣言を省略出来る
- 戻し値の式だけでreturnも省略できる
let array3 = map(closureNum, {v in v * 2}) println(array1)
- クロージャの引数は$0,$1,$2と取得できる
let array4 = map(closureNum){$0 * 2} println(array4)
- クロージャを受け取る関数を作り、使う
//クロージャ func dicMap(var dic:Dictionary<String,Int>, closure:(String, Int) -> (String, Int)) -> Dictionary<String,Int>{ for (key,value) in dic{ let (theKey,newValue) = closure(key,value) dic[theKey] = newValue } return dic } // dicMapを使う let abcDic = ["a":3,"b":6,"c":1] let result = dicMap(abcDic){(key:String,value:Int)->(String,Int) in return (key,value*2) } println(result)
Class
- initもオーバーロード出来る
class MyClass{ let msg:String let name:String? init(msg:String = "hello"){ self.msg = msg } init(msg:String,name:String){ self.msg = msg self.name = name } func hello(){ var helloMsg:String if let user = name { helloMsg = user+"さん。"+msg } else{ helloMsg = msg } println(helloMsg) } } ---------------- let myObj = MyClass(msg:"MyClass") myObj.hello() let myObj2 = MyClass(msg:"MyClass",name:"starhoshi") myObj2.hello()
- convenience init
- initを呼ぶinitを作れる。引数をみると何が呼ばれるのか、違いがわかる
class MyClass{ let msg:String let name:String init(msg:String,name:String){ self.msg = msg self.name = name } convenience init(msg:String = "hello"){ self.init(msg:msg,name:"匿名") } func hello(){ var helloMsg = name + "さん。" + msg println(helloMsg) } } ----------------- let myObj = MyClass(msg:"hello!") myObj.hello() let myObj2 = MyClass(msg:"hello!",name:"starhoshi") myObj2.hello() let myObj3 = MyClass() myObj3.hello()
- クラスメンバ
- インスタンスメンバと違い、頭にclassとつける
- swift 1.1だと使えないようでエラーになる
- クラスメンバについて、参考になりそう
- 【Java】 staticって何? | 一番かんたんなJava入門
- クラスに属するのがstatic、インスタンスに属するのが非static
- 【Java】 staticって何? | 一番かんたんなJava入門
class MyGame{ class let version:String = "1.0.0" class var userCount:UInt= 3 }
- クラスメソッド
- クラスに対し実行する
class MyClass{ class func GoodMorning() -> String{ return "GoodMorning" } } ------------------- let myObj4 = MyClass.GoodMorning() println(myObj4)
- Computedプロパティ
- ↔Storedプロパティ
- Computedプロパティそのものは値を保持していない
- 参照に対してはget,設定に対してはsetメソッドを使う
- computedプロパティを使う側からすれば、Storedプロパティと区別はつかない
class MyClass{ var radius:Double = 1.0 var area:Double{ get{ return radius * radius * M_PI } set(menseki){ radius = sqrt(menseki / M_PI) } } } --------------- var myCircle = MyClass() println(myCircle.radius) println(myCircle.area) myCircle.area *= 2 println(myCircle.radius) println(myCircle.area)
- プロパティオブザーバー
- プロパティに値がセットされたことをwillSetとdidSetで監視できる
class MyClass{ init(){ level = 0 } var times = 0; var level:Int{ willSet{ if level != newValue{ println("\(level) -> \(newValue)") } } didSet{ if oldValue != level{ ++times println("\(times)回目の更新") } } } } ---------------- var thePlayer = MyClass() thePlayer.level = 10 thePlayer.level = 10 thePlayer.level = 15 //0 -> 10 //1回目の更新 //10 -> 15 //2回目の更新
- lazyプロパティ
- lazy var みたいにStoredプロパティにlazy付けうと遅延評価になる
- 参照されるまで初期化されない
class MyClass(){ lazy var home = HomeClass() func who(){ println(home.owner) } } class HomeClass{ var owner = "yoshiyuki oshige" } -------------------- var home = MyClass() home.who()
classここから下は長くなるためソースはなし
- アクセス権
- クラス・プロパティ・メソッドにはアクセス権を設定できる
- internal
- 他のファイルからでもアクセス可能(デフォルト)
- private
- 同一ファイル内でのみアクセス可能
- ptivare(set)とするとリードオンリーになる
- public
- どこからでもアクセス可能(一般には使用しない)
- メソッドのオーバーライド
- final - 継承やオーバーライドを禁止する
- final class Human{}
- final func method()
- プロトコル
- javaでいうinterface
- extension
- 既存のクラスを書き換えたり継承することなく機能を拡張できる
- Stringとかintも拡張出来る
- js のプロトタイプ拡張みたいな感じか
列挙型 enum
enum MensSize{ case S case M case L case XL } enum WomansSize{ case S,M,L,XL } func packing(size:WomansSize) -> String { var stuff:String switch size { case .S: stuff = ".S" case .M: stuff = ".M" case .L: stuff = ".L" case .XL: stuff = ".XL" } return stuff } ----------------- println(MensSize.L) println(WomansSize.S) var mySize = MensSize.M mySize = .S println(packing(.M))
- enumに値を定義する
- 普通にイコールでいける
- Intで最初だけ数値指定した場合、あとのは1ずつ増えていく
enum Direction:Int{ case forward = 1 case backword case right case left } ------------------- println(Direction.backword.rawValue)
- enumに関数を定義する
enum Prize:Int{ case Gold = 1,Silver,Bronze,Four,Five func description() -> String{ switch self{ case .Gold: return "優勝" case .Silver: return "準優勝" case .Bronze: return "じゅんじゅん優勝" case .Four, .Five: return "入賞" } } --------------------- let myRank = Prize.Bronze println(myRank.description()) }
enum Pattern { case Monotone(PColor) case Border(c1:PColor,c2:PColor) enum PColor:String{ case red = "red" case green = "green" case blue = "blue" } } ---------------------------- let shirt1 = Pattern.Border(c1: .red, c2: .green) switch shirt1 { case .Border(let c1, let c2): println(c1.rawValue,c2.rawValue) }
struct 構造体
クラスと同じような機能を持ち、書式もほぼ同じ。
だが継承をしないのでスーパークラスを設定する書式はない。
- structでは初期値設定できる
//初期値なし struct ColorBox{ var width:Int var height:Int var color:String } // 初期値有り struct WhiteBox{ var width:Int = 100 var height:Int = 100 var color:String = "white" } -------------------- var redBox = ColorBox(width: 100, height: 100, color: "red") var theBox = WhiteBox() println(theBox.width)
- classと同じくイニシャライザを作れる
- init()
- classは参照型だが、structは値型
- structはコピーを作成する
- 関数とかもclassと同じく作れる
- だが構造体自身のプロパティを変更する際に関数を使ってできない
- mutating をつける
- mutatingを付けたメソッド内でプロパティの変更を行う
struct Line{ var p1:Point var p2:Point mutating func move(#h:Int,v:Int){ p1.h += h p1.v += v p2.h += h p1.v += v } } ------------------------ theLine.move(h:50,v:20) let p1 = theLine.p1 let p2 = theLine.p2 println(p1.h,p1.v) println(p2.h,p2.v)
- subscript
- 構造体の要素に[]を使ってアクセスできる
- structa[1], structB["a",2]みたいにアクセスする
struct Stock { var name:String var data:[String:Int] = [:] init(name:String){ self.name = name } subscript(color:String,size:Double) -> Int{ get { let key = color + size.description if let value = data[key]{ return value }else{ return 0 } } set{ let key = color + size.description data[key] = newValue } } } ------------------------------ var addixStock = Stock(name: "addix") addixStock["green",24.5] = 4 addixStock["green",24.0] = 1 addixStock["green",24.5] = 7 addixStock["green",24.0] += 1 println(addixStock["green",24.0]) println(addixStock["green",24.5])