node
var spaceship: SKSpriteNode!
var bird = SKSpriteNode()
let player = SKSpriteNode(imageNamed: "girl")
var hearts: [SKSpriteNode] = []
______________________
toggle
var toggle:Bool = true
func toggleTest() {
if(toggle){
videoNode.play()
toggle = false;
}else{
videoNode.pause()
toggle = true;
}
_________________________
配列
var word: [String] = [] //空の要素
var namber = [String]()
var data = Array()
var hearts: [SKSpriteNode] = []
var possibleEnemies = ["ball", "hammer", "tv"]
var obstacles: [SKSpriteNode] = []
var items = [String]()
var teleport = [CGPoint]()
var scores: [Int] = [0, 0]
__________________
CGPoint
anchorPoint の初期値は
CGPoint(x: 0.5, y: 0.5)
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
ImageNode.anchorPoint = CGPoint(x: 0.5, y: 0.5)//center
ImageNode.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
let center = CGPoint(x: frame.midX, y: frame.midY)
label.text = "Hello World!"
label.position = CGPoint(x: self.frame.midX + 200, y: self.frame.midY + 450)
_________________________
SKLabelNode
var scoreLabel: SKLabelNode!
var score: Int = 0 {
didSet {
scoreLabel.text = "SCORE: \(score)"
}
}
class HelloLabel: SKLabelNode {
init(fontNamed: String) {
super.init(fontNamed: fontNamed)
self.text = "Hello, World!"
self.fontSize = 65;
self.position = CGPoint(x: 400, y: 500);
}
}
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
//let myLabel = SKLabelNode(fontNamed:"Chalkduster")
//myLabel.text = "Hello, World!";
//myLabel.fontSize = 65;
//myLabel.position = CGPoint(x: 400, y: 500);
let myLabel = HelloLabel(fontNamed: "Chalkduster")
self.addChild(myLabel)
}
}
func createScore() {
scoreLabel = SKLabelNode(fontNamed: "Optima-ExtraBlack")
scoreLabel.fontSize = 24
scoreLabel.position = CGPoint(x: frame.midX, y: frame.maxY - 60)
scoreLabel.text = "SCORE: 0"
scoreLabel.fontColor = SKColor.black
// scoreLabel.fontName = "Avenir"
// scoreLabel = SKLabelNode(text: "kaisu: 0kai")
addChild(scoreLabel)
}
________________________
Button(spritekit)
TappedNodes(参照)
//////////////////////
変数・定数 / データ型
// 定数は let
// 変数は var
let msg: String = "hello world"
// Int型で定数定義
let i: Int = 10
let i = 10
// Float Double
let d = 53.8
// String
let s = "hello"
// Bool true/false
let flag = true
var x = "five"
x = String(5)
演算子
// 数値
print(10 / 3) // 3
print(10.0 / 3) // 3.3333
print(10 % 3) // 1
var y = 10
//y = y + 5
y += 5
print(y) // 15
// 文字列
print("hello " + "world")
print("y is \(y)")
print("y2 is \(y * 2)")
// 論理値 true false
print(true && false) // false
print(true || false) // true
print(!true) // false
条件分岐(if / switch)
// if文
let score = 40
let result: "" // String
// 基本
if score > 80 {
result = "great"
} else if score > 60 {
result = "good"
} else {
result = "so so ..."
}
// 条件演算子
// 条件 ? A : B
result = score > 80 ? "great" : "so so ..."
// switch文
let num = 15
// 基本
switch num {
case 0:
print("zero")
case 1, 2, 3:
print("small")
case 4...6:
print("4/5/6")
case 7..<9:
print("7/8")
case let n where n > 20:
print("\(n) is huge!")
default:
// print("n.a.")
break
}
繰り返し(for / while)
// for 変数 in データの集合 { 処理 }
// break
// continue
for i in 0...5 {
if i == 3 {
// break
continue
}
print(i)
}
// while
var n = 10
while n < 3 {
print(n)
n += 1
}
//repeat {
// print(n)
// n += 1
//} while n < 3
配列
// 配列は全て中身が同じ型になる
// 可変長で、繰り返し処理も可能
// 基本
var scores: [Int] = [50, 40]
// 型省略
var scores = [50, 40]
// 取り出し
print(scores[0]) // 50
// 更新
scores[1] = 30
// その他
print(scores.count) // 2
print(scores.isEmpty) // false
// 空の配列
var names = [String]()
// 追加
names.append("田中")
names.append("鈴木")
names += ["佐藤"]
// forで取り出し
for name in names {
print(name)
}
集合(Set)
// 基本(setは重複無視される)
var winners: Set = [3, 5, 8, 8]
// 型の省略
var winners: Set = [3, 5, 8, 8]
// 取り出し
print(winners.contains(3))
// 追加
winners.insert(10)
// 削除
winners.remove(5)
// 空の集合
let s = Set()
print(s.isEmpty)
// 集合の演算
let a: Set = [1, 3, 5, 8]
let b: Set = [3, 5, 8, 9]
print(a.union(b)) // 和集合
print(a.intersection(b)) // 積集合
print(a.subtracting(b)) // 差集合
タプル
// タプルは、最初に定義したときに長さが固定(可変長ではない)
// また、型の場所も固定になる(最初の定義時に1番目が文字列型、二番目が数値型だったら、再代入する場合も1番目が文字列型、二番目が数値型でなければならず、違う場合エラーが出る)
var items = ("apple", 5)
print(items.0)
items.1 = 8
print(items)
let (product, amount) = items
print(product)
print(amount)
let (product, _) = items
print(product)
var items = (product: "apple", amount: 5)
print(items.product)
辞書(Dictionary)
// 基本
var sales: Dictionary<string, int=""> = ["a": 200, "b": 300]
// 型を省略
var sales = ["a": 200, "b": 300]
// 更新
sales["b"] = 500
// 辞書からの取り出しはオプショナル型を含む可能性があるためunwrap
print(sales["a"] ?? "n.a.")
// 値の追加
sales["c"] = 400
// countで数を取り出す
print(sales.count)
// タプルで分けて取り出す
for (key, value) in sales {
print("\(key): \(value)")
}
// 空の辞書
let d = [String: Int]()
print(d.isEmpty)
Optional型
// nilの可能性を含む型
// 値を取り出す場合はunwrapする必要がある
// 基本
let s: Optional = nil
// 省略形
let s: String? = nil
// unwrapその1
if s != nil {
print(s!) // unwrap
}
// unwrapその2 (Optional Binding)
if let value = s {
print(value)
}
// unwrapその3
print(s ?? "this is nil!")
inoutキーワード
// 関数の引数は基本は「定数」となる
// 引数で受けた変数に再代入したい場合はinoutキーワードを使う
func add10(x: inout Int) {
x = x + 10
print(x)
}
var i = 10
add10(x: &i) // 20
print(i) // 20(iの中身が再代入された値で保存される)
まとめ
Swiftはバージョンで互換性がなくなって過去のバージョンで作ってたアプリが壊れるらしい。
////////////////////////////////////////////////////////////////////////////
Class
基本
// クラスは「型」として扱う
// 頭は大文字
class User {
let name: String // propertyと呼ぶ
var score: Int // property
init() {
self.name = "me!"
self.score = 23
}
}
// 基本
let user: User = User()
// 省略形
let user = User() // instance
// アクセス・値の変更
print(user.name)
print(user.score)
user.score = 26
print(user.score)
イニシャライザ
// 初期化メソッドのこと
class User {
let name: String
var score: Int
// イニシャライザ使用時
init(_ name: String, _ score: Int) {
self.name = name
self.score = score
}
// 引数がなかった時(default設定)
init() {
self.name = "bob"
self.score = 30
}
}
//let tom = User(name: "tom", score: 23)
let tom = User("tom", 23)
print(tom.name)
print(tom.score)
let bob = User()
print(bob.name)
print(bob.score)
計算プロパティ(getとset)
// プロパティを動的に計算させることも可能
class User {
let name: String
var score: Int
// 計算プロパティ
var level: Int {
get {
return Int(self.score / 10)
// 自明の時はselfの省略可能
}
set {
// 渡された値をnewValueで受け取ることができる
if newValue >= 0 {
score = newValue * 10
}
}
}
// getのみの場合
// var level: Int {
// return Int(score / 10)
// }
init(_ name: String, _ score: Int) {
self.name = name
self.score = score
}
}
let tom = User("tom", 23)
// getが動く
print(tom.level) // 23/10 = 2
// setに対して値を渡す
tom.level = 5
// すると、scoreが書き換わる
print(tom.score) // 50
// マイナスの値は、newValue >= 0の条件より反応しない
tom.level = -3
// したがって、変化せず50のまま
print(tom.score) // 50
プロパティの値の監視(willSetとdidSet)
// willSetとdidSetでプロパティの値の変化を監視できる
class User {
let name: String
var score: Int {
// プロパティの値が変わる前の処理
willSet {
print("\(score) -> \(newValue)")
// newValueで変化後の値を取得可能
}
// プロパティの値が変わった後の処理
didSet {
print("Changed: \(score - oldValue)")
// newValueで変化後の値を取得可能
}
}
// プロパティが最初に初期化される時は
// willSetとdidSetは実行されない
init(_ name: String, _ score: Int) {
self.name = name
self.score = score
}
}
let tom = User("tom", 23)
tom.score = 53
tom.score = 40
メソッド作成
class User {
let name: String
var score: Int
init(_ name: String, _ score: Int) {
self.name = name
self.score = score
}
// method
func sayHi(_ msg: String) {
print("\(msg) \(name)")
}
}
let tom = User("tom", 23)
tom.sayHi("hola")
継承
class User {
let name: String
var score: Int
init(_ name: String, _ score: Int) {
self.name = name
self.score = score
}
func sayHi() {
print("hi \(name)")
}
// 頭にfinalをつけるとoverrideされない
}
class AdminUser: User {
func sayHello() {
print("hello \(name)")
}
// 親クラスメソッドの上書き
override func sayHi() {
print("[admin] hi \(name)")
}
}
let tom = User("tom", 23)
let bob = AdminUser("bob", 33)
print(bob.name)
print(bob.score)
bob.sayHi()
bob.sayHello()
型プロパティ、型メソッド
class User {
let name: String
var score: Int
// 頭にstaticで型プロパティ
static var count = 0
init(_ name: String, _ score: Int) {
self.name = name
self.score = score
// インスタンス化されるたびに、+1
User.count += 1
}
func sayHi() {
print("hi \(name)")
}
// override可能な型メソッドにする場合はstaticではなくclass func
class func getInfo() {
print("\(count) instances")
}
}
class AdminUser: User {
func sayHello() {
print("hello \(name)")
}
override func sayHi() {
print("[admin] hi \(name)")
}
override class func getInfo() {
print("[admin] \(count) instances")
}
}
User.getInfo() // 0
let tom = User("tom", 23)
User.getInfo() // 1
AdminUser.getInfo() // 1
let bob = AdminUser("bob", 33)
AdminUser.getInfo() // 2
型キャスト(as)
// as : キャストが成功すると保証されるときに使用(アップキャストなど)
// as! : 強制ダウンキャストの際に使用
// as? : ダウンキャストが成功するか分からない場合に使用(失敗すると戻り値はnil)
class User {
let name: String
init(_ name: String) {
self.name = name
}
}
class AdminUser: User {}
let tom = User("tom")
let bob = AdminUser("bob")
// User型の配列
// AdminUser型はUser型を継承していることをswiftが判別してくれていて
// エラー出ない
let users: [User] = [tom, bob]
for user in users {
// as?(型キャスト)
// あるクラスを、他のクラスに変換すること
// if let文と組み合わせて、
// AdminUserのみ名前を表示させている
// こっちは一旦User型のuserをAdminUser型に変えてみて、
// うまくいく場合はuにuserが代入される
if let u = user as? AdminUser {
print(u.name)
}
// こっちはまずuserがAdminUser型か確認している
// User型のuserをAdminUser型に変えて、
// 且つoptional型をunwrapする
if user is AdminUser {
let u = user as! AdminUser
print(u.name)
}
}
protocol
// クラスに対して「このプロパティやメソッドは絶対実装してね」という約束をさせるために利用する
// Protocolは継承と違って複数適合させることができる
// Protocol自体がProtocolを継承できる
protocol Printable {
// 読み込み
var type: String { get }
// 読み書き可能
var count: Int { get set }
func printout()
}
class User: Printable {
let type = "Laser"
var count = 0
let name: String
init(_ name: String) {
self.name = name
}
func printout() {
count += 1
print("\(type): \(count)")
}
}
let tom = User("tom")
tom.printout()
tom.printout()
tom.printout()
extension
// 既存の型に新しいプロパティやメソッドを追加できる仕組み
// String型の拡張
extension String {
var length: Int {
return self.characters.count
}
}
let msg = "hello"
// lengthが使用可能
print(msg.length)
// protocolとextensionを組み合わせる
protocol Printable {
func printout()
}
extension Printable {
func printout() {
print("now printing...")
}
}
// User型にprotocolを適用
class User: Printable {
let name: String
init(_ name: String) {
self.name = name
}
}
let tom = User("tom")
tom.printout() // now printing...
//////////////////////////////////////
https://whatsupguys.net/?p=2130
値型と参照型
// Int, Double, Array .. -> 値型
// Class -> 参照型
// 値型と参照型で再代入したときの挙動が異なる
// 値型の場合
var original = 10
var copy = original // originalの値そのもの
original = 20
print(original) // 20
print(copy) // 10
class User {
var name: String
init(_ name: String) {
self.name = name
}
}
// 参照型の場合
var original = User("tom")
var copy = original // originalが格納されている場所
original.name = "bob"
print(original.name) // "bob"
print(copy.name) // "bob"
構造体(struct)
// 構造体
// - クラスとほぼ同機能
// - 値型
// - 継承ができない
// - extension, protocolは使える
// 基本的に一回作ったら値が変わってほしくないようなデータに使用
//class User {
struct User {
var name: String
init(_ name: String) {
self.name = name
}
// 本来構造体では値の変更ができない
// 明示的にmutatingを用いると値の変更が可能
mutating func changeName() {
self.name = name.uppercased()
}
}
var original = User("tom")
var copy = original // copy: originalの値
original.name = "bob"
print(original.name) // bob
print(copy.name) // tom
列挙型(enum)
// 関連する値をまとめて型にする
// 列挙型は値型
// enumちょっとよくわからん、まだ勉強が必要
enum Direction {
case right
case left
}
var dir: Direction.right
switch (dir) {
case .right:
print("right")
case .left:
print("left")
}
enum Direction: Int {
case right = 1
case left = -1
}
print(Direction.right.rawValue)
ジェネリクス
// 汎用化されたデータ型
// TはTypeのT
//func getThree(x: Int) {
func getThree(x: T) {
print(x)
print(x)
print(x)
}
// Int型だけでなく、どの型が引数に与えられても対応できる
getThree(x: 5)
getThree(x: "hello")
getThree(x: 2.3)
subscript
// クラス、構造体、列挙型などにインデックスをつけられる
class Team {
var members = ["aaa", "bbb", "ccc"]
// インスタンスにインデックスが付与されていた時反応
subscript(index: Int) -> String {
get {
return members[index]
}
set {
members.insert(newValue, at: index)
}
}
}
var giants = Team()
print(giants[1]) // bbb
giants[3] = "ddd"
print(giants[3]) // ddd
guard文
// 異常処理をわかりやすく書くための仕組み
// if letで書く場合
func sayHi(_ msg: String?) {
if let s = msg {
print(s)
} else {
print("value not set!")
}
}
// early returnの場合
func sayHi(_ msg: String?) {
if msg == nil {
print("value not set!")
return
}
print(msg!)
}
// guardで書く場合
func sayHi(_ msg: String?) {
guard let s = msg else {
print("value not set!")
return
}
print(s)
}
sayHi(nil)
sayHi("hello")
例外処理
// 列挙型でエラーパターンを定義
enum LoginError: Error {
case emptyName
case shortName
}
class User {
let name: String
init(_ name: String) {
self.name = name
}
// 例外発生の可能性がある場合、throwsを使う
func login() throws {
guard name != "" else {
throw LoginError.emptyName
}
guard name.count > 5 else {
throw LoginError.shortName
}
print("login success")
}
}
let tom = User("tom")
let tom = User("takahashi")
let tom = User("")
// do catchでエラー表示
do {
try tom.login()
} catch LoginError.emptyName {
print("please enter your name")
} catch LoginError.shortName {
print("too short")
}
Optional Chaining
// オプショナル型のnilチェックをスッキリ書くためのもの
// 変数が nil だったら nil を、そうではなかったらその値を含む Optional 型を返す
// nilだった場合も、単に返り値がnilになるだけでエラーにならない
// 非オプショナル型の場合...
//class User {
// var name: String = ""
//}
//
//let user: User()
//user.name = "him"
//let s = user.name.uppercased()
//print(s)
// オプショナル型の場合
class User {
// optional宣言の省略型
var name: String? = ""
}
// optional宣言の省略型
var user: User?
user = User()
// Optional Chaining(後ろに?をつける)
user?.name = "him"
if let s = user?.name?.uppercased() {
print(s)
}
暗黙的 unwrap optional
// Implicitly Unwrapped Optional
// 宣言で「!」をつけることで、値を使う時にUnwrapしなくてもいいOptional型だと理解する
// 通常のoptional型定義(後ろに?)
//var msg: String?
// Implicitly Unwrapped Optional(後ろに!)
var msg: String!
msg = "hello"
// 本来ならunwrap処理が必要であるが、
//if msg != nil {
// print(msg!)
//}
// この場合はunwrap不要で利用できる
print(msg)
</string,>