Extension 

: 이미 정의된 타입에 새 속성 또는 메서드 추가

* extension 사용하여 정의

* override는 불가능

extension Int {
    var squareof: Int { return self * self }
}

let num = 4.squareof
print("4의 제곱은 \(num)입니다.") //4의 제곱은 16입니다.

 

 

 

'iOS' 카테고리의 다른 글

[iOS/Swift] 8. 프로토콜, Any, 타입 캐스팅  (0) 2021.02.09
[iOS/Swift] 7. Enum(Enumeration)  (0) 2021.02.09
[iOS/Swift] 6. 튜플(Tuple)  (0) 2021.02.09
[iOS/Swift] 5. 클래스, 구조체  (0) 2021.02.09
[iOS/Swift] 4. 함수, 클로저  (0) 2021.02.08

 

 프로토콜 

: 최소한으로 가져야 할 속성. 정의만 함

 

* 프로토콜을 적용(Conform)시키면 프로토콜에 정의된 속성, 메서드를 모두 구현해야 함

* 프로토콜을 다른 프로토콜에 적용시킬 수도 있음

protocol Have {
    var student: String? { get }
    var what: String { get }
    
    func have()
}

struct Class: Have {
    var student: String?
    var what: String
    
    func have() {
        print("\(self.student) has \(self.what) class.")
    }
}

struct Club: Have {
    var student: String?
    var what: string
    
    func have() {
    print("\(self.student) is in \(what) club.")
    }
}

* CustomStringConvertible

public protocol CustomStringConvertible {
    /// A textual representation of `self`.
    public var description: String { get }
}

struct Student: CustomStringConvertible {
    var name: String
    var description: String {
        return "이름: \(self.name)"
    }
}

let student = Student(name: "ahhye")
print(student) //ahhye

 

 Any 

: Any는 모든 타입에 대응하고 AnyObject는 모든 객체에 대응함

* Any도 프로토콜

let num: Any = 5
let str: Any = "Hello World"
let obj: AnyObject = Student()

 

 

 

 타입 캐스팅(Type Casting) 

 

 다운 캐스팅(Down Casting) 

: as 를 이용해서 작은 범위로

* Any는 as? 로 옵셔널을 취해야 함

let num: Int? = anyNum as? Int

//옵셔널 바인딩
if let num = anyNum as? Int {
    print(num)
}

 

 타입 검사 

* is 를 사용

print(anyNum is Int) //true
print(anyNum is Any) //true

 

 

 

'iOS' 카테고리의 다른 글

[iOS/Swift] 9. 익스텐션(Extension)  (0) 2021.02.09
[iOS/Swift] 7. Enum(Enumeration)  (0) 2021.02.09
[iOS/Swift] 6. 튜플(Tuple)  (0) 2021.02.09
[iOS/Swift] 5. 클래스, 구조체  (0) 2021.02.09
[iOS/Swift] 4. 함수, 클로저  (0) 2021.02.08

 

 Enum 

: 열거형

* rawValue로 값 접근 (Int, String을 값으로 가질 수 있음)

* rawValue를 가지지 않아도 됨

enum Days: Int {
    case sun = 0
    case mon
    case tue
    case wed
    case thu
    case fri
    case sat
    
    func dayInfo() -> String {
        switch self {
        case .sun:
            return "일요일"
        case .mon:
            return "월요일"
        ...
        }
    }
}

let tuesday = Days.tue
print(tuesday.rawValue) //2
print(tuesday.dayInfo()) //화요일

let friday = Days(rawValue: 5)
print(friday) //Optional(Days.fri)
let sunday = Days(rawValue:7)
print(sunday) //nil
let today: Days = .tue

 

 

 

'iOS' 카테고리의 다른 글

[iOS/Swift] 9. 익스텐션(Extension)  (0) 2021.02.09
[iOS/Swift] 8. 프로토콜, Any, 타입 캐스팅  (0) 2021.02.09
[iOS/Swift] 6. 튜플(Tuple)  (0) 2021.02.09
[iOS/Swift] 5. 클래스, 구조체  (0) 2021.02.09
[iOS/Swift] 4. 함수, 클로저  (0) 2021.02.08

 

 튜플 

: 길이가 고정된 어떠한 값들의 묶음

* 온점( . )을 사용하여 값 접근

var studentInfo: (String, Int) = ("ahhye", 4)
studentInfo.0 //ahhye
studentInfo.1 = 3

var classInfo: (className: String, prof: String) = (className: "iOS Programming", prof: "Kim")
classInfo.className //iOS Programming
classInfo.prof = "Lee"

 

* 여러 변수에 값 지정

let (name, grade) = ("ahhye", 4)
name //ahhye
grade //4

 

* 튜플에 저장된 값 무시

let (name, _) = ("ahhye", 4)
name //ahhye

 

 

 

 

 클래스와 구조체 비교 

  클래스(Class) 구조체(Structure)
정의 class struct
상속 가능 불가능
값 접근 참조 복사

 

 

 Properties (속성) 

 

 Stored Property 

: 값 자체를 가지고 있음

 

 Computed Property 

: 연산 수행 후 결과 반환

* get, set 으로 정의

* set은 newValue로 새로 설정될 값 접근

 

 

 

 클래스 

class Student {
    var name: String?
    var grade: Int?
    
    init() {
        self.grade = 1
    }
    
    deinit {
        print("메모리 해제") //메모리에서 해제된 직후 호출
    }
    
    init(name: String?, grade: Int?) {
        self.name = name
        self.grade = grade
    }
    
    func studentInfo() -> String {
        if let name = self.name {
            return "Student name: \(name)"
        } else {
            return "No Info"
        }
    }
}

var student1 = Student()
student1.name = "ahhye"
print(student1.studentInfo()) //Student name: ahhye

var student2 = Student(name: "ahhye", grade: 4)

* 상속

class Major {
    let major = "CE"
}

class Student: Major {
    var name: String?
    var grade: Int
    
    override init() {
        self.grade = 1
        super.init() //상위 클래스 생성자. 이전에 self 접근하면 컴파일 에러!
    }

}

var student1 = Student()
print(student1.major) //CE

 

 

 

 구조체 

struct Classes {
    var name: String?
    var prof: String?
    
    init() {
        self.prof = "None"
    }
    
    func classtInfo() -> String {
        if let name = self.name {
            return "Class name: \(name)"
        } else {
            return "No Info"
        }
    }
}

var class1 = Classes()
class1.name = "iOS Programming"
print(class1.classInfo()) //Class name: iOS Programming

* Computed Property

* didSet: 속성 값이 변경된 직후 호출(기존 값: oldValue로 접근)

* willSet: 속성 값이 변경되기 직전 호출(새로운 값: newValue로 접근)

struct Classes {
    var name: String? {
        didSet (oldValue) {
            ...
        }
        willSet (newValue) {
            ...
        }
    }
    var prof: String? {
        get {
            if let prof = self.prof {
                return prof
            } else {
                return nil
            }
        }
        set {
            if let newValue = newValue {
                self.prof = prof
            } else {
                self.prof = nil
            }
        }
    }

 

 

 

 

 

 

 함수 

* func 키워드, ->(반환 타입 지정)

* 함수 호출 시 파라미터 이름 함께 써줘야 함

func MyName(name: String) -> String {
    var string = "제 이름은 \(name)입니다.\n"
    return string
}

MyName(name: "ahhye")
func MyName(userName name: String) -> String {
    var string = "제 이름은 \(name)입니다.\n"
    return string
}

MyName(userName: "ahhye")

* 기본값이 지정된 파라미터는 호출 시 생략 가능

func MyName(_ name: String) -> String {
    var string = "제 이름은 \(name)입니다.\n"
    return string
}

MyName("ahhye")

* Variadic Parameters

func MyName(name: String...) -> String {
    var string = "제 이름은 \(name)입니다.\n"
    return string
}

MyName("ahhye", "eunseo", "jisu", "yuhyeon")

* 함수 중첩

func Hello(name: String) {
    func MyName(name: String) -> String {
        var string = "제 이름은 \(name)입니다.\n"
        return string
    }
    
    print(MyName(name: name))
}

* 함수 반환

func Hello(name: String) -> (String) -> String { //내부 함수의 파라미터가 여러 개일 경우 (String, String, ..)
    func MyName(name: String) -> String {
        var string = "제 이름은 \(name)입니다.\n"
        return string
    }
    
    return MyName
}

 

 

 

 클로저 (Closure) 

: 이름이 없는 함수 (중괄호 {} 로 감싸지고, 파라미터 받을 수 있으며 값 반환도 가능)

* in 으로 코드 분리

func Hello(message: String) -> (String) -> String {
    return { name in
        return name + message
    }
}
func Hello(message: String) -> (String) -> String {
    return { 
        return $0 + message
    }
}
func Hello(message: String) -> (String) -> String {
    return { $0 + message }
}
let name: (String) -> String = { "제 이름은 " + $0 + "입니다." }
let name: ((String) -> String)? //옵셔널

 

let numbers = [3, 2, 4, 6, 1, 9, 8]

let sorted = numbers.sort { $0 < $1 }

let odds = numbers.filter { $0 % 2 != 0 }

let mult2 = numbers.map { $0 * 2 }

numbers.reduce(0) { $0 + $1 } //33
numbers.reduce(0, +) //33

 

 

 

 

 옵셔널 

: 어떤 값을 가질 수도 있고 값을 가지지 않을 수도(nil) 있는 변수

* 물음표( ? )를 사용하여 표시

var name: String = "Ahhye"
name = nil //컴파일 에러

var phone: String?
var email: String? = nil
print(phone) //nil
print(email) //nil

phone = "01012345678"
print(phone) //Optional(01012345678)

* 옵셔널이 아닌 변수에 옵셔널 변수 대입 불가능

 

 

 옵셔널 바인딩(Optional Binding) 

: 옵셔널 값이 존재하는지 확인 후 존재한다면 다른 변수에 그 값을 대입시키는 것

* if let/var 사용

* 여러 옵셔널을 바인딩할 때는 쉼표( , )로 구분하며 모든 옵셔널의 값이 존재해야 if문 실행

var optionalPhone: String? //nil

if let phone = optionalPhone {
    print(phone) //optionalPhone의 값이 nil이므로 실행하지 않음
}

var optionalEmail: String? = "abc123@aaaa.com"

if let email = optionalEmail {
    print(email) //Optional(abc123@aaaa.com)
}

var optionalGender: String? = "Female"
var optionalName: String? = "Ahhye"

if let gender = optionalGender, 
   name = optionalName {
    //모든 옵셔널의 값이 존재하므로 if문 실행
}

* 바인딩된 값의 조건을 정의할 때는 쉼표( , ) 사용

var optionalBrithyear: Int? = 1998

if let birthyear = optionalBirthyear, birthyear < 2002 {
//옵셔널 값이 존재하고 조건에 해당되므로 if문 실행
}

if let birthyear = optionalBirthyear {
    if age < 2002 {
    //이렇게도 쓸 수 있음
    }
}

 

 

 

 Unwrapping 

 

 Forced Upwrapping 

* 느낌표( ! ) 사용

* 옵셔널 값이 nil인 경우 런타임 에러 발생

print(optionalBirthyear) //Optional("1998")
print(optionalBirthyear!) //1998

 

 Implicitly Upwrapped Optional 

* 옵셔널 정의 시 물음표( ? ) 대신 느낌표( ! )를 붙이는 경우

* 바인딩이나 upwrapping 없이 값에 바로 접근 가능

var name: String! = "ahhye"
print(name) //ahhye

var name: String! //nil
print(name) //런타임 에러

 

 

 

 옵셔널 체이닝(Optional Chaining) 

* 인스턴스 내부의 옵셔널일 수 있는 값이 nil인지 확인할 수 있는 방법

* 옵셔널 바인딩 과정을 물음표( ? )로 줄여줌

 

 

 

 조건문 

 

 if문 

* 조건절에 Bool 타입을 사용해야 함

var x: Int = 0
if !x { ... } //컴파일 에러
if x == 0 { ... }
if arr.isEmpty { ... }
var score = 95
var grade = ""

if score/10 == 9 || score/10 == 10 {
    grade = "A"
} else if score/10 == 8 {
    grade = "B"
} else if score/10 == 7 {
    grade = "C"
} else if score/10 == 6 {
    grade = "D"
} else {
    grade = "F"
}

grade //A

 

 Switch문 

* fallthrough를 지원하지 않으므로(관련 없는 case문은 실행하지 않고 switch문을 빠져 나감) break는 필요 없음.

* fallthrough를 원한다면 case문에 fallthrough 추가

* case문에 내용이 없을 경우 에러

* 하나의 case에 여러 값을 조건으로 할 때는 쉼표( , )로 구분

var score = 95
var grade = ""

switch score/10 {
case 9, 10:
    grade = "A"
    //fallthrough
case 8:
    grade = "B"
case 7:
    grade = "C"
case 6:
    grade = "D"
default:
    grade = "F"
}

grade //A

 

 

 

 반복문 

 

 for문 

for i in 0..<10 {
    print(i) //0~9
}

for _ in 0..<10 {
    print("Hello World!") //10번 반복 출력
}
let names: [String] = ["Ahhye", "Eunseo", "Jisu", "Yuhyeon"]

for name in names {
    print("제 이름은 \(name)입니다.")
}

 

 while문 

var num = 0

while num < 10 {
    print(num)
    num += 1
}

 

 repeat-while문 

* do-while문과 유사

var num = 0

repeat {
    print(num)
    num += 1
} while num < 10

 

 

+ Recent posts