SWIFT - 스위프트 오피셜 다큐먼트 부시기 (Digging down swift official guide!)

Contents

  1. Swift Brief Introduction
  2. The Basic Values
  3. Operators
  4. Control Flow
  5. Function & Closures
  6. Class & Structure
  7. Properties
  8. Method
  9. Inheritance
  10. Initialization

Introduction to Swift

  • Apple’s code: objective-C -> swift (2014)
  • compiled language
  • LLVM compiler
  • IDE(Integrated Development Environment) : Xcode (2003)
  • Package: UIKit, SwiftUI

Basic Values

  • type safe language
    • 변수의 type을 명시해야함. 변수에 명시된 type 외의 값을 넣을 수 없음. 단, swift는 type inference를 지원하기때문에 C언어처럼 모든 변수에 type을 선언할 필요는 없음. Compile 과정에서 swift가 변수에 할당된 값을 보고 type을 유추하기 때문.

variable

  • syntax
    • var
  • naming convention
    • lower camel case (ex. thisIsAnExample)
  • usage
    • 변수의 값(value)이 변경되는 경우 사용
    • constant의 type(ex. Double)과 value의 type(ex. 70)이 일치 해야 함

constant

  • syntax
    • let
  • usage
    • 변수의 값(value)가 변하지 않을 경우 사용. 즉, 고정된 하나의 값이 프로그램 내에 반복적으로 사용될 때 필요함.
    • constant의 type(ex. Double)과 value의 type(ex. 70)이 일치 해야 함 (굳이 type을 정의하지 않아도 컴파일러가 value의 type을 보고 constant의 타입을 지정함=>Type Inference)
let implicitDouble = 70.0
let explicitDouble: Double = 70 

types

Int, Float, Double
var implicitDouble = 70.0
let explicitDouble: Double = 70
String
  • syntax
    • string 내부에서 변수 사용 "\(variable)"
    • multiple lines """string"""
var apple:Int = 1
var orange:Int = 3
print("I have \(apple) apples and \(orange) oranges")
// I have 1 apples and 3 oranges
Bool
Array & Dictionary
  • syntax
    • []
  • array
    var shoppingList = ["water","snack"]
    shoppingList.append("orange") // list append
    
  • dictionary
    var occupations = [
      "Christina" : "programmer",
      "Daewang" : "puppy"
    ]
    occupations["Zooho"] = "data scientist"
    print(occupations)
    // ["Daewang": "puppy", "Zooho": "data scientist", "Christina": "programmer"]
    
tuples
  • syntax
    • ()
  • usage
    • 여러 값들을 그룹에 담을 때 사용함. 서로 다른 타입의 값도 같은 tuple로 묶일 수 있음.
let httpStatus = (statusCode:200, description: "okay")
print("status code is \(httpStatus.statusCode) and messgae is \(httpStatus.description)}")

Initializer

  • initializer
    • int, float, double, string
      • 값을 할당해 initialize
        • ex: var x = 1
      • type 할당을 먼저한 후 값을 지정하여 initialize
        • ex: var x: Int; x = 1
    • list : []()
    • dictionary : [:]()
// dictionary
var emptyDictionary = [String : Float]()
emptyDictionary["name"] = 1
print(emptyDictionary)
// ["name": 1.0]

// list
var tempt = [Any]()
tempt.append("a")
tempt.append(1)
print(tempt)
// ["a", 1]

Optionals

  • definition
    • 값(value)이 있을 수도 없을 수도 있는 타입. C 언어에서는 없었던 개념으로 swift만의 강점이라고 할 수 있음.
    • 값이 있는 경우는 optional을 풀어서 값을 얻음.
    • 값이 없는 경우는 nil(=값이 없음)을 얻음.
  • syntax
    • String?
  • initialize
    • optional에 값을 할당하지 않고 initialize한 경우 초깃값은 nil로 세팅됨.
      • var testNil : Int?
    • optinal에 초깃값을 할당
      • var test: Int? = Int(8)
forced unwrapping
  • optional에 값이 확실히 존재할 때, 그 값을 가져오는 방법을 forced unwrapping이라고 함.
  • syntax
    • optional 변수명 뒤에 느낌표 !를 붙이면 optional의 값만 가져옴.
      • ex. test!
optional binding
  • optional에 값 존재 여부에 따라 분기문을 이용해 다르게 처리하는 방법.
  • syntax
    • if let constantName = someOptional { statement } else {statement}
  • [주의] constantName 변수는 if문 내에서만 사용 가능.
let possibleNumber = "123"
if let actualNumber = Int(possibleNumber) {
    print(print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)"))
}else{
    print("The string \"\(possibleNumber)\" couldn't be converted to an integer")
}
// "The string "123" has an integer value of 123"
nil-coalescing Operator
  • optional에 값이 존재하지 않을 때 (=nil), nil 대신 부여할 값을 지정하는 연산자
  • syntax
    • someOptional ?? substituteValue
let optionalInt: Int?
print(optionalInt)
// nil

if let number = optionalInt {
	print("value is assgined!")
}
// (nothing printed)

let number: Int? = Int("42")
print(number)
// Optional(42)
print("upwrap the number : \(number!)")
// 42

let defaultValue = "default"
let outputOptional = optionalInt ?? defaultValue
print(outputOptional)
// default

Implicitly Unwrapped Optionals

  • definition
    • 항상 값이 존재하는 optional.
    • optional과 같은 타입이지만, 값이 존재하는지 확인하는 과정을 건너뛸 수 있다는 점에서 optional과 다름. 즉, 항상 forced-upwrapping(!)을 할 수 있는 optional.
  • syntax
    • String!
let assumedString : String! =  "implicitly unwrapped optional string"

let optionalString = assumedString 
let implicitString: String = assumedString // implicitString가 타입을 String으로 명시했기 때문에 assumedString(implicitly unwrapped optinal)가 값을 forced-upwrapping한 후 변수에 할당함

print(optionalString) 
// Optional("implicitly unwrapped optional string") // 여전히 optinal 타입
print(implicitString)
// implicitly unwrapped optional string

Operators

ternary conditional operator

  • syntax
    • question ? answer1 : answer2
  • definition
    • ternary operator란 피연산자(operands)를 3개 갖는 연산자를 의미함.
      (unary=> 1개, binary=>2개, ternary=>3개)
    • if question; then answer1 else; answer2; fi 조건문을 한 줄로 처리할 수 있는 연산자.
  • example
    let contentHeight = 40
    let hasHeader = true
    let rowHeight = contentHeight + (hasHeader ? 50 : 20) // if hasHeader is true; return 50; else 20
    print(rowHeight) // 90
    

nil-coalescing operator

  • syntax
    • a ?? b
  • definition
    • 만약 optional 변수의 값이 존재하면 (!= nil) 그 값을 반환하고 그렇지 않으면 nil 대신 다른 값을 반환하는 연산자.
    • a != nil ? a! : b코드를 처리함.
  • example
    let defaultColorName = "red"
    var userDefindedColorName: String? // default is nil
    var colorNameToUse = userDefindedColorName ?? defaultColorName
    print(colorNameToUse) // red 
    userDefindedColorName = "green" // optionalString에 string 값을 할당함
    colorNameToUse = userDefindedColorName ?? defaultColorName
    print(colorNameToUse) // green
    

range operator

  • syntax
    • closed: 1...5
      • 1 이상, 5 이하
    • half-opened: 1..<5
      • 1 이상, 5 미만
      • 파이썬의 range(1,5)와 동일
    • one-sided: 1...
      • 1 이상의 모든 값
      • 시작 값이 없는 경우 (ex. ...100)는 iteration이 불가능
      • 끝 값이 없는 경우 (ex. 2...)는 iteration이 가능함
  • example
let names = ["Anna","Alex", "Brian", "Jack"]
let numberOfPeople = names.count
for i in 0..<numberOfPeople {
    print("Person \(i+1) is called \(names[i])")
}
//Person 1 is called Anna
//Person 2 is called Alex
//Person 3 is called Brian
//Person 4 is called Jack

for name in names[2...]{
    print(name)
}
//Brian
//Jack

let oneSideRange = ...5
print(oneSideRange.contains(7))
// false

Control Flow

template

  • syntax
    • aaa
  • definition
    • aaa
  • example
    aaa
    

conditional

  • if
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
  • switch
    • let x where [condition] 구문은 Python의 x if lambda x : [condition] else False와 같다. 즉, vegetable 변수가 특정 condition을 만족하면 다음 코드를 실행하도록 제어한다.
let vegetable = "red pepper"

switch vegetable {
case "celery":
    print("throw it away")
case "cucumber", "watercress":
    print("make a sandwitch")
case let x where x.hasSuffix("pepper"): // assign value to x if value has "pepper" at the back
    print("Is it a spicy \(x)?")
default:
    "everything goes well with soup."
}
// Is it a spicy red pepper?

loops

  • for-in
let interestingNumbers = [
    "Prime" : [2,3,5,7,11,13],
    "Fibonacci" : [1,1,2,3,5,8],
    "Square" : [1,4,9,16,25]
]
var largest = 0
var largestKeys : String?
for (key, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
            largestKeys = key
            
        }
    }
}
print("largest number : \(largest) in key : \(largestKeys)")
//largest number : 25 in key : Optional("Square")
  • while
var n = 2
while n < 100 {
    n *= 2
}
print(n)
// 128
  • repeat-while
    • 반복을 최소 1번은 이루어진다는 가정 하에 반복문이 조건문보다 앞에 나올 수 있다.
var m = 2
repeat {
    m *= 2
} while m < 100
print(m)
// 128
  • ..< & ...
    • a..<b
      • Python의 range(a,b)와 동일하다. 즉, a 이상, b 미만의 수를 생성한다.
    • a...b
      • Python의 range(a,b+1)과 동일하다. 즉, a 이상, b 이하의 수를 생성한다.
var total = 0
for i in 0..<4 {
    total += i
}
print(total)
// 6

total = 0
for i in 0...4{
    total += i
}
print(total)
// 10

Functions & Closures

functions

parameters
  • keyword argument
    • func function_name(parameter_name : type)
    • ex. func greet(person: String, day: String) -> String
  • no argument label
    • func function_name(_ parameter_name : type)
    • ex. func menu(_ person: String) -> String
  • customized argument label
    • func function_name(customized_label parameter_name : type)
    • ex. func menu(lunch meal: String) -> String
func greet(person: String, day: String) -> String {
    return "Hello \(person), today is \(day)."
}
print(greet(person: "Christina", day: "Sunday"))
// Hello Christina, today is Sunday.
func menu(_ person: String, lunch meal: String) -> String {
    return "Hello \(person), today's meal is \(meal)."
}
print(menu("Chris", lunch: "salad"))
// Hello Chris, today's meal is salad.
returned values
  • 함수의 반환값이 여러개 인 경우 (multiple values), tuple로 반환한다.
  • 반환된 tuple 값은 변수명이나 변수의 인덱스로 얻을 수 있다.
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    var min = scores[0]
    var max = scores[0]
    var sum = 0
    
    for score in scores {
        if score > max {
            max = score
        } else if score < min {
            min = score
        }
        sum += score
    }
    return (min, max, sum)
}

let statistics = calculateStatistics(scores: [5,3,100,3,9])
print(statistics.min)
// 3
print(statistics.0)
// 3
nested functions
  • 함수는 first-class type이다. first-class type이란 다른 함수의 argument로 입력될 수 있고, 다른 함수에서 반환될 수 있는 타입을 말한다.

  • 함수가 다른 함수의 arguments로 입력되는 경우

func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20,19,7,12]
print(hasAnyMatches(list: numbers, condition: lessThanTen))
//true
  • 함수가 다른 함수에서 반환되는 경우
    • 함수의 반환값이 (Int) -> Int라면, 이 함수는 다른 함수를 반환하는 함수이다.
func makeIncrementer() -> ((Int) -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
print(increment(7)) // increment 변수는 곧 addOne 함수
// 8

closure

  • 함수는 closure이다.
    • closure 설명 추가…
  • {}
    • 함수명이 없는 closure 함수 생성
var numbers = [20,19,7,12]
let oddNumbers = numbers.map({ (number: Int) -> Int in
                                if number % 2 == 1 {
                                    return 0
                                } else {
                                    return number
                                }
})
print(oddNumbers)
//[20, 0, 0, 12]

// simple closure(No parameter type, return type, and return statement) when closure has a single statement
let mappedNumbers = numbers.map({ number in 3 * number
})
print(mappedNumbers)
// [60, 57, 21, 36]

// simple closure using parameter index 
let ascendingNumbers = numbers.sorted{ $0 < $1 }
print(ascendingNumbers)
// [7, 12, 19, 20]

Object and Classes

property

  • property에 value assigning 방법
    1. declaration: class 내부에서 값을 할당 (ex. numberOfSides)
    2. initializer : initializer로 값을 할당. initializer 내부에서는 property 앞에 self를 붙여 arguement 변수와 구분해줌 (ex. self.name)
class NamedShape {
    var numberOfSides: Int = 0
    var name: String // require initializer
    
    init(name: String) { // initializer
        self.name = name
    }
    
    func simpleDescription() -> String { // method
        return "A shape with \(numberOfSides) sides."
    }
}

var namedShape = NamedShape(name: "Triangle") // instance
namedShape.numberOfSides = 3
print(namedShape.simpleDescription())
// A shape with 3 sides.

superclass and subclass

  • overriding
    • initializer : super.init()
    • method : override func
class Square: NamedShape {
    var sideLength: Double
    
    init(sideLength: Double, name: String){
        self.sideLength = sideLength
        super.init(name: name) // overrid initializer
        numberOfSides = 4
    }
    
    func area() -> Double {
        return sideLength * sideLength
    }
    
    override func simpleDescription() -> String { // override method
        return "A square with sides of length \(sideLength)"
    }
}
let test = Square(sideLength: 5.2, name: "my test square")
print(test.area())
// A shape triangle with 3 sides.
print(test.simpleDescription())
// A shape with 3 sides.

getter and setter

  • property에 계산의 결과값을 할당하고 싶을 때, getter와 setter를 사용한다.
  • setter
    • property(ex. perimeter )에 값이 할당되면 이 값은 newValue라는 변수에 할당된다.
class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0
    
    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }
    
    var perimeter: Double {
        get {
            return 3.0 * sideLength
        }
        set {
            sideLength = newValue / 3.0
        }
    }
    
    override func simpleDescription() -> String {
        return "A equilateral triangle with sides of length \(sideLength)"
    }
}

var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
print(triangle.perimeter)
// 9.3
triangle.perimeter = 9.9
print(triangle.sideLength)
// 3.3
  • property에 계산한 값을 반환할 필요는 없지만, property에 값을 할당하기 전과 후의 값이 모두 필요할 때 willSetdidSet을 사용한다.
  • willSetdidSet은 instance의 property 값이 변경되는 순간에 작동한다.
// willSet을 사용해 triangle과 square의 sideLength가 항상 일치시키기

class TriangleAndSquare {
    var triangle: EquilateralTriangle {
        willSet {
            square.sideLength = newValue.sideLength
        }
    }
    
    var square: Square {
        willSet {
            triangle.sideLength = newValue.sideLength
        }
    }
    
    init(size: Double, name: String){
        square = Square(sideLength: size, name: name)
        triangle = EquilateralTriangle(sideLength: size, name: name)
    }
}

var triangleAndSquare = TriangleAndSquare(size: 10, name: "another teset shape")
print(triangleAndSquare.square.sideLength)
// 10
print(triangleAndSquare.triangle.sideLength)
// 10
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
print(triangleAndSquare.triangle.sideLength)
// 50

Properties

Methods

Inheritance

Initialization

Reference

Swift Official Language Guide
Swift Official Document