λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ₯– Bread Basics/Swift

Swift 곡식 λ¬Έμ„œ 정리 - A Swift Tour

by BreadDev 2025. 4. 10.
728x90

μ•ˆλ…•ν•˜μ„Έμš”. μ˜€λŠ˜μ€ A Swift Tour λ‚΄μš©μ„ 정리해보렀고 ν•©λ‹ˆλ‹€. 이 글이 Swift μž…λ¬ΈμžλΆ„λ“€κ»˜ 도움이 되길 λ°”λžλ‹ˆλ‹€.

πŸ“Œ Hello, World!

λͺ¨λ“  ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ˜ 첫 μ‹œμž‘μ€ "Hello, World!"μž…λ‹ˆλ‹€. Swiftμ—μ„œλŠ” μ•„μ£Ό κ°„λ‹¨ν•˜κ²Œ ν‘œν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

print("Hello, world!")

print: μ½˜μ†”μ— ν…μŠ€νŠΈλ₯Ό 좜λ ₯ν•˜λŠ” Swift의 κΈ°λ³Έ ν•¨μˆ˜

πŸ“Œ κ°„λ‹¨ν•œ κ°’ (Simple Values)

μƒμˆ˜μ™€ λ³€μˆ˜

var myVariable = 42  // λ³€μˆ˜ μ„ μ–Έ (κ°’ λ³€κ²½ κ°€λŠ₯)
myVariable = 50      // κ°’ λ³€κ²½ κ°€λŠ₯

let myConstant = 42  // μƒμˆ˜ μ„ μ–Έ (κ°’ λ³€κ²½ λΆˆκ°€)

var: 값이 λ³€ν•  수 μžˆλŠ” λ³€μˆ˜(variable)λ₯Ό μ„ μ–Έν•  λ•Œ μ‚¬μš©

let: 값이 λ³€ν•˜μ§€ μ•ŠλŠ” μƒμˆ˜(constant)λ₯Ό μ„ μ–Έν•  λ•Œ μ‚¬μš©

νƒ€μž… μΆ”λ‘ κ³Ό λͺ…μ‹œμ  νƒ€μž… μ§€μ •

let implicitInteger = 70       // νƒ€μž… μΆ”λ‘ : Int
let implicitDouble = 70.0      // νƒ€μž… μΆ”λ‘ : Double
let explicitDouble: Double = 70 // λͺ…μ‹œμ  νƒ€μž… μ§€μ •(Double)

νƒ€μž… μΆ”λ‘ (Type Inference): μ΄ˆκΈ°κ°’μ„ 보고 μ»΄νŒŒμΌλŸ¬κ°€ μžλ™μœΌλ‘œ νƒ€μž…μ„ κ²°μ •ν•˜λŠ” κΈ°λŠ₯

λ¬Έμžμ—΄ μ²˜λ¦¬μ™€ 보간법

let label = "The width is "
let width = 94
let widthLabel = label + String(width)  // λ¬Έμžμ—΄ λ³€ν™˜ ν›„ κ²°ν•©

// λ¬Έμžμ—΄ 보간법 (String Interpolation)
let apples = 3
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."

λ¬Έμžμ—΄ 보간법: \(ν‘œν˜„μ‹) ν˜•νƒœλ‘œ λ¬Έμžμ—΄ μ•ˆμ— λ³€μˆ˜λ‚˜ ν‘œν˜„μ‹μ„ μ‚½μž…ν•˜λŠ” κΈ°λŠ₯

μ—¬λŸ¬ 쀄 λ¬Έμžμ—΄

let quotation = """
        μ—¬λŸ¬ 쀄에 걸친 λ¬Έμžμ—΄μ€
        μ΄λ ‡κ²Œ μŒλ”°μ˜΄ν‘œ μ„Έ 개둜 μ‹œμž‘ν•˜κ³  λλ‚©λ‹ˆλ‹€.
        듀여쓰기도 μœ μ§€λ©λ‹ˆλ‹€.
        """

μ—¬λŸ¬ 쀄 λ¬Έμžμ—΄: μ„Έ 개의 μŒλ”°μ˜΄ν‘œ(""")둜 κ°μ‹Έμ„œ μ—¬λŸ¬ μ€„μ˜ λ¬Έμžμ—΄μ„ ν‘œν˜„

λ°°μ—΄κ³Ό λ”•μ…”λ„ˆλ¦¬

// λ°°μ—΄
var fruits = ["strawberries", "limes", "tangerines"]
fruits[1] = "grapes"  // λ°°μ—΄ μš”μ†Œ λ³€κ²½
fruits.append("blueberries")  // μš”μ†Œ μΆ”κ°€

// λ”•μ…”λ„ˆλ¦¬
var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"  // μƒˆ ν‚€-κ°’ 쌍 μΆ”κ°€

λ°°μ—΄(Array): μˆœμ„œκ°€ μžˆλŠ” κ°’μ˜ λͺ©λ‘

λ”•μ…”λ„ˆλ¦¬(Dictionary): ν‚€-κ°’ 쌍의 μ»¬λ ‰μ…˜

append(): 배열에 μƒˆ μš”μ†Œλ₯Ό μΆ”κ°€ν•˜λŠ” λ©”μ„œλ“œ

빈 μ»¬λ ‰μ…˜ 생성

let emptyArray: [String] = []
let emptyDictionary: [String: Float] = [:]

πŸ“Œ μ œμ–΄ 흐름 (Control Flow)

쑰건문 (if-else)

let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0

for score in individualScores {
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
print(teamScore)  // 11

if-else: 쑰건에 따라 μ½”λ“œ μ‹€ν–‰ μ—¬λΆ€λ₯Ό κ²°μ •ν•˜λŠ” ꡬ문

for-in: μ»¬λ ‰μ…˜μ˜ 각 ν•­λͺ©μ— λŒ€ν•΄ 반볡 μ‹€ν–‰ν•˜λŠ” 루프 ꡬ문

쑰건뢀 κ°’ ν• λ‹Ή

let scoreDecoration = if teamScore > 10 {
    "πŸŽ‰"
} else {
    ""
}
print("Score:", teamScore, scoreDecoration)  // Score: 11 πŸŽ‰

쑰건뢀 ν• λ‹Ή: Swiftμ—μ„œ if ν‘œν˜„μ‹μ„ μ‚¬μš©ν•΄ 쑰건에 따라 λ‹€λ₯Έ 값을 ν• λ‹Ήν•˜λŠ” 방식

μ˜΅μ…”λ„ (Optionals)

var optionalString: String? = "Hello"
print(optionalString == nil)  // false

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

μ˜΅μ…”λ„(Optional): 값이 μžˆμ„ μˆ˜λ„, 없을 μˆ˜λ„ μžˆμŒμ„ ν‘œν˜„ν•˜λŠ” νƒ€μž…

nil: 값이 μ—†μŒμ„ λ‚˜νƒ€λ‚΄λŠ” Swift의 특수 κ°’

if let: μ˜΅μ…”λ„ λ°”μΈλ”©μœΌλ‘œ, μ˜΅μ…”λ„μ— 값이 μžˆμ„ κ²½μš°μ—λ§Œ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” ꡬ문

μ˜΅μ…”λ„ 처리 방법듀

// nil 병합 μ—°μ‚°μž
let nickname: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickname ?? fullName)"  // Hi John Appleseed

// 더 짧은 μ˜΅μ…”λ„ 바인딩
if let nickname {
    print("Hey, \(nickname)")
}  // nickname이 nilμ΄λ―€λ‘œ 아무것도 좜λ ₯λ˜μ§€ μ•ŠμŒ

?? (Nil-Coalescing Operator): μ˜΅μ…”λ„ 값이 nil일 경우 기본값을 μ œκ³΅ν•˜λŠ” μ—°μ‚°μž

Switch λ¬Έ

let vegetable = "red pepper"
switch vegetable {
case "celery":
    print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
    print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
    print("Is it a spicy \(x)?")
default:
    print("Everything tastes good in soup.")
}
// 좜λ ₯: "Is it a spicy red pepper?"

switch: 값을 μ—¬λŸ¬ νŒ¨ν„΄κ³Ό λΉ„κ΅ν•˜μ—¬ μΌμΉ˜ν•˜λŠ” νŒ¨ν„΄μ— 따라 μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” ꡬ문

case let x where: νŒ¨ν„΄ λ§€μΉ­κ³Ό ν•¨κ»˜ 쑰건을 μ§€μ •ν•˜λŠ” 방식

반볡문

// for-in 반볡문
for (_, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}

// while 반볡문
var n = 2
while n < 100 {
    n *= 2
}

// repeat-while 반볡문 (λ‹€λ₯Έ μ–Έμ–΄μ˜ do-whileκ³Ό μœ μ‚¬)
var m = 2
repeat {
    m *= 2
} while m < 100

while: 쑰건이 참인 λ™μ•ˆ μ½”λ“œ 블둝을 반볡 μ‹€ν–‰

repeat-while: μ½”λ“œ 블둝을 μ΅œμ†Œ ν•œ 번 μ‹€ν–‰ν•œ ν›„, 쑰건이 참인 λ™μ•ˆ 반볡

λ²”μœ„ μ—°μ‚°μž

var total = 0
for i in 0..<4 {  // 0, 1, 2, 3
    total += i
}

..<: λ°˜μ—΄λ¦° λ²”μœ„ μ—°μ‚°μžλ‘œ, μ‹œμž‘ 값은 ν¬ν•¨ν•˜κ³  끝 값은 μ œμ™Έ

...: λ‹«νžŒ λ²”μœ„ μ—°μ‚°μžλ‘œ, μ‹œμž‘ κ°’κ³Ό 끝 값을 λͺ¨λ‘ 포함

πŸ“Œ ν•¨μˆ˜μ™€ ν΄λ‘œμ € (Functions and Closures)

ν•¨μˆ˜ μ •μ˜μ™€ 호좜

func greet(person: String, day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet(person: "Bob", day: "Tuesday")

func: ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜λŠ” ν‚€μ›Œλ“œ

->: λ°˜ν™˜ νƒ€μž…μ„ μ§€μ •ν•˜λŠ” 기호

Argument Label

func greet(_ person: String, on day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday")

Argument Label: ν•¨μˆ˜ 호좜 μ‹œ λ§€κ°œλ³€μˆ˜ μ•žμ— ν‘œμ‹œλ˜λŠ” 이름

_: 인수 λ ˆμ΄λΈ”μ„ μ‚¬μš©ν•˜μ§€ μ•Šμ„ λ•Œ μ§€μ •ν•˜λŠ” μ™€μΌλ“œμΉ΄λ“œ μ‹λ³„μž

νŠœν”Œ λ°˜ν™˜

func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    // ν•¨μˆ˜ κ΅¬ν˜„ ...
    return (min, max, sum)
}
let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
print(statistics.sum)  // 120
print(statistics.2)    // 120 (μΈλ±μŠ€λ‘œλ„ μ ‘κ·Ό κ°€λŠ₯)

νŠœν”Œ(Tuple): μ—¬λŸ¬ 값을 ν•˜λ‚˜μ˜ 볡합 κ°’μœΌλ‘œ κ·Έλ£Ήν™”ν•˜λŠ” νƒ€μž…

쀑첩 ν•¨μˆ˜

func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}

쀑첩 ν•¨μˆ˜(Nested Function): ν•¨μˆ˜ 내뢀에 μ •μ˜λœ ν•¨μˆ˜λ‘œ, μ™ΈλΆ€ ν•¨μˆ˜μ˜ λ³€μˆ˜μ— μ ‘κ·Ό κ°€λŠ₯

ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜

func makeIncrementer() -> ((Int) -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)  // 8

κ³ μ°¨ ν•¨μˆ˜(Higher-order Function): ν•¨μˆ˜λ₯Ό 인자둜 λ°›κ±°λ‚˜ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜

ν΄λ‘œμ € (Closures)

// ν΄λ‘œμ € ν‘œν˜„μ‹
numbers.map({ (number: Int) -> Int in
    let result = 3 * number
    return result
})

// κ°„μ†Œν™”λœ ν΄λ‘œμ € ν‘œν˜„μ‹
let mappedNumbers = numbers.map({ number in 3 * number })

// 더 κ°„μ†Œν™”λœ ν΄λ‘œμ € ν‘œν˜„μ‹ (μ•”μ‹œμ  νŒŒλΌλ―Έν„° 이름)
let sortedNumbers = numbers.sorted { $0 > $1 }

ν΄λ‘œμ €(Closure): μ½”λ“œ 블둝을 μΊ‘μŠν™”ν•˜μ—¬ μ „λ‹¬ν•˜κ³  μ‚¬μš©ν•  수 μžˆλŠ” κΈ°λŠ₯

$0, $1: ν΄λ‘œμ €μ—μ„œ μ‚¬μš©λ˜λŠ” μ•”μ‹œμ  νŒŒλΌλ―Έν„° 이름

πŸ“Œ 객체와 클래슀 (Objects and Classes)

클래슀 μ •μ˜

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

class: 클래슀λ₯Ό μ •μ˜ν•˜λŠ” ν‚€μ›Œλ“œ

ν”„λ‘œνΌν‹°(Property): 클래슀, ꡬ쑰체, μ—΄κ±°ν˜•μ— μ—°κ΄€λœ κ°’

클래슀 μΈμŠ€ν„΄μŠ€ 생성과 μ‚¬μš©

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

μ΄ˆκΈ°ν™” ꡬ문

class NamedShape {
    var numberOfSides: Int = 0
    var name: String

    init(name: String) {
        self.name = name
    }
    
    // λ©”μ„œλ“œ μ •μ˜...
}

init: μ΄ˆκΈ°ν™” ꡬ문을 μ •μ˜ν•˜λŠ” ν‚€μ›Œλ“œ

self: μΈμŠ€ν„΄μŠ€ μžμ‹ μ„ κ°€λ¦¬ν‚€λŠ” ν”„λ‘œνΌν‹°

상속과 λ©”μ„œλ“œ μž¬μ •μ˜

class Square: NamedShape {
    var sideLength: Double

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 4
    }

    func area() -> Double {
        return sideLength * sideLength
    }

    override func simpleDescription() -> String {
        return "A square with sides of length \(sideLength)."
    }
}

상속(Inheritance): ν•œ ν΄λž˜μŠ€κ°€ λ‹€λ₯Έ 클래슀의 νŠΉμ„±μ„ λ¬Όλ €λ°›λŠ” κΈ°λŠ₯

override: μƒμœ„ 클래슀의 λ©”μ„œλ“œλ₯Ό μž¬μ •μ˜ν•˜λŠ” ν‚€μ›Œλ“œ

super: μƒμœ„ 클래슀의 λ©”μ„œλ“œ, ν”„λ‘œνΌν‹° 등에 μ ‘κ·Όν•˜λŠ” ν‚€μ›Œλ“œ

ν”„λ‘œνΌν‹° getter와 setter

class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0
    
    // 계산 ν”„λ‘œνΌν‹°
    var perimeter: Double {
        get {
            return 3.0 * sideLength
        }
        set {
            sideLength = newValue / 3.0
        }
    }
    
    // μƒλž΅...
}

계산 ν”„λ‘œνΌν‹°(Computed Property): 값을 μ €μž₯ν•˜λŠ” λŒ€μ‹  getter와 setterλ₯Ό 톡해 값을 κ³„μ‚°ν•˜λŠ” ν”„λ‘œνΌν‹°

newValue: setterμ—μ„œ μƒˆλ‘œ μ„€μ •λ˜λŠ” 값을 μ˜λ―Έν•˜λŠ” κΈ°λ³Έ λ§€κ°œλ³€μˆ˜ 이름

ν”„λ‘œνΌν‹° μ˜΅μ €λ²„

class TriangleAndSquare {
    var triangle: EquilateralTriangle {
        willSet {
            square.sideLength = newValue.sideLength
        }
    }
    var square: Square {
        willSet {
            triangle.sideLength = newValue.sideLength
        }
    }
    // μƒλž΅...
}

willSet: ν”„λ‘œνΌν‹° 값이 λ³€κ²½λ˜κΈ° 직전에 ν˜ΈμΆœλ˜λŠ” μ˜΅μ €λ²„

didSet: ν”„λ‘œνΌν‹° 값이 λ³€κ²½λœ 직후에 ν˜ΈμΆœλ˜λŠ” μ˜΅μ €λ²„

μ˜΅μ…”λ„ 체이닝

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength

μ˜΅μ…”λ„ 체이닝(Optional Chaining): μ˜΅μ…”λ„ 값이 nil이 아닐 λ•Œλ§Œ ν”„λ‘œνΌν‹°, λ©”μ„œλ“œ 등에 μ ‘κ·Όν•˜λŠ” κΈ°λŠ₯

πŸ“Œ μ—΄κ±°ν˜•κ³Ό ꡬ쑰체 (Enumerations and Structures)

μ—΄κ±°ν˜• μ •μ˜μ™€ μ‚¬μš©

enum Rank: Int {
    case ace = 1
    case two, three, four, five, six, seven, eight, nine, ten
    case jack, queen, king
    
    func simpleDescription() -> String {
        // λ©”μ„œλ“œ κ΅¬ν˜„...
    }
}
let ace = Rank.ace
let aceRawValue = ace.rawValue  // 1

enum: μ—΄κ±°ν˜•μ„ μ •μ˜ν•˜λŠ” ν‚€μ›Œλ“œ

case: μ—΄κ±°ν˜•μ˜ 각 μΌ€μ΄μŠ€λ₯Ό μ •μ˜ν•˜λŠ” ν‚€μ›Œλ“œ

rawValue: μ—΄κ±°ν˜• μΌ€μ΄μŠ€μ˜ μ›μ‹œ 값에 μ ‘κ·Όν•˜λŠ” ν”„λ‘œνΌν‹°

μ—°κ΄€ 값을 κ°€μ§„ μ—΄κ±°ν˜•

enum ServerResponse {
    case result(String, String)
    case failure(String)
}

let success = ServerResponse.result("6:00 am", "8:09 pm")

switch success {
case let .result(sunrise, sunset):
    print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
case let .failure(message):
    print("Failure... \(message)")
}

μ—°κ΄€ κ°’(Associated Value): μ—΄κ±°ν˜• μΌ€μ΄μŠ€κ°€ μ €μž₯ν•  수 μžˆλŠ” μΆ”κ°€ 정보

ꡬ쑰체 μ •μ˜μ™€ μ‚¬μš©

struct Card {
    var rank: Rank
    var suit: Suit
    
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
}
let threeOfSpades = Card(rank: .three, suit: .spades)

struct: ꡬ쑰체λ₯Ό μ •μ˜ν•˜λŠ” ν‚€μ›Œλ“œ

ꡬ쑰체와 클래슀의 차이점: κ΅¬μ‘°μ²΄λŠ” κ°’ νƒ€μž…μ΄κ³ , ν΄λž˜μŠ€λŠ” μ°Έμ‘° νƒ€μž…

πŸ“Œ λ™μ‹œμ„± (Concurrency)

비동기 ν•¨μˆ˜

func fetchUserID(from server: String) async -> Int {
    if server == "primary" {
        return 97
    }
    return 501
}

async: 비동기 ν•¨μˆ˜λ₯Ό μ„ μ–Έν•˜λŠ” ν‚€μ›Œλ“œ

비동기 ν•¨μˆ˜: 싀행을 μΌμ‹œ μ€‘λ‹¨ν•˜κ³  λ‚˜μ€‘μ— λ‹€μ‹œ μ‹œμž‘ν•  수 μžˆλŠ” ν•¨μˆ˜

비동기 ν•¨μˆ˜ 호좜

func fetchUsername(from server: String) async -> String {
    let userID = await fetchUserID(from: server)
    // μƒλž΅...
}

await: 비동기 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κ³  κ²°κ³Όλ₯Ό κΈ°λ‹€λ¦¬λŠ” ν‚€μ›Œλ“œ

병렬 비동기 μž‘μ—…

func connectUser(to server: String) async {
    async let userID = fetchUserID(from: server)
    async let username = fetchUsername(from: server)
    let greeting = await "Hello \(username), user ID \(userID)"
    print(greeting)
}

async let: 비동기 μž‘μ—…μ„ λ³‘λ ¬λ‘œ μ‹œμž‘ν•˜λŠ” ꡬ문

TaskGroup

let userIDs = await withTaskGroup(of: Int.self) { group in
    for server in ["primary", "secondary", "development"] {
        group.addTask {
            return await fetchUserID(from: server)
        }
    }
    
    // κ²°κ³Ό μˆ˜μ§‘...
}

withTaskGroup: μ—¬λŸ¬ 비동기 μž‘μ—…μ„ κ·Έλ£Ήν™”ν•˜μ—¬ κ΄€λ¦¬ν•˜λŠ” ν•¨μˆ˜

μ•‘ν„° (Actor)

actor ServerConnection {
    var server: String = "primary"
    private var activeUsers: [Int] = []
    
    func connect() async -> Int {
        let userID = await fetchUserID(from: server)
        activeUsers.append(userID)
        return userID
    }
}

actor: λ™μ‹œμ„± μ»¨ν…μŠ€νŠΈμ—μ„œ μ•ˆμ „ν•˜κ²Œ μƒνƒœλ₯Ό κ³΅μœ ν•  수 μžˆλŠ” μ°Έμ‘° νƒ€μž…

πŸ“Œ ν”„λ‘œν† μ½œκ³Ό ν™•μž₯ (Protocols and Extensions)

ν”„λ‘œν† μ½œ μ •μ˜

protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}

protocol: ν”„λ‘œν† μ½œμ„ μ •μ˜ν•˜λŠ” ν‚€μ›Œλ“œ

{ get }: 읽기 μ „μš© ν”„λ‘œνΌν‹°λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μ§€μ •μž

mutating: κ΅¬μ‘°μ²΄λ‚˜ μ—΄κ±°ν˜• λ©”μ„œλ“œκ°€ selfλ₯Ό μˆ˜μ •ν•  수 μžˆμŒμ„ λ‚˜νƒ€λ‚΄λŠ” ν‚€μ›Œλ“œ

ν”„λ‘œν† μ½œ 채택

class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 69105
    func adjust() {
        simpleDescription += "  Now 100% adjusted."
    }
}

struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}

ν™•μž₯ (Extension)

extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }
    mutating func adjust() {
        self += 42
    }
}
print(7.simpleDescription)  // "The number 7"

extension: κΈ°μ‘΄ νƒ€μž…μ— μƒˆλ‘œμš΄ κΈ°λŠ₯을 μΆ”κ°€ν•˜λŠ” ν‚€μ›Œλ“œ

πŸ“Œ μ—λŸ¬ 처리 (Error Handling)

μ—λŸ¬ μ •μ˜

enum PrinterError: Error {
    case outOfPaper
    case noToner
    case onFire
}

Error: Swift의 μ—λŸ¬ 처리 λ©”μ»€λ‹ˆμ¦˜μ„ μœ„ν•œ ν”„λ‘œν† μ½œ

throws ν‚€μ›Œλ“œμ™€ μ—λŸ¬ λ˜μ§€κΈ°

func send(job: Int, toPrinter printerName: String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.noToner
    }
    return "Job sent"
}

throws: ν•¨μˆ˜κ°€ μ—λŸ¬λ₯Ό 던질 수 μžˆμŒμ„ λ‚˜νƒ€λ‚΄λŠ” ν‚€μ›Œλ“œ

throw: μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚€λŠ” ν‚€μ›Œλ“œ

do-catch둜 μ—λŸ¬ 처리

do {
    let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
    print(printerResponse)
} catch {
    print(error)
}

do-catch: μ—λŸ¬λ₯Ό μ²˜λ¦¬ν•˜λŠ” ꡬ문

try: μ—λŸ¬λ₯Ό 던질 수 μžˆλŠ” ν•¨μˆ˜ ν˜ΈμΆœμ— μ‚¬μš©ν•˜λŠ” ν‚€μ›Œλ“œ

λ‹€μ–‘ν•œ μ—λŸ¬ 처리 방법

// try? - μ˜΅μ…”λ„ κ²°κ³Ό λ°˜ν™˜
let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")

// defer - ν•¨μˆ˜ μ’…λ£Œ μ‹œ μ‹€ν–‰λ˜λŠ” μ½”λ“œ 블둝
func fridgeContains(_ food: String) -> Bool {
    fridgeIsOpen = true
    defer {
        fridgeIsOpen = false
    }
    // ν•¨μˆ˜ κ΅¬ν˜„...
}

try?: μ—λŸ¬κ°€ λ°œμƒν•˜λ©΄ nil을 λ°˜ν™˜ν•˜λŠ” μ—λŸ¬ 처리 방식

defer: ν•¨μˆ˜κ°€ μ’…λ£Œλ  λ•Œ μ‹€ν–‰λ˜λŠ” μ½”λ“œ 블둝을 μ •μ˜ν•˜λŠ” ν‚€μ›Œλ“œ

πŸ“Œ μ œλ„ˆλ¦­ (Generics)

μ œλ„ˆλ¦­ ν•¨μˆ˜

func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
    var result = [Item]()
    for _ in 0..<numberOfTimes {
        result.append(item)
    }
    return result
}
makeArray(repeating: "knock", numberOfTimes: 4)

μ œλ„ˆλ¦­(Generic): νƒ€μž…μ— μœ μ—°ν•˜κ²Œ μž‘λ™ν•˜λŠ” μ½”λ“œλ₯Ό μž‘μ„±ν•  수 있게 ν•΄μ£ΌλŠ” κΈ°λŠ₯

<Item>: νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό μ •μ˜ν•˜λŠ” ꡬ문

μ œλ„ˆλ¦­ νƒ€μž…

enum OptionalValue<Wrapped> {
    case none
    case some(Wrapped)
}
var possibleInteger: OptionalValue<Int> = .none

μ œμ•½ 쑰건 μΆ”κ°€

func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool
    where T.Element: Equatable, T.Element == U.Element
{
    // ν•¨μˆ˜ κ΅¬ν˜„...
}

where 절: μ œλ„€λ¦­ νƒ€μž…μ— μ œμ•½ 쑰건을 μΆ”κ°€ν•˜λŠ” ꡬ문

Sequence: μš”μ†Œμ— 순차적으둜 μ ‘κ·Όν•  수 μžˆλŠ” νƒ€μž…μ„ μ •μ˜ν•˜λŠ” ν”„λ‘œν† μ½œ

Equatable: κ°’μ˜ 동등성을 비ꡐ할 수 μžˆλŠ” νƒ€μž…μ„ μ •μ˜ν•˜λŠ” ν”„λ‘œν† μ½œ


μ΄μƒμœΌλ‘œ Swift μ–Έμ–΄μ˜ κΈ°λ³Έ 문법뢀터 κ³ κΈ‰ κΈ°λŠ₯κΉŒμ§€ 핡심 λ‚΄μš©μ„ μ‚΄νŽ΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. SwiftλŠ” μ•ˆμ „μ„±, μ„±λŠ₯, ν‘œν˜„λ ₯을 λͺ¨λ‘ κ°–μΆ˜ ν˜„λŒ€μ μΈ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λ‘œ, iOS, macOS, watchOS, tvOS μ• ν”Œλ¦¬μΌ€μ΄μ…˜ κ°œλ°œμ— μ‚¬μš©λ©λ‹ˆλ‹€.