ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • yagom 의 iOS Swift 홈페이지 강좌
    기술/iOS 2022. 2. 19. 14:00

    기초 개념

    이름 짓기

    CamelCase 를 사용함 EASY EASY~

    콘솔 로그

    • print: 단순 문자열 출력
    • dump: 인스턴스의 자세한 요소들까지 전부 출력 해줌

    보간법

    \()

    상수와 개념

    함수형 패러다임 답게 상수표현이 많이 등장함

    띄워쓰기 잘못쓰면 문제가 생김 ( 에바쎄바 )

    • let: 상수
      • let 이름: 타입 = 값
      • 상수를 먼저 선언하고 나중에 한번 값을 넣어줄 수 있음
    • var: 변수
      • var 이름: 타입 = 값
      • 변수도 선언하고 나중에 사용 가능

    데이터 타입

    기본 데이터 타입

    데이터 타입은 아주 정확히 할당해야한다.

    • Bool
      • 0, 1 사용 가능 ( 에바쎄바... )
    • Int, UInt
      • Int: 64bit
      • UnsingedInt: 음수 안됨, Int 도 못넣음
    • Float, Double
      • Float: 32bit, 정수를 넣어도 됨 ( 또라이 아니냐 )
      • Double: 64bit, 정수를 넣어도 됨, Float 못넣음
    • Character, String
      • Character: Unicode 를 사용하는 문자
      • String: Unicode 를 사용하는 문자열

    Any, AnyObject, nil

    • Any: Swift 의 모든 타입을 지칭하는 키워드
      • Any 타입은 다른 변수에 할당이 불가하다.
    • AnyObject: Swift 의 모든 클래스를 지칭하는 키워드
      • 클래스의 인스턴스만 가질 수 있음
    • nil: 없음을 표현하는 키워드
      • Any, AnyObject 에 할당 불가

    컬렉션 타입

    • Array: 순서가 있는 리스트
    • Dictionary: 키와 값으로 이루어진 컬렉션
      • Dict.removeValue(forKey: “Key”) == Dict[”Key”] = nil
      • **let someValue: String = Dict[”name”] 이 문법은 name 이 있을지 없을 지 몰라 불가하다.**
    • Set: 순서가 없고, 멤버가 유일한 컬렉션

    함수

    함수 기본

    func 함수이름(매개변수: 타입) -> 반환타입 {
        함수 구현부
            return 구현값
    }

    반환 값이 없는 경우 Void, 없다(nil)를 표현하는 타입, 생략 가능

    함수를 호출할 때 반드시 인자들과 값을 모두 작성해야한다.

    함수 고급

    • 매개변수 기본값
    • 전달인자 레이블
      • 함수 중복 정의가 가능함
      • 전달인자를 사용하면 인자에서는 꼭 전달인자 레이블을 사용해야 함
    • 가변 매개변수
      • ... : 함수 당 하나, 맨 뒤에 위치
      • 당연하지만 인자로 nil 은 안됨
    • 함수 타입 표현
      • 일급 객체이기 때문에 변수에 할당 가능
      • (타입) → 반환 타입

    조건문

    if-else

    condition 소괄호 생략 가능

    조건문에는 항상 Bool 타입이 들어와야 함 ( int 안돼 )

    if condition {
        statements
    } else if condition {
      statements
    }

    switch

    • 범위 연산자
    • switch someInteger { case 1..<100: case 101..Int.max: }
    • 정수 외의 대부분의 기본 타입을 사용할 수 있다.
    • break 없어도 무조건 Break
      • fallthrough 를 쓰면 break 를 무효화할 수 있음
    • Default 가 없으면 에러

    반복문

    for-in

    for item in items {
      code
    }
    for (name, age) in people {
      code
    }

    while

    조건문의 소괄호는 선택사항

    반드시 Bool 값 ( Int 멈춰! )

    while condition {
    
    }

    repeat-while

    • do-while 과 같음, do 를 사용하지 않는 이유는 오류 처리에 사용하기 때문
    repeat {
      code
    } while condition

    옵셔널

    • 값이 있을수도 없을수도 있음
    func someFunction(someOptionalParam: Int?){}

    암시적 추출 옵셔널

    Int!
    • 기존 변수처럼 사용 가능
    • 런타임 오류 발생 가능

    명시적 추출 옵셔널

    Int?
    • 기존 변수처럼 사용 불가

    옵셔널 추출

    Optional Binding - if-let

    • nil 체크 + 안전한 꺼냄
    if let name: String = myName {
      print(name)
    } else {
      print(it's nil!!)
    }

    Force Unwrapping

    • 강제 추출하는 방법
    • 런타임 오류 발생 가능
    • 암시적 추출 옵셔널을 사용하면 강제로 이 방법으로 변수가 사용됨
    var myName: String? = "yagom"
    print(myName!)

    구조체

    struct 이름 {
        var property: Int = 100 // 가변 프로퍼티
        let property: Int = 100 // 불변 프로퍼티
    
        static var typeProperty: Int = 100 // 타입 프로퍼티
    
        // 메서드
        func method(){
    
        }
    
        static func method() {} // 타입 메서드
    }
    • 인스턴스화를 let 으로 했을 때 가변 프로퍼티도 변경 불가
    • 타입 메서드, 프로퍼티는 구조체만 사용 가능하고, 인스턴스는 사용 불가
    • 타입 메서드, 인스턴스 메서드는 동일한 이름 사용 가능

    클래스

    • 구조체는 값, 클래스는 참조
    • 인스턴스화를 let 으로 했을 때 가변 프로퍼티도 변경 가능
    class 이름 {
        var property: Int = 100 // 가변 프로퍼티
        let property: Int = 100 // 불변 프로퍼티
    
        static var typeProperty: Int = 100 // 타입 프로퍼티
    
        // 메서드
        func method(){
    
        }
    
        static func method() {} // 타입 메서드 ( 상속 시 재정의 불가 )
        class func method() {} // 타입 메서드 ( 상속 시 재정의 가능 )
    }

    열거형

    enum 이름 {
      case 이름
        case 이름2
        case 이름3, 이름4, 이름5
    }
    • enum 은 타입이기때문에 대문자 정의
    • 선언 시 타입 명시, 이후 생략 가능
    • switch 문과 같이 사용 가능, Case 를 모두 정의하면 Default 생략 가능
    • 원시값 사용 가능
      • 자동으로 1씩 증가함
      • 문자열의 경우 케이스의 이름 고대로 가져옴
    • enum Fruit: Int { case apple = 0 case grape = 1 case peach }
    • Optional 타입임
    • 메서드를 가질 수 있음

    값 / 참조 타입

    Untitled

    구조체는 언제 사용하나?

    • 연관된 데이터를 모아 하나의 데이터 타입으로 표현하고 싶을 때
    • 다른 객체 또는 함수 등으로 전달될 때 참조가 아닌 복사를 원할 때
    • 자신을 상속할 필요가 없거나, 자신이 다른 타입을 상속받을 필요가 없을 때
    • Apple 프레임워크에서 프로그래밍할때 주로 클래스 사용
    • Swift 프레임워크에서 프로그래밍할 때 주로 구조체 사용

    값 / 참조

    • Value
      • 데이터를 복사해서 전달
    • Reference
      • 참조를 전달

    클로저

    • 일급시민으로 전달인자, 변수, 상수 등으로 전달 가능
    • 함수는 클로저의 일종으로, 이름이 있는 클로저
    • 함수의 Callback 으로서도 많이 사용됨

    클로저 고급

    후행 클로저

    result = calculate(a: 10, b: 10) { (left: Int, right: Int) -> Int in
        return left + right
    }

    반환 타입 생략

    result = calculate(a: 10, b: 10, method: { (left: Int, right: Int) in
        return left + right
    })
    
    print(result) // 20
    
    // 후행클로저와 함께 사용할 수도 있습니다
    result = calculate(a: 10, b: 10) { (left: Int, right: Int) in
        return left + right
    }

    단축 인자이름

    result = calculate(a: 10, b: 10, method: {
        return $0 + $1
    })
    
    print(result) // 20
    
    // 당연히 후행 클로저와 함께 사용할 수 있습니다
    result = calculate(a: 10, b: 10) {
        return $0 + $1
    }
    
    print(result) // 20

    암시적 반환 표현

    result = calculate(a: 10, b: 10) {
        $0 + $1
    }
    
    print(result) // 20
    
    // 간결하게 한 줄로 표현해 줄 수도 있습니다
    result = calculate(a: 10, b: 10) { $0 + $1 }

    프로퍼티

    인스턴스 저장 프로퍼티

    struct Student {
        var age: Int = 0
    }

    타입 저장 프로퍼티

    struct Student {
        static var age: Int = 0
    }

    인스턴스 연산 프로퍼티

    • get 만 있으면 읽기 전용
    • 읽기 전용에서는 get 을 생략할 수 있음
    • set 은 매개변수를 newValue 로 생략할 수 있음
    • 변수에서 사용 가능
    struct Student {
        var age: Int {
            get {
                return age - 1
            }
            set {
                age = newValue + 1
            }
        }
    }

    타입 연산 프로퍼티

    struct Student {
        static var age: Int {
            return 0
        }
    }
    
    var yagom: Student = Student()
    print(yagom.age)

    프로퍼티 감시자

    프로퍼티 값이 변경될 때 원하는 동작을 수행할 수 있음

    • 암시적으로 newValue, oldValue 로 생략 할 수 있음
    • 연산 프로퍼티와 같이 사용할 수 없음
    struct Money {
        // 프로퍼티 감시자 사용
        var currencyRate: Double = 1100 {
            willSet(newRate) {
                print("환율이 \(currencyRate)에서 \(newRate)으로 변경될 예정입니다")
            }
    
            didSet(oldRate) {
                print("환율이 \(oldRate)에서 \(currencyRate)으로 변경되었습니다")
            }
        }
    }

    상속

    • 클래스, 프로토콜에서 가능
    • 열거형, 구조체 불가
    • 다중 상속 지원 불가
    class 부모 클래스 {
        func method() {} // 재정의 가능
        final func finalMethod() {} // final 을 사용하여 재정의 불가하도록 할 수 있음
        static func typeMethod() {} // 재정의 불가
        class func tyclassMethod() {} // 재정의 가능
        final class func finalcClassMethod() {} // 재정의 불가
    }
    
    class 이름: 부모 클래스 {
        override func method( super.method() ) {} // 재정의 및 부모 클래스 메서드 호출
        override class func classMethod() {} // 재정의
    }

    인스턴스 생성과 소멸

    모든 인스턴스는 초기화와 동시에 모든 프로퍼티에 유효한 값이 할당되어 있어야 한다.

    init

    • Optional 프로퍼티 사용 가능
    • initalizer 여러개 중복 가능
    • 자신의 init 을 호출할 때는 convenience 키워드를 사용
    • 실패 가능한 이니셜라이저 ( init? )
      • 실패하면 nil 을 반환함
    class PersonB {
        var name: String
        var age: Int
        var nickName: String
    
        convenience init(name: String, age: Int, nickName: String) {
                    self.init(name: name, age: age)
            self.name = name
            self.age = age
            self.nickName = nickName
        }
    
            init(name: String, age: Int) {
            self.name = name
            self.age = age
           }
    
            init?(name: String, age: Int) {
            if (0...120).contains(age) == false {
                return nil
            }
            if name.characters.count == 0 {
                return nil
            }
            self.name = name
            self.age = age
            }
    }
    let hana: PersonB = PersonB(name: "hana", age: 20, nickName: "하나")

    deinit

    • 메모리에서 해제될 때 해야할 일을 구현할 수 있음
    class PersonE {
        var name: String
        var pet: Puppy?
        var child: PersonC
        init(name: String, child: PersonC) {
            self.name = name
            self.child = child
        }
        // 인스턴스가 메모리에서 해제되는 시점에 자동 호출
        deinit {
            if let petName = pet?.name {
                print("\(name)가 \(child.name)에게 \(petName)를 인도합니다")
                self.pet?.owner = child
            }
        }
    }

    옵셔널 심화

    옵셔널 체이닝

    func chaining(owner: Person?) {
        if let guardJob = ownner?.home?.guard?job {
        } else {
        }
    }

    nil 병합 연산자

    guardJob = yagom?.home?.guard?.job ?? "슈퍼맨"

    타입 캐스팅

    • 인스턴스의 타입을 확인하는 용도
    • 부모 혹은 자식 클래스의 타입으로 사용할 수 있는지
    Double(value) 는 타입 캐스팅이 아님, Double 인스턴스를 새로 만든 것

    is

    let yagom: UniversityStudent: UniversityStudent()
    
    result = yagom is Person  // true
    result = yagom is Student // true
    result = yagom is UniversityStudent // true

    as

    var mike: Person = UniversityStudent() as Person

    다운 캐스팅

    • as? - 조건부 다운캐스팅
    • mike as? UniversityStudent // 캐스팅 가능 yagom as? UniversityStudent // 캐스팅 불가, nil
    • as! - 강제 다운캐스팅
    mike as? UniversityStudent // 캐스팅 가능
    yagom as? UniversityStudent // 캐스팅 불가, 런타임에러
    • 자식 클래스의 인스턴스로 사용할 수 있도록 인스턴스 타입 정보를 전환한다.

    assert 와 guard

    • 애플리케이션 동작 도중 결과값을 동적으로 확인하고 안전하게 처리할 수 있도록 확인하고 빠르게 처리할 수 있다.

    assert

    • 디버깅중에만 사용됨
    var someInt: Int = 1
    assert(someInt == 0, "someInt != 0"). // 디버깅에서 동작을 중지함

    guard

    • 프로덕션에서도 사용됨
    • 빠른 종료를 위해 사용됨
    • if else 의 축약절정도로 사용됨
    func guard(age: Int?) {
        guard let unwrappedAage = age,
            unwrappedAge < 130
            unwrappedAge >= else {
                print("나이 값 입력이 잘못되었습니다.")
                return // 반드시 return 이 필요함
        }
    }

    프로토콜

    • 인터페이스 정의
    • 구현할거라 선언하면 채택(Adopted)
    • 구현을 실행하면 준수(Conform)
    • 프로토콜은 다중 상속 가능
    struct Person: Talkable {
        // 프로토콜을 구현하여 준수
    }
    • 상속과 함께 쓰려면 상속, 프로토콜, 프로토콜 순으로 작성해야함
    • is, as 사용 가능

    익스텐션

    • 타입을 알고있으면 새로운 기능을 추가할 수 있음
    • 프로토콜 확장 가능
    extension Int {
        var isEven: Bool {
            return self % 2 == 0
        }
    }

    오류처리

    Error

    • 주로 열거형을 통해 오류를 통해 표현함
    • catch 에러를 생략 가능
    • do 만 사용 가능
    • try? 를 사용해서 결과 값을 nil 로 받음
    • try! 를 사용하면 런타임 에러가 발생
    enum VendingMachineError: Error {
        case invalidInput
        case insufficeintFunds(moneyNeeded: Int)
        case outOfStock
    }
    func receiveMoney(_ money: Int) throws {
        guard money > 0 else {
            throw VendingMachinError.invalidInput
        }
    }
    do {
        try receiveMoney(0)
    } catch VendingMachinError.invalidInput{
    
    }

    고차 함수

    • map, filter ,reduce
    • 인자 생략 가능 $0
    • 후행 클로저로 전달 가능

    접근 수준

    • 상위 요소보다 하위 요소가 더 높은 접근 수준을 가질 수 없다.
    • private class AClasee { public func someMethod() {. // private 취급 됨 } }
    • public: 어디서든, 상속 후 재정의 불가
    • open: 클래스와 클래스 멤버에서만 사용 가능, 상속 후 재정의 가능
    • internal: 기본 접근 수준, 모듈레벨
    • filepriavte: 소스파일 내부에서만 사용 가능
    • private: 구현한 범위 내
    • 프로퍼티의 get, set 은 따로 접근 수준 부여가 가능하다.

    프로토콜 지향 언어

    • protocol, extension 을 활용하여 중복을 없앨 수 있음
    • 프로토콜의 요구사항을 익스텐션으로 구현하는 것을 프로토콜 초기구혀닝라고 한다.

    '기술 > iOS' 카테고리의 다른 글

    Swift 5.6 Control Flow  (0) 2022.02.26
    Swift 5.6 Arrays  (0) 2022.02.26
    Swift 5.6 Strings and Characters  (0) 2022.02.25
    Swift 5.6 Basic Operators  (0) 2022.02.25
    Swift 5.6 The Basics  (0) 2022.02.25

    TAG

    댓글 0

Designed by Tistory.