μλ νμΈμ. μ€λμ 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 μ ν리μΌμ΄μ κ°λ°μ μ¬μ©λ©λλ€.
'π₯ Bread Basics > Swift' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Swift 곡μ λ¬Έμ μ 리 - ν΄λ‘μ (Closures) (0) | 2025.04.11 |
---|---|
Swift 곡μ λ¬Έμ μ 리 - ν¨μ (Functions) (0) | 2025.04.11 |
Swift 곡μ λ¬Έμ μ 리 - μ μ΄ νλ¦ (Control Flow) (0) | 2025.04.10 |
Swift 곡μ λ¬Έμ μ 리 - 컬λ μ νμ (Collection Types) (0) | 2025.04.10 |
Swift 곡μ λ¬Έμ μ 리 - λ¬Έμμ΄κ³Ό λ¬Έμ (Strings and Characters) (0) | 2025.04.10 |
Swift 곡μ λ¬Έμ μ 리 - κΈ°λ³Έ μ°μ°μ (Basic Operators) (0) | 2025.04.10 |
Swift 곡μ λ¬Έμ μ 리 - κΈ°λ³Έ(The Basics)(2/2) (0) | 2025.04.10 |
Swift 곡μ λ¬Έμ μ 리 - κΈ°λ³Έ(The Basics)(1/2) (0) | 2025.04.10 |