• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

Spritekit

My WordPress site

  • Top
  • SpriteKitBase
    • Collision
    • Enumerated
    • Shooting
    • Breakout
    • Physics1
      • physics4
      • physics3
      • Physics2
  • SwiftUI&SpriteKit
    • TabScroll
    • LocalWebView
      • Counter
      • StateObject
      • Button
      • SceneMove
    • Swift Learning
  • Photo Gallery
    • Photo Galler 2
    • Photo Gallery 3
    • リンク
      • プロフィール
      • p5.play test

kyougif

SceneMove

04/10/2022 by kyougif


GameScene

import SpriteKit
import GameplayKit
import SwiftUI

class GameScene: SKScene, SKPhysicsContactDelegate, ObservableObject {  

    @Published var gameScore = 0
        override func didMove(to view: SKView) {
        backgroundColor = .yellow
        physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
        ball()
     //   addScore()
    }
    func ball() {
           let ball = SKShapeNode(circleOfRadius: 50)
           ball.position = CGPoint(x: 100, y: 100)
           ball.fillColor = .blue
           self.addChild(ball)
       }

    let removeLabel = SKAction.sequence([SKAction.fadeIn(withDuration: 0.3),
    SKAction.wait(forDuration: 0.8), SKAction.fadeOut(withDuration: 0.3)])

    override func sceneDidLoad() {
        super.sceneDidLoad()
    }
   func addScore(){
        if gameScore < 10 {
            gameScore += 2          
        } else {
            gameScore += 4         
        }
    }    
}

/////////////
GameScene2

import SpriteKit
import GameplayKit

class GameScene2: SKScene {
    override func didMove(to view: SKView) {
        backgroundColor = .blue
        physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
    }
    override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        let location = touch.location(in: self)
        let box = SKSpriteNode(color: SKColor.red, size: CGSize(width: 40, height: 40))
        box.position = location
        box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 40, height: 40))
        addChild(box)
    }
}
/////////////////////
ContentView

import SwiftUI
import SpriteKit

struct ContentView: View {
@State var switcher = false
    @StateObject var gameScene: GameScene = GameScene() // <<: Here 3

var scene: SKScene {
    let scene = GameScene()
       scene.size = CGSize(width: 216, height: 216)
       scene.scaleMode = .fill
    //    scene.backgroundColor = .yellow
       return scene
}
var scene2: SKScene {
    let scene2 = GameScene2()
       scene2.size = CGSize(width: 216, height: 216)
       scene2.scaleMode = .fill
       return scene2
}

var body: some View {    
 //   Text("Score: \(gameScene.gameScore)") // <<: Here 4
      //       .onTapGesture {
     //            gameScene.addScore()  // <<: Here 5
    //         }
    Button(action: {
        gameScene.addScore()
         }, label: {
             Text("Score: \(gameScene.gameScore)")
         })
  if switcher {
    SpriteView(scene: scene)
        .frame(width: 256, height: 256)
        .ignoresSafeArea()
        .background(Color.red)
        .onAppear {
          scene2.isPaused = true
        }
        .onDisappear {
          scene2.isPaused = false
        }
        
  } else {
    SpriteView(scene: scene2)
        .frame(width: 256, height: 256)
        .ignoresSafeArea()
        .background(Color.blue)
        .onAppear {
          scene.isPaused = true      
        }
        .onDisappear {
          scene.isPaused = false
        }  
  }
  Button {
    withAnimation(.easeInOut(duration: 1.0)) {
      switcher.toggle()
    }
  } label: {
    Text("SceneMove")
  }
}
}

Filed Under: Programming, spritekit, swiftui

Counter

04/03/2022 by kyougif


import SwiftUI
import SpriteKit

struct ContentView: View {
@ObservedObject var counter = Counter()
var scene: SKScene {
let scene = GameScene()
scene.counter = counter
scene.size = CGSize(width: 300, height: 400)
scene.scaleMode = .fill
return scene
}
var body: some View {
VStack{
SpriteView(scene: scene)
.frame(width: 300, height: 400)
.ignoresSafeArea()
//   Button{
//  counter.add(count: 1)
//     counter.reset()
//   } label: {
//       Text("reset to count")
//    }
Text("New count = \(counter.count)")
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
/////////////////////////////////
Counter.swift

import SwiftUI
class Counter: ObservableObject {
@Published var count : Int = 0
func add(count: Int) {
    self.count += count
 //   print("Add \(count); new total: \(self.count)")
 }
 func reset() { count = 0 }
}
//////////////////////////
GameScene.swift

import SwiftUI
import SpriteKit
class GameScene: SKScene {
    var counter : Counter?
    var count = 0   
 override func didMove(to view: SKView) {
        physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
}
override func touchesBegan(_ touches: Set, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    let location = touch.location(in: self)
    let box = SKSpriteNode(color: SKColor.red, size: CGSize(width: 50, height: 50))
    box.position = location
    box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 50, height: 50))
        self.addChild(box)
    // score += 1
    //  counter.add(count: 1)
        counter?.add(count: 1)
    }
}

Filed Under: Programming, spritekit, swiftui

StateObject

04/02/2022 by kyougif

@StateObjectと@ObservedObjectの違い
StateObjectCounterは親Viewのcounterが更新されても値を保持しているのに対し、
OvservedObjectCounterは親Viewの値更新に伴い値が初期化されている。
ライフサイクルが異なる。
@ObservedObjectは親Viewが再描画される度(= 親Viewのプロパティが更新される度)に更新され、保持するViewが再描画される。
counter (親View)
StateObjectCounter (子View)
OvservedObjectCounter (子View)


import SwiftUI


struct ContentView: View {
@State var counter = 0
var body: some View {
VStack(alignment: .leading, spacing: 30) {
HStack {
Text("counter: \(counter)")
Button("count up") {
counter += 1
}
}
StateObjectCounter()
ObservedObjectCounter()
}
}
}

final class Counter: ObservableObject {
@Published var number = 0
func increment() { number += 1 }
func reset() { number = 0 }
}

struct StateObjectCounter: View {
@StateObject private var counter = Counter()
var body: some View {
HStack {
Text("StateObject: \(counter.number)")
Button("count up") {
counter.number += 1
}
Button("Reset") {
self.counter.reset()
}
}
}
}

struct ObservedObjectCounter: View {
@ObservedObject private var counter = Counter()

var body: some View {
HStack {
Text("OvservedObject: \(counter.number)")
Button("count up") {
counter.number += 1
}
}
}
}

Filed Under: Programming, swiftui

SwiftUI&SpriteKit

04/02/2022 by kyougif


ContentView.swift

import SwiftUI
import SpriteKit
struct ContentView: View {
    var scene: SKScene {
        let scene = GameScene()
        scene.size = CGSize(width: 300, height: 400)
        scene.scaleMode = .fill
        return scene
    }

    var body: some View {
        SpriteView(scene: scene)
            .frame(width: 300, height: 400)
            .ignoresSafeArea()
    }
}
/*
struct ContentView: View {
let width = UIScreen.main.bounds.size.width
let height = UIScreen.main.bounds.size.height

var body: some View {
let scene = GameScene()
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
scene.scaleMode = .resizeFill
return SpriteView(scene: scene)
.frame(width: width, height: height)
.edgesIgnoringSafeArea(.all)
}
}
*/
/////////////////////
GameScene.swift

import SpriteKit
import GameplayKit
class GameScene: SKScene {
let width = UIScreen.main.bounds.size.width
let height = UIScreen.main.bounds.size.height
var shapeNode = SKShapeNode()
override func didMove(to view: SKView) {
backgroundColor = .blue
let rect = CGRect(x: -1 * width / 2,
y: -1 * height / 2,
width: width,
height: height);
self.physicsBody = SKPhysicsBody(edgeLoopFrom: rect)
physicsWorld.gravity = CGVector(dx: 0.0, dy: -1.0)
print("frame what?")
print(frame)
// 落下するボール
shapeNode = SKShapeNode(circleOfRadius: 50)
shapeNode.position = CGPoint(x: 0,
y: 150)
shapeNode.fillColor = .white
shapeNode.strokeColor = .blue
shapeNode.physicsBody = SKPhysicsBody(circleOfRadius: shapeNode.frame.width / 2)
shapeNode.physicsBody?.isDynamic = true
shapeNode.physicsBody?.linearDamping = 0.1
shapeNode.physicsBody?.restitution = 0.8
addChild(shapeNode)
// 動かないボール
let shapeNode3 = SKShapeNode(circleOfRadius: 50)
shapeNode3.position = CGPoint(x: 40, y: -90)
shapeNode3.fillColor = .red
shapeNode3.strokeColor = .red
shapeNode3.physicsBody = SKPhysicsBody(circleOfRadius: shapeNode.frame.width / 2)
shapeNode3.physicsBody?.isDynamic = false
shapeNode3.physicsBody?.affectedByGravity = false
addChild(shapeNode3)
}
override func touchesBegan(_ touches: Set, with event: UIEvent?) {
shapeNode.physicsBody?.applyImpulse(CGVector(
dx: Double(arc4random_uniform(200)) - 100.0,
dy: Double(arc4random_uniform(200)) - 100.0))
}
override func touchesMoved(_ touches: Set, with event: UIEvent?) {
}
}

Filed Under: Programming, swiftui

SpriteKitBase

04/02/2022 by kyougif


ContentView.swift

import SwiftUI
import SpriteKit
struct ContentView: View {
let screenWidth  = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
var scene: SKScene {
let scene = GameScene()
scene.size = CGSize(width: screenWidth, height: screenHeight)
scene.scaleMode = .fill
return scene
}

var body: some View {
SpriteView(scene: scene)
.frame(width: screenWidth, height: screenHeight)
.ignoresSafeArea()
}
}
///////////////////////////
GameScene.swift

import SpriteKit
import GameplayKit
class GameScene: SKScene {
override func didMove(to view: SKView) {
backgroundColor = .yellow
physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
}
func touchDown(atPoint pos : CGPoint) {      
 }
func touchMoved(toPoint pos : CGPoint) {       
}    
func touchUp(atPoint pos : CGPoint) {   
}
override func touchesBegan(_ touches: Set, with event: UIEvent?) {
guard let touch = touches.first else { return }
let location = touch.location(in: self)
let box = SKSpriteNode(color: SKColor.red, size: CGSize(width: 50, height: 50))
box.position = location
box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 50, height: 50))
addChild(box)
}
override func touchesMoved(_ touches: Set, with event: UIEvent?) {      
}
override func touchesEnded(_ touches: Set, with event: UIEvent?) {
}    
override func touchesCancelled(_ touches: Set, with event: UIEvent?) {
}  
override func update(_ currentTime: TimeInterval) {
 }
}

Filed Under: Programming, spritekit, swiftui

Swift Learning

09/13/2014 by kyougif


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,>

Filed Under: Programming Tagged With: swift

  • « Go to Previous Page
  • Go to page 1
  • Interim pages omitted …
  • Go to page 3
  • Go to page 4
  • Go to page 5
  • Go to page 6
  • Go to Next Page »

Primary Sidebar

最近の投稿

  • ObservableObj
  • SideMenu
  • TabScroll
  • Text
  • TappedNodes
  • Collision2
  • CoreMotion
  • Collision
  • Timer
  • Enumerated
  • Random
  • SwiftUI-List
  • Shooting
  • Sound
  • Camera
  • SpriteSheet
  • SKPhysics42
  • physics4
  • physics3
  • Physics2

アーカイブ

  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2014年9月
  • 2014年5月

カテゴリー

  • Programming
  • spritekit
  • swiftui

固定ページ

  • Home
  • p5.play test
  • Photo Galler 2
  • Photo Gallery
  • Photo Gallery 3
  • Top
  • プロフィール
  • リンク

Copyright © 2026 · Genesis-child on Genesis Framework · WordPress · Log in