[Swift🦩] #22 ν”„λ‘œν† μ½œ ⭐️⭐️

λ˜μƒΒ·2022λ…„ 4μ›” 21일
0

iOS

λͺ©λ‘ 보기
38/47
post-thumbnail
  • ν•„μš”ν•œ λ³€μˆ˜, ν•¨μˆ˜λ₯Ό μ •μ˜λ§Œ ν•˜κ³ ,
  • 클래슀, ꡬ쑰체, μ—΄κ±°ν˜• μ—μ„œ μ±„νƒν•΄μ„œ κ΅¬ν˜„
  • ν”„λ‘œν† μ½œμ˜ μš”κ΅¬μ‚¬ν•­μ„ λͺ¨λ‘ κ΅¬ν˜„ν•˜λ©΄ ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ ν•œλ‹€κ³  함.

1. ν”„λ‘œν† μ½œ 문법

protocol SomeProtocol: Hashable, Codable { // λ‹€λ₯Έ ν”„λ‘œν† μ½œ 채택 κ°€λŠ₯.
    // μš”κ΅¬μ‚¬ν•­ μ •μ˜
}

class SomeClass: SomeSuperClass, Hashable, Codable {
    // 상속이 λ¨Όμ €, ν”„λ‘œν† μ½œ 채택이 λ‚˜μ€‘μ—.
}

2. Property

  • μΈμŠ€ν„΄μŠ€ ν”„λ‘œνΌν‹°, νƒ€μž… ν”„λ‘œνΌν‹°λ₯Ό λͺ¨λ‘ μš”κ΅¬μ‚¬ν•­μœΌλ‘œ 넣을 수 μžˆλ‹€.
  • 이름과 νƒ€μž…, gettable, settable만 지정
  • 계산 ν”„λ‘œνΌν‹°μΈμ§€ μ €μž₯ ν”„λ‘œνΌν‹°μΈμ§€λŠ” 지정 X
protocol SomeProtocol {
    var mustBeSettable: Int { get set } // 무쑰건 set 이 κ°€λŠ₯해야함.
    var doesNotNeedToBeSettable: Int { get } // set 은 κ°€λŠ₯ν• μˆ˜λ„? μ•„λ‹μˆ˜λ„?
    static var someTypeProperty: Int { get set }
}

λ‹€λ₯Έ λ³€μˆ˜λ₯Ό 더 κ΅¬ν˜„ν•˜λŠ” 것은 상관 μ—†μœΌλ‚˜, ν”„λ‘œν† μ½œμ— μš”κ΅¬λ˜λŠ” λ³€μˆ˜λŠ” λͺ¨λ‘ κ΅¬ν˜„ν•΄μ•Όν•œλ‹€.


3. Method

  • μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ, νƒ€μž… λ©”μ„œλ“œ κ°€λŠ₯.
  • 이름, 인자, λ°˜ν™˜κ°’λ§Œ λ“€μ–΄κ°„λ‹€.
  • μ€‘κ΄„ν˜Έ, λ©”μ„œλ“œ λ°”λ””λŠ” μ—†μŒ
protocol SomeProtocol {
    static func someTypeMethod()
}

protocol RandomNumberGenerator {
    func random() -> Double
}

class LinearCongruentialGenerator: RandomNumberGenerator {
    var lastRandom = 42.0
    let m = 139968.0
    let a = 3877.0
    let c = 29573.0
    func random() -> Double {
        lastRandom = ((lastRandom * a + c)
            .truncatingRemainder(dividingBy:m))
        return lastRandom / m
    }
}
let generator = LinearCongruentialGenerator()
print("Here's a random number: \(generator.random())")
print("And another one: \(generator.random())")

4. mutating

  • λ©”μ„œλ“œκ°€ μ†ν•œ μΈμŠ€ν„΄μŠ€λ₯Ό λ³€κ²½ν•΄μ•Ό ν•˜λŠ” κ²½μš°κ°€ 있음.
  • mutating ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©.
protocol Togglable {
    mutating func toggle()
}

enum OnOffSwitch: Togglable {
    case off, on
    mutating func toggle() {
        switch self {
        case .off:
            self = .on
        case .on:
            self = .off
        }
    }
}
var lightSwitch = OnOffSwitch.off
lightSwitch.toggle() // .on
  • mutating ν‚€μ›Œλ“œμ˜ 경우, κ°’ νƒ€μž…μ—μ„œλ§Œ κ°€λŠ₯. class νƒ€μž…μ—μ„  쓰지 μ•ŠμŒ.
  • κ·Έλž˜μ„œ protocol 내뢀에 mutating func κ°€ μžˆλŠ”λ° κ·Έ protocol 을 class μ—μ„œ μ±„νƒν•˜κ²Œ 되면 mutating ν‚€μ›Œλ“œλ₯Ό μž‘μ„±ν•˜μ§€ μ•Šμ•„λ„ 됨.

5. init

  • ν”„λ‘œν† μ½œμ€ init 도 μš”κ΅¬ κ°€λŠ₯ν•˜λ‹€.
protocol SomeProtocol {
    init(someParameter: Int)
}

ν”„λ‘œν† μ½œ λ‚΄ init 을 ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„ν•˜κΈ°

  • ν”„λ‘œν† μ½œ 내에 μžˆλŠ” init 을 κ΅¬ν˜„ν•  λ•ŒλŠ”
  • required ν‚€μ›Œλ“œλ₯Ό λΆ™μ—¬μ€˜μ•Ό ν•œλ‹€.
class SomeClass: SomeProtocol {
    required init(someParameter: Int) {
        // initializer implementation goes here
    }
}
  • λ§Œμ•½ 상속받은 μƒμœ„ ν΄λž˜μŠ€μ—λ„ ν•΄λ‹Ή init 이 있고,
  • μ±„νƒν•œ ν”„λ‘œν† μ½œμ—λ„ ν•΄λ‹Ή init 이 μžˆλ‹€λ©΄?
  • required override init 으둜 같이 μ“°λ©΄ λœλ‹€.
protocol SomeProtocol {
    init()
}

class SomeSuperClass {
    init() {
        // initializer implementation goes here
    }
}

class SomeSubClass: SomeSuperClass, SomeProtocol {
    // "required" from SomeProtocol conformance; "override" from SomeSuperClass
    required override init() {
        // initializer implementation goes here
    }
}

failable init in protocol

  • ν”„λ‘œν† μ½œμ— failable init 이 μžˆλ‹€λ©΄??
  • ν•΄λ‹Ή init 을 κ΅¬ν˜„λΆ€μ—μ„œ init 으둜 κ΅¬ν˜„ν•΄λ„, init? 으둜 κ΅¬ν˜„ν•΄λ„ μ‚¬μš©ν•  수 μžˆλ‹€.

6. νƒ€μž…μœΌλ‘œμ„œ Protocol

  • ν”„λ‘œν† μ½œμ€ κΈ°λŠ₯을 κ΅¬ν˜„ν•˜μ§€ μ•ŠλŠ”λ‹€.
  • ν•˜μ§€λ§Œ? νƒ€μž…μœΌλ‘œ μ‚¬μš©ν•  μˆ˜κ°€ μžˆλŠ”λ°...
  • ν•΄λ‹Ή ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λŠ” μ–΄λ–€ νƒ€μž… μ΄λΌλŠ” 뜻.
  • νŒŒλΌλ―Έν„°, λ°˜ν™˜ / μƒμˆ˜, λ³€μˆ˜, ν”„λ‘œνΌν‹°μ˜ νƒ€μž… / λ°°μ—΄, λ”•μ…”λ„ˆλ¦¬, μ»¨ν…Œμ΄λ„ˆμ˜ ν•­λͺ© νƒ€μž…μœΌλ‘œ μ‚¬μš© κ°€λŠ₯.
class Dice {
    let sides: Int
    let generator: RandomNumberGenerator
    // generator κ°€ RandomNumberGenerator λΌλŠ” νƒ€μž…μ„ μ±„νƒν•˜λŠ” μ–΄λ–€ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€μž„.
    // λ‹€μš΄ μΊμŠ€νŒ…μœΌλ‘œ κΈ°μ‘΄ νƒ€μž…μœΌλ‘œ μ‚¬μš© κ°€λŠ₯.
    init(sides: Int, generator: RandomNumberGenerator) 
        self.sides = sides
        self.generator = generator
    }
    func roll() -> Int {
        return Int(generator.random() * Double(sides)) + 1
    }
}

var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
for _ in 1...5 {
    print("Random dice roll is \(d6.roll())")
}



7. Delegation ⭐️⭐️

  • ν΄λž˜μŠ€λ‚˜ ꡬ쑰체가 μ±…μž„μ˜ 일뢀λ₯Ό λ‹€λ₯Έ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€μ—κ²Œ λ„˜κ²¨μ£Όκ±°λ‚˜ μœ„μž„ν•˜λŠ” λ””μžμΈ νŒ¨ν„΄.
  • μœ„μž„ν•˜λŠ” μž‘μ—…μ„ μΊ‘μŠν™”ν•˜λŠ” ν”„λ‘œν† μ½œμ„ μ •μ˜ν•˜κ³ , μœ„μž„ λ°›λŠ” 것이 κ·Έ ν”„λ‘œν† μ½œμ„ κ΅¬ν˜„.
  • νŠΉμ • μž‘μ—…μ— μ‘λ‹΅ν•˜κ±°λ‚˜ / ν•΄λ‹Ή μ†ŒμŠ€μ˜ κΈ°λ³Έ νƒ€μž…μ„ μ•Œ ν•„μš” 없이 μ™ΈλΆ€ μ†ŒμŠ€μ—μ„œ 데이터λ₯Ό κ²€μƒ‰ν•˜λŠ”λ° μ‚¬μš© κ°€λŠ₯.
protocol DiceGame { // κ²Œμž„μ— μ±„νƒλ˜λŠ” ν”„λ‘œν† μ½œ
    var dice: Dice { get }
    func play()
}

protocol DiceGameDelegate: AnyObject { // κ²Œμž„ 진행 상황을 μΆ”μ ν•˜λŠ”λ° 채택
    func gameDidStart(_ game: DiceGame)
    func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
    func gameDidEnd(_ game: DiceGame)
}
  • delegate λŠ” κ°•ν•œ μˆœν™˜ μ°Έμ‘°λ₯Ό λ°œμƒμ‹œν‚¬ 수 있기 λ•Œλ¬Έμ— weak 둜 μ„ μ–Έ.
  • ν”„λ‘œν† μ½œμ„ μ±„νƒν•œ 객체의 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ•Όν•˜λ‹ˆκΉŒ, κ·Έ 객체λ₯Ό 계속 μ°Έμ‘°ν•˜κ³  있게 됨.
  • ν•΄λ‹Ή κ°μ²΄λŠ” λ‚΄λ €κ°€μ•Όν•˜λŠ”λ° 내렀가지 μ•ŠλŠ” 상황이 올 수 μžˆλ‹€.
class SnakesAndLadders: DiceGame {
    let finalSquare = 25
    let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
    var square = 0
    var board: [Int]
    init() {
        board = Array(repeating: 0, count: finalSquare + 1)
        board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
        board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
    }
    weak var delegate: DiceGameDelegate?
    func play() {
        square = 0
        delegate?.gameDidStart(self)
        gameLoop: while square != finalSquare {
            let diceRoll = dice.roll()
            delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
            switch square + diceRoll {
            case finalSquare:
                break gameLoop
            case let newSquare where newSquare > finalSquare:
                continue gameLoop
            default:
                square += diceRoll
                square += board[square]
            }
        }
        delegate?.gameDidEnd(self)
    }
}
  • κΆκΈˆν•œ 점 : 예λ₯Ό λ“€μ–΄μ„œ tableviewCell 이 tableviewController 에 protocol 을 μ΄μš©ν•΄μ„œ μœ„μž„μ„ 해버릴 μˆ˜λ„ 있고, μ•„λ‹ˆλ©΄ κ·Έλƒ₯ ν•Έλ“€λŸ¬ λ³€μˆ˜λ₯Ό ν•˜λ‚˜ 두고 셀에 λ„˜κ²¨μ£ΌκΈ°λ„ ν•˜λŠ”λ°? 이 두방식을 μ–΄λ–»κ²Œ κ΅¬λΆ„ν•΄μ„œ μ‚¬μš©ν•˜λŠ”μ§€?? κ·Έλƒ₯ μŠ€νƒ€μΌ 차이인지??? μ•„λ‹ˆλ©΄ 또 ν”„λ‘œν† μ½œ 없이 RxSwift λ₯Ό μ‚¬μš©ν•˜κΈ°λ„ ν•˜λŠ”λ° 속도 차이가 μ–΄λ–»κ²Œ 될까...
class DiceGameTracker: DiceGameDelegate {
    var numberOfTurns = 0
    func gameDidStart(_ game: DiceGame) {
        numberOfTurns = 0
        if game is SnakesAndLadders {
            print("Started a new game of Snakes and Ladders")
        }
        print("The game is using a \(game.dice.sides)-sided dice")
    }
    func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
        numberOfTurns += 1
        print("Rolled a \(diceRoll)")
    }
    func gameDidEnd(_ game: DiceGame) {
        print("The game lasted for \(numberOfTurns) turns")
    }
}

let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate = tracker
game.play()

8. extension 으둜 protocol μ€€μˆ˜

  • μ†ŒμŠ€ μ½”λ“œ μƒμœΌλ‘œ 접근이 λΆˆκ°€λŠ₯ν•œ κΈ°μ‘΄ νƒ€μž…μ— λŒ€ν•΄μ„œλ„ extension 으둜 ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜κ²Œ ν•  수 μžˆλ‹€.
  • μ†ŒμŠ€ μ½”λ“œ μƒμœΌλ‘œ 접근이 κ°€λŠ₯해도 가독성을 μœ„ν•΄μ„œ extension 으둜 λΆ„λ¦¬ν•˜κΈ°λ„ 함.
  • 계산 ν”„λ‘œνΌν‹°, λ©”μ„œλ“œ, μ„œλΈŒμŠ€ν¬λ¦½νŠΈλ₯Ό extension μ•ˆμ—μ„œ μ •μ˜ν•  수 μžˆμœΌλ―€λ‘œ extension 으둜 protocol 채택 κ°€λŠ₯.
  • κΈ°μ‘΄ μΈμŠ€ν„΄μŠ€ 생성 후에 ν”„λ‘œν† μ½œμ„ 채택해도 ν”„λ‘œν† μ½œμ„ λ”°λ₯΄κ²Œ 됨.
protocol TextRepresentable {
    var textualDescription: String { get }
}

extension Dice: TextRepresentable {
    var textualDescription: String {
        return "A \(sides)-sided dice"
    }
}

let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
print(d12.textualDescription) // Prints "A 12-sided dice"

쑰건적으둜 ν”„λ‘œν† μ½œ μ€€μˆ˜ where

  • μ–΄λ–€ νŒŒλΌλ―Έν„°κ°€ νŠΉμ • ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λŠ” νŠΉμ • μ‘°κ±΄μ—μ„œλ§Œ ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λ„λ‘ ν•  수 μžˆλ‹€.
// λ°°μ—΄μ˜ μš”μ†Œκ°€ TextRespresentable 을 λ”°λ₯Ό λ•Œ Array 도 TextRepresentable.
extension Array: TextRepresentable where Element: TextRepresentable {
    var textualDescription: String {
        let itemsAsText = self.map { $0.textualDescription }
        return "[" + itemsAsText.joined(separator: ", ") + "]"
    }
}
let myDice = [d6, d12]
print(myDice.textualDescription)  // Prints "[A 6-sided dice, A 12-sided dice]"

ν™•μž₯κ³Ό ν•¨κ»˜ ν”„λ‘œν† μ½œ 채택 μ„ μ–Έ

  • 이미 ν”„λ‘œν† μ½œμ„ λ”°λ₯΄μ§€λ§Œ, ν”„λ‘œν† μ½œμ„ μ±„νƒν•œλ‹€κ³  λͺ…μ‹œν•˜μ§€ μ•Šμ€ 경우
  • 빈 ν”„λ‘œν† μ½œλ‘œ λͺ…μ‹œ κ°€λŠ₯.
struct Hamster {
    var name: String
    var textualDescription: String {
        return "A hamster named \(name)"
    }
}
extension Hamster: TextRepresentable {}

9. 이미 κ΅¬ν˜„λœ ν”„λ‘œν† μ½œ 채택

  • Equatable, Hashable, Comparable ν”„λ‘œν† μ½œ μ€€μˆ˜μ„±μ„ μžλ™μœΌλ‘œ μ œκ³΅ν•œλ‹€.

Equtable

  • Equatable 의 == != 을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄ 맀번 μ—°μ‚°μžλ₯Ό κ΅¬ν˜„ν•΄μ•Όν•˜λŠ” 것이 μ•„λ‹ˆλ‹€.
    • Equatable ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λŠ” μ €μž₯ ν”„λ‘œνΌν‹°λ§Œ μžˆλŠ” struct
    • Equatable ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λŠ” μ—°κ΄€λœ νƒ€μž…λ§Œ μžˆλŠ” μ—΄κ±°ν˜•
    • μ—°κ΄€λœ νƒ€μž…μ΄ μ—†λŠ” μ—΄κ±°ν˜•
      μ—λŠ” μžλ™ 제곡됨.
struct Vector3D: Equatable {
    var x = 0.0, y = 0.0, z = 0.0
}

let twoThreeFour = Vector3D(x: 2.0, y: 3.0, z: 4.0)
let anotherTwoThreeFour = Vector3D(x: 2.0, y: 3.0, z: 4.0)
if twoThreeFour == anotherTwoThreeFour {
    print("These two vectors are also equivalent.")
}

Hashable: Equatable

  • μ •μˆ˜λ‘œ 된 hash 값을 μ œκ³΅ν•˜λŠ” νƒ€μž….
  • κΈ°λ³Έ μ œκ³΅μ€ Equatable κ³Ό 쑰건이 κ°™μŒ.
  • κ·Έ κ°’ 자체둜 μœ μΌν•˜λ‹€λΌλŠ”κ±Έ κ΅¬ν˜„ν•˜λŠ” hash(into:) λΌλŠ” ν•¨μˆ˜λ₯Ό 맀번 κ΅¬ν˜„ν•  ν•„μš”κ°€ μ—†μŒ.
  • 이 ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λ©΄ ꡬ쑰체λ₯Ό λ°°μ—΄μ΄λ‚˜ λ”•μ…”λ„ˆλ¦¬μ— 넣을 수 있음.

https://developer.apple.com/documentation/swift/hashable#2849490

Comparable

  • < > >= <= λ₯Ό κΈ°λ³Έ 제곡.
enum SkillLevel: Comparable {
    case beginner
    case intermediate
    case expert(stars: Int)
}
var levels = [SkillLevel.intermediate, SkillLevel.beginner,
              SkillLevel.expert(stars: 5), SkillLevel.expert(stars: 3)]
for level in levels.sorted() {
    print(level)
}
// Prints "beginner"
// Prints "intermediate"
// Prints "expert(stars: 3)"
// Prints "expert(stars: 5)"

10. ν”„λ‘œν† μ½œ νƒ€μž…μ˜ μ½œλ ‰μ…˜

  • λ°°μ—΄, λ”•μ…”λ„ˆλ¦¬ 같은 μ»¬λ ‰μ…˜ νƒ€μž…μ— μ €μž₯되기 μœ„ν•΄μ„œ μ‚¬μš© κ°€λŠ₯.
  • 반볡과 ν”„λ‘œν† μ½œμ— μžˆλŠ” ν”„λ‘œνΌν‹°, λ©”μ„œλ“œ μ‚¬μš© κ°€λŠ₯.
let things: [TextRepresentable] = [game, d12, simonTheHamster]

for thing in things {
    print(thing.textualDescription)
}
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
// A hamster named Simon

11. ν”„λ‘œν† μ½œ 상속

  • ν”„λ‘œν† μ½œλ„ 상속할 수 μžˆλ‹€.
protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
    // protocol definition goes here
}

protocol PrettyTextRepresentable: TextRepresentable {
    var prettyTextualDescription: String { get }
}

// 기쑴에 TextRepresentable 을 μ€€μˆ˜ν•˜κ³  μžˆλŠ” SnakesAndLadders μ—μ„œ
// PrettyTextRepresentable 을 채택
extension SnakesAndLadders: PrettyTextRepresentable {
    var prettyTextualDescription: String {
        // 이미 TextRepresentable μ΄λ―€λ‘œ textualDescription ν”„λ‘œνΌν‹°μ— μ ‘κ·Ό κ°€λŠ₯.
        var output = textualDescription + ":\n"
        for index in 1...finalSquare {
            switch board[index] {
            case let ladder where ladder > 0:
                output += "β–² "
            case let snake where snake < 0:
                output += "β–Ό "
            default:
                output += "β—‹ "
            }
        }
        return output
    }
}

12. 클래슀 μ „μš© ν”„λ‘œν† μ½œ

  • ν”„λ‘œν† μ½œ 상속 λͺ©λ‘μ— AnyObject λ₯Ό μΆ”κ°€ν•˜λ©΄ ν΄λž˜μŠ€μ—μ„œλ§Œ κ΅¬ν˜„ν•  수 있게 λ§Œλ“€ 수 μžˆλ‹€.
  • ν”„λ‘œν† μ½œμ— λŒ€ν•΄ μ°Έμ‘° 의미 체계가 μžˆλ‹€κ³  μƒκ°λ˜λŠ” 경우 (...) μ‚¬μš©ν•œλ‹€.
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

13. ν”„λ‘œν† μ½œ ꡬ성

  • μ—¬λŸ¬ ν”„λ‘œν† μ½œμ„ 단일 μš”κ΅¬μ‚¬ν•­μœΌλ‘œ κ²°ν•©ν•  수 μžˆλ‹€. Equtable & Comparable
  • λͺ¨λ“  ν”„λ‘œν† μ½œμ˜ μš”κ΅¬μ‚¬ν•­μ„ 가진 μž„μ‹œ 둜컬 ν”„λ‘œν† μ½œλ‘œ μ •μ˜λœ 것 처럼 λ™μž‘ν•œλ‹€.
protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}
struct Person: Named, Aged {
    var name: String
    var age: Int
}

// Person λŒ€μ‹  Named & Aged λ₯Ό μ‚¬μš©.
// Person 이 μ•„λ‹Œ 두 ν”„λ‘œν† μ½œμ„ κ΅¬ν˜„ν•œ μ–΄λ–€ 것이라도 μΈμžκ°€ 될 수 있음.
func wishHappyBirthday(to celebrator: Named & Aged) {
    print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(to: birthdayPerson)
// Prints "Happy birthday, Malcolm, you're 21!"

14. ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λŠ”μ§€ 검사.

  • νƒ€μž… μΊμŠ€νŒ… 처럼 is as μ‚¬μš©.
  • is : ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λ©΄ true μ•„λ‹ˆλ©΄ false
  • as? as! : λ‹€μš΄ μΊμŠ€νŒ….

15. μ˜΅μ…”λ„ μš”κ΅¬μ‚¬ν•­

  • ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λŠ” νƒ€μž…μœΌλ‘œ κ΅¬ν˜„λ  ν•„μš”κ°€ μ—†λ‹€.
  • optional μˆ˜μ‹μ–΄λ₯Ό λΆ™μž„.
  • obj-c 에도 μ‚¬μš© κ°€λŠ₯ν•œ μ½”λ“œλ₯Ό μž‘μ„±ν•  수 μžˆμ§€λ§Œ @objc 뢙여야함.
  • μ˜΅μ…”λ„ μš”κ΅¬μ‚¬ν•­μ—μ„œ ν”„λ‘œνΌν‹°λ‚˜ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ μžλ™μ μœΌλ‘œ optional type 으둜 λ§Œλ“€μ–΄ 쀌.
  • λ°˜ν™˜ νƒ€μž… μ—­μ‹œ optional.
// μ‹€μ œ μ½”λ“œμ—μ„  optional 만 μžˆλŠ” μ½”λ“œλŠ” λ³„λ‘œ 쒋지 μ•ŠμŒ.
@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}

class Counter {
    var count = 0
    var dataSource: CounterDataSource?
    func increment() { // count 증가.
        // increment κ°€ optional func 이기 λ•Œλ¬Έμ— ? 을 λΆ™μ—¬ 체이닝.
        // μ‹€μ œ κ΅¬ν˜„λΆ€μ— μžˆλŠ” ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜λŠ” 것.
        if let amount = dataSource?.increment?(forCount: count) {
            count += amount
        } else if let amount = dataSource?.fixedIncrement {
            count += amount
        }
    }
}

// ContuerDataSource λ₯Ό μ‹€μ œλ‘œ κ΅¬ν˜„ν•˜λŠ” λΆ€λΆ„.
class ThreeSource: NSObject, CounterDataSource {
    let fixedIncrement = 3
}

var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1...4 { 
    counter.increment()
    print(counter.count) // 3 6 9 12
}

16. ν”„λ‘œν† μ½œ ν™•μž₯

  • ν”„λ‘œν† μ½œμ„ ν™•μž₯ν•΄μ„œ λ©”μ„œλ“œ, μ΄ˆκΈ°ν™” ꡬ문, μ„œλΈŒμŠ€ν¬λ¦½νŠΈ, κ³„μ‚°λœ ν”„λ‘œνΌν‹° κ΅¬ν˜„μ„ ν•  수 μžˆλ‹€.
  • νƒ€μž…μ΄ μΆ©μ‘±ν•΄μ•Όν•˜λŠ” μ œμ•½μ‘°κ±΄μ„ λ§λΆ™μ΄λŠ” 것도 κ°€λŠ₯함.
// 직접 μ–΄λ””μ„ κ°€ ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λ € κ΅¬ν˜„μ„ ν•˜μ§€ μ•Šμ•„λ„ ν”„λ‘œν† μ½œλ§Œ μ±„νƒν•˜λ©΄ μ‚¬μš© κ°€λŠ₯.
extension RandomNumberGenerator {
    func randomBool() -> Bool {
        return random() > 0.5
    }
}

κΈ°λ³Έ κ΅¬ν˜„ 제곡

  • λ©”μ„œλ“œλ‚˜ κ³„μ‚°λœ ν”„λ‘œνΌν‹°μ— κΈ°λ³Έ κ΅¬ν˜„ 제곡.
extension PrettyTextRepresentable  {
    var prettyTextualDescription: String {
        return textualDescription
    }
}

ν”„λ‘œν† μ½œ ν™•μž₯에 μ œμ•½μ‚¬ν•­ μΆ”κ°€.

  • μ»¬λ ‰μ…˜ νƒ€μž…μΈλ°, μ›μ†Œκ°€ Equatable 을 λ”°λ₯΄λŠ” κ²ƒλ§Œ allEqual ν•¨μˆ˜ μ‚¬μš© κ°€λŠ₯.
extension Collection where Element: Equatable {
    func allEqual() -> Bool {
        for element in self {
            if element != self.first { // != μ‚¬μš©ν•˜λ €κ³  Equatable 쑰건 건 것.
                return false
            }
        }
        return true
    }
}

let equalNumbers = [100, 100, 100, 100, 100]
let differentNumbers = [100, 100, 200, 100, 200]

print(equalNumbers.allEqual()) // true
print(differentNumbers.allEqual()) // false



질문

ν”„λ‘œν† μ½œμ΄λž€ 무엇인지 μ„€λͺ…ν•˜μ‹œμ˜€.

  • ν”„λ‘œν† μ½œμ€ Swift μ—μ„œ μ œκ³΅ν•˜λŠ” κ·œμΉ™μ„ μ •μ˜ν•˜λŠ” 문법이닀. λ‹€λ₯Έ μ–Έμ–΄μ˜ μΈν„°νŽ˜μ΄μŠ€μ™€ λΉ„μŠ·ν•˜λ‹€.
  • ν•„μš”ν•œ λ³€μˆ˜λ‚˜ λ©”μ„œλ“œ init 을 μ•ˆμ—μ„œ μ •μ˜λ§Œ ν•˜κ³  κ΅¬ν˜„μ€ ν•˜μ§€ μ•Šκ³ , μ‹€μ œλ‘œ ν”„λ‘œν† μ½œμ„ μ±„νƒν•˜λŠ” λΆ€λΆ„μ—μ„œ κ΅¬ν˜„ν•˜κ²Œ λœλ‹€.
  • ν”„λ‘œν† μ½œμ— μžˆλŠ” λͺ¨λ“  ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜λ©΄ ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•œλ‹€κ³  λ§ν•œλ‹€.
  • ν”„λ‘œν† μ½œμ„ 톡해 delegate λΌλŠ” λ‹€λ₯Έ 객체에 μ±…μž„μ„ λ„˜κΈ°λŠ” νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λŠ”λ°,
    • μ±…μž„μ„ λ„˜κΈ°λ €κ³  ν•˜λŠ” 객체가 protocol νƒ€μž…μ˜ weak optional λ³€μˆ˜λ₯Ό μƒμ„±ν•˜κ³ , ν•΄λ‹Ή ν”„λ‘œν† μ½œ μ•ˆμ— μžˆλŠ” ν”„λ‘œνΌν‹°λ‚˜ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄,
    • μ‹€μ œλ‘œ κ·Έ λ³€μˆ˜λ‚˜ ν”„λ‘œνΌν‹°κ°€ κ΅¬ν˜„λ˜μ–΄ μžˆλŠ” κ΅¬ν˜„λΆ€μ—μ„œ μœ„μž„ λ°›μ•„μ„œ μ²˜λ¦¬ν•˜κ²Œ λœλ‹€.
    • tableviewcell μ—μ„œ viewcontroller 의 정보가 ν•„μš”ν•œ 상황에 delegate λ₯Ό μ΄μš©ν•΄μ„œ viewcontroller κ°€ λ„˜κ²¨μ„œ μ²˜λ¦¬ν•  수 μžˆλ„λ‘ κ΅¬ν˜„ ν–ˆμ—ˆλ‹€.
  • 이미 κ΅¬ν˜„λœ Equatable 같은 ν”„λ‘œν† μ½œμ„ μ±„νƒν•˜κ±°λ‚˜ ν”„λ‘œν† μ½œλΌλ¦¬ 상속을 ν•  μˆ˜λ„ μžˆλ‹€.

Hashable이 무엇이고, Equatable을 μ™œ 상속해야 ν•˜λŠ”μ§€ μ„€λͺ…ν•˜μ‹œμ˜€.

  • Hashable 은 ν•΄μ‹œκ°€ κ°€λŠ₯ν•œ νƒ€μž…μΈλ°,
  • ν•΄μ‹œκ°€ κ°€λŠ₯ν•˜κΈ° μœ„ν•΄μ„œλŠ” μ •μˆ˜ ν•΄μ‹œκ°’μ„ μ œκ³΅ν•΄μ•Ό ν•œλ‹€.
  • ν•΄μ‹œκ°’μ€ κ³ μœ ν•œ κ°’μ΄λ―€λ‘œ input μ›μ†Œκ°€ λ‹€λ₯΄λ©΄ ν•΄μ‹œκ°’λ„ λ‹€λ₯΄κ²Œ λ‚˜μ™€μ•Ό ν•œλ‹€.
  • κ·Έλž˜μ„œ hashValue λ₯Ό μƒμ„±ν•΄μ£ΌλŠ” ν•¨μˆ˜κ°€ ν•˜λ‚˜ ν•„μš”ν•˜κ³ ,
  • ꡬ뢄이 κ°€λŠ₯ν•˜λ €λ©΄ 두 μ›μ†Œκ°€ 같닀에 λŒ€ν•œ μ •μ˜κ°€ μžˆμ–΄μ•Ό ν•˜λ―€λ‘œ Equtable 을 상속해야 ν•œλ‹€.
  • dictionary, set 의 key λŠ” Hashable 을 μ€€μˆ˜ν•΄μ•Ό ν•œλ‹€.

Hashable 을 λ”°λ₯΄λŠ” 것듀

  • String, Integer, Float, Boolean
  • Optinal, Array, Range - μ•ˆμ˜ μ›μ†Œ νƒ€μž…μ΄ 동일할 λ•Œ.
  • associate value λ₯Ό κ΅¬ν˜„ν•˜μ§€ μ•Šμ€ enum
  • μ €μž₯ ν”„λ‘œνΌν‹°κ°€ λͺ¨λ‘ Hashable ν•œ ꡬ쑰체
  • case κ°€ λͺ¨λ‘ Hashable ν•œ enum
  • +) Hashable 을 μ±„νƒν•˜μ—¬ hash(into: ) λ₯Ό 직접 κ΅¬ν˜„ν•œ custom type
  • +) κΈ°λ³Έ 제곡 데이터 νƒ€μž…μ€ λͺ¨λ‘ Equatable

Codable에 λŒ€ν•˜μ—¬ μ„€λͺ…ν•˜μ‹œμ˜€.

  • Codable 은 Swift 의 ν˜•μ‹μ„ μ–΄λ–€ λ‹€λ₯Έ ν˜•μ‹μœΌλ‘œ 인코딩, 디코딩이 κ°€λŠ₯ν•˜κ²Œ λ§Œλ“€μ–΄μ£ΌλŠ” ν”„λ‘œν† μ½œμ΄λ‹€.
  • json 을 λ‹€λ£° λ•Œ 많이 쓰인닀.
  • λ³€ν™˜ν•˜κ³  싢은 struct, enum, class 에 Codable ν”„λ‘œν† μ½œμ„ 채택해주면 Encoder, Decoder λ₯Ό μ‚¬μš©ν•΄μ„œ json 으둜 λ³€ν™˜ν•  수 μžˆλ‹€.
  • type 이 μ •ν™•ν•˜κ²Œ μ§€μ •λœ λ³€μˆ˜λ§Œ 좕약이 κ°€λŠ₯ν•˜κ³ , μ€‘μ²©λœ νƒ€μž…μ΄λ‚˜ Any νƒ€μž…μ—μ„œλŠ” μ‚¬μš©ν•˜κΈ° μ–΄λ ΅λ‹€.
  • Encodable, Decodable 을 λ”°λ‘œ 채택해쀄 μˆ˜λ„ μžˆλ‹€.
  • enum CodingKeys λ₯Ό μ‚¬μš©ν•΄μ„œ μ„œλ²„μ˜ λ³€μˆ˜ 넀이밍을 Swift 에 μ•Œλ§žκ²Œ λ°”κΏ€ μˆ˜λ„ μžˆλ‹€.

AnyObject에 λŒ€ν•΄ μ„€λͺ…ν•˜μ‹œμ˜€.

  • μ–΄λ–€ 클래슀의 μΈμŠ€ν„΄μŠ€λ„ 받을 수 μžˆλŠ” νƒ€μž…μ΄λ‹€.
  • 이걸 μ‚¬μš©ν•˜λ©΄ 클래슀 μΈμŠ€ν„΄μŠ€λ₯Ό μ“Έ λ•Œ νƒ€μž… μΊμŠ€νŒ…μ΄ ν•„μš”ν•΄μ„œ νŠΉλ³„ν•œ μΌ€μ΄μŠ€κ°€ μ•„λ‹ˆλ©΄ μ•ˆ μ“°λŠ” 것이 μ’‹λ‹€.

Delegate νŒ¨ν„΄μ„ ν™œμš©ν•˜λŠ” 경우λ₯Ό 예λ₯Ό λ“€μ–΄ μ„€λͺ…ν•˜μ‹œμ˜€.

Delegates와 Notification λ°©μ‹μ˜ 차이점에 λŒ€ν•΄ μ„€λͺ…ν•˜μ‹œμ˜€.

  • λΈλ¦¬κ²Œμ΄νŠΈλŠ” μœ„μž„ 방식이닀.

    • μ–΄λ–€ μ΄λ²€νŠΈκ°€ λ°œμƒν–ˆμ„ λ•Œ λ‹€λ₯Έ ν΄λž˜μŠ€μ—μ„œ ν•΄λ‹Ή 이벀트λ₯Ό μ²˜λ¦¬ν•  수 μžˆλ„λ‘ μ±…μž„μ„ λ„˜κΈ΄λ‹€.
  • λ…Έν‹°ν”ΌμΌ€μ΄μ…˜μ€

    • μ΄λ²€νŠΈκ°€ λ°œμƒν•˜λŠ” 것을 κ΄€μ°°ν•˜κ³  μžˆλ‹€κ°€,
    • ν•΄λ‹Ή μ΄λ²€νŠΈκ°€ λ°œμƒν•˜λ©΄ μ²˜λ¦¬ν•˜κ²Œ λœλ‹€.

차이점은,

  • λΈλ¦¬κ²Œμ΄νŠΈλŠ” ν”„λ‘œν† μ½œμ„ μ΄μš©ν•΄μ„œ ν•˜κΈ° λ•Œλ¬Έμ— μ—„κ²©ν•œ κ·œμΉ™μ„ μ§€μΌœμ•Όν•œλ‹€.

  • ν”„λ‘œν† μ½œμ„ κ΅¬ν˜„ν•œ ν•˜λ‚˜μ˜ VC μ•ˆμ—μ„œ 보톡 μ²˜λ¦¬κ°€ λœλ‹€.

  • delegate μ—μ„œ 이벀트λ₯Ό λ°œμƒμ‹œν‚€λ©΄, μ΄λ²€νŠΈκ°€ λ°œμƒν–ˆμ„ λ•Œ μ§μ ‘μ μœΌλ‘œ delegate λ‚΄μ˜ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄μ„œ 처리λ₯Ό ν•˜κΈ° λ•Œλ¬Έμ— 둜직의 흐름을 따라가기 쉽닀.

  • λ…Έν‹°ν”ΌμΌ€μ΄μ…˜μ€ 이벀트λ₯Ό post 둜 λ°œμƒμ‹œν‚€κ³  observer 둜 κ·Έ 이벀트λ₯Ό 작기 λ•Œλ¬Έμ— μ‰½κ²Œ κ΅¬ν˜„μ΄ κ°€λŠ₯ν•˜μ§€λ§Œ,

  • μ–΄λ–€ κ³³μ—μ„œ λ°œμƒν•΄μ„œ ν•¨μˆ˜κ°€ μ‹€ν–‰λœκ±΄μ§€μ— λŒ€ν•œ 좔적이 쉽지 μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

Protocol Oriented Programmingκ³Ό Object Oriented Programming의 차이점을 μ„€λͺ…ν•˜μ‹œμ˜€.

  • λ‘˜ λ‹€ λ‹€ν˜•μ„±μ„ κ΅¬ν˜„ν•˜κΈ° μœ„ν•œ 방법이닀.

  • ν”„λ‘œν† μ½œ 지ν–₯ ν”„λ‘œκ·Έλž˜λ°

    • ν”„λ‘œν† μ½œμ„ μ€‘μ‹¬μœΌλ‘œ ν•΄μ„œ 합성을 ν†΅ν•œ μˆ˜ν‰μ  ꡬ쑰 ν™•μž₯을 기반으둜 ν•œλ‹€.
    • μ–΄λ–€ 속성 을 가지고 μžˆλ‹€λΌλŠ” has-A 의미 ꡬ쑰λ₯Ό ν‘œν˜„ν•  수 있음.
    • value type 에도 적용이 κ°€λŠ₯ν•˜λ‹€.
    • 닀쀑 상속이 κ°€λŠ₯함.
  • 객체 지ν–₯ ν”„λ‘œκ·Έλž˜λ°

    • 상속을 μ€‘μ‹¬μœΌλ‘œ ν•œ 수직 ꡬ쑰 ν™•μž₯을 기반으둜 ν•œλ‹€.
    • 이것은 이것이닀 λΌλŠ” is-A 의미 ꡬ쑰λ₯Ό ν‘œν˜„ν•˜κΈ° 적합.
    • λΆ€λͺ¨μ˜ λͺ¨λ“  것을 상속받기 λ•Œλ¬Έμ—, ν•„μš” μ—†λŠ” λ©”μ„œλ“œλ‚˜ λ³€μˆ˜λ„ 상속될 수 μžˆλ‹€.
    • 상속을 μœ„ν•΄ value type λŒ€μ‹  reference type 으둜 λͺ¨λ“  것을 κ΅¬ν˜„ν•΄μ•Ό ν•œλ‹€.
    • 닀쀑 상속이 μ•ˆλ¨.
  • κ·Έλž˜μ„œ ν—€λ“œνΌμŠ€νŠΈ λ””μžμΈ νŒ¨ν„΄ 첫 λŒ€λͺ©μ˜ Flyable Quackable 이 μžλ°”μ—μ„œ μ•ˆ 쒋은 μ˜ˆμ‹œλΌκ³  ν•΄μ„œ Swift... κ°€λŠ₯ν•˜μž–μ•„..? 라고 μƒκ°ν–ˆλ˜ κ²ƒμ΄μ—ˆλ‹€. ν”„λ‘œν† μ½œ κΈ°λ°˜μ΄λ‹ˆκΉŒ!



  • weak self 의 경우 클래슀 μΈμŠ€ν„΄μŠ€μ™€ 클래슀 μΈμŠ€ν„΄μŠ€ ν˜Ήμ€ ν΄λ‘œμ €μ™€ 클래슀 μΈμŠ€ν„΄μŠ€κ°€ μ„œλ‘œλ₯Ό μ°Έμ‘°ν•  λ•Œ μ‚¬μš©ν•˜κ³ ,
  • unowned self 의 κ²½μš°λŠ” κΈ°λ³Έ κ°œλ…μ€ 같은데 μ°Έμ‘°ν•˜λŠ” 객체가 λ©”λͺ¨λ¦¬ 상에 μ‘΄μž¬ν•œλ‹€κ³  ν™•μ‹ ν•  수 μžˆμ„ λ•Œ μ‚¬μš©ν•œλ‹€. κ·Έλž˜μ„œ nil 인지 κΌ­ 확인을 거쳐야함.



μ°Έκ³ 
https://bbiguduk.gitbook.io/swift/language-guide-1/protocols
https://velog.io/@hayeon/Hashable이-무엇이고-Equatable을-μ™œ-상속해야-ν•˜λŠ”μ§€-μ„€λͺ…ν•˜μ‹œμ˜€

profile
0λ…„μ°¨ iOS κ°œλ°œμžμž…λ‹ˆλ‹€.

0개의 λŒ“κΈ€