Optional 타입형
var carName: String?
carName = nil //nil
carName = "탱크" //탱크
Swift 에는 Obtional 타입형이라는 것이 있음. String? 이라는 타입형은 Optional String 타입형이라는 것이다 . 주의 ! String 형이 아님. Optional 타입형임.
Optional 이라는 것은 값을 안가질수도 있는 상황(nil)일 때 쓰는 것이다. nil은 0도 아니고, null도 아니다. 값이 없다는 것임.
optional 타입형으로 가져오기 싫으면 !를 붙여서 대입하면 , 값이 있는 것에 대한 타입형이 나옴.
단, 선언할 때 !는 ?와 마찬가지로 optional의 의미를 가짐
let num = Int("10") //num의 타입형은 Int?임
위의 경우는 왜 Int?일까? 변환이 실패할 경우도 있기 때문에 스위프트에서는 이것을 옵셔널 변수로 지정한다
- Forced unwrapping
- Optional binding (if let)
- Optional binding (guard)
- Nil coalescing : 값이 없으면 디폴트 값을 주는 것
// -- Forced unwrapping 단점: nil일 경우 ! 쓰면 에러
print(carName) //Optional("탱크") 출력
print(carName!) //탱크 출력
carName = nil
print(carName!) //에러 - 값이 없기때문.
// -- Optional binding (if let) 장점: nil이여도 에러가 안뜸. 단점: 코드가 늘어남.
if let unwrappedCarName = carName {
print(unwrappedCarName)
} else {
print("Car Name 없다")
}
// -- Optional binding (guard) 위에 보다 조금더 간단
guard let unwrappedCarName = carName else {
print("Car Name 없다")
return
}
print(unwrappedCarName)
// -- Nil coalescing 물음포 뒤에가 nil 일 경우 디폴트값
let unwrappedCarName: String = carName ?? "Car Name 없다"
Closures 클로져
이름이 없는 함수다
인라인 함수 같은 함수임. (인라인 함수 : 함수 호출없이 그 위치에서 바로 실행되는 함수)
근데 클로져는 인라인 함수와 비교가 안될 정도로 간단히 축약이 가능 인자도 필요 없으며, 심지어 Return도 생략해버림
import UIKit
var mulClosure: (Int, Int)-> Int = {$0 * $1} //클로저 축약형
let result = mulClosure(6,2)
//함수인자로 직접 클로저 넣기
func operatefunc(_ a: Int,_ b: Int, operation: (Int,Int) -> Int) -> Int {
let result = operation(a,b)
return result
}
operatefunc(4,2){ a, b in
return a / b
}
바로바로 즉흥적으로 사용 가능한 함수 클로져!
- Capturing
var count = 0
let incrementer = {
count+=1
}
incrementer()
incrementer()
incrementer()
print(count)
클로져에 의해 한번 캡쳐되면 바깥 scope을 벗어나더라도 사용가능하다.
- Trailing Closure
func simplefunc(message: String, choSimple: () -> Void){
print("함수에서 호출이 되었어요, 메세지는 \(message)")
choSimple()
}
choSimple(message: "맹맹맹", choSimple: {
print("클로져에서 호출")
})
// -- 클로져 축약형
choSimple(message: "맹맹맹") {
print("클로져에서 호출")
}
클로져가 맨 마지막 인자로 올 경우 축약이 가능하다.
Inout
기본적으로 스위프트는 함수에서 들어오는 인자는 복사되는 값으로 constant로 들어오기때문에 함수 안에서 변경 불가능하다.
var value = 3
func incrementAndPrint(_ value: Int){
value += 1
print(value)
}
incrementAndPrint(value) //에러발생 value변경 불가능!
타입형 앞에 inout을 써주면 주소를 가지고와서 사용이 가능해진다.
var value = 3
func incrementAndPrint(_ value: inout Int){
value += 1
print(value)
}
incrementAndPrint(&value) //출력결과: 4
변수, 인자에 함수 대입 가능
// -- 변수에 함수 대입
func add(_ a: Int, _ b: Int) -> Int{
return a + b
}
var function = add
print(function(4,2)) //6출력
// -- 인자에 함수 대입
func printResult(_ function: (Int, Int) -> Int, _ a: Int, _ b: Int){
let result = function(a,b)
print(result)
}
printResult(add, 4, 2) // 6출력
Class , Struct 차이
let pClass1 = PersonClass(name: "Jason", age: 5)
let pClass2 = pClass1
pClass2.name = "Hey"
pClass1.name //Hey 출력
pClass2.name //Hey 출력
var pStruct1 = PersonStruct(name: "Jason", age: 5)
var pStruct2 = pStruct1
pStruct2.name = "Hey"
pStruct1.name //Jason 출력
pStruct2.name //Hey 출력
클래스: 새로운 변수에 대입될때 사실상 그 변수는 기존의 클래스를 참조 하는것, (공유) 레퍼런스 타입. 힙에 클래스 생성. (느림)
클래스는 반드시 만들때, 프로퍼티가 초기화 되어있어야함.
구조체: 새로운 변수에 대입될 때, 복사가 된다. 즉 기존이랑 남남이 됨. (복사) 값 타입. 스택에 클래스 생성. (빠름)
구조체는 만들때, 프로퍼티를 초기화 안해도됨.
사용: 구조는 같지만 따로 관리해야하는 경우, 여러 스레드를 이용해야하는경우(레퍼런스로이용하면 위험부담)
Protocol
struct Lecture: CustomStringConvertible{
var description: String{
return "Title: \(lecname) , Instructor: \(pername), Number, \(count)"
}
var lecname : String
var pername : String
var count : Int
}
var lec1 = Lecture(lecname: "math", pername: "I", count: 50)
print(lec1) //Title: math , Instructor: I, Number, 50 출력
해야할 일들, 규약
Getter, Setter
struct Person{
var firstname: String
var fullname: String{
get{
return "\(firstname)"
}
set{
self.firstname = newValue
}
}
}
var person = Person(firstname: "변경전")
print(person.fullname) //변경전 출력
person.fullname = "변경후"
print(person.fullname) //변경후 출력
'iOS스터디 > Swift' 카테고리의 다른 글
[Swift] GCD Dispatch Queue (0) | 2021.03.03 |
---|---|
[Swift] Equatable , Codable 프로토콜 (0) | 2021.02.05 |
[Swift] mutating 구조체 (0) | 2021.02.05 |
[Swift] Computed Property vs Method (0) | 2021.01.14 |
[Swift] 스위프트 문서 정리 잘된 한국어 번역 (0) | 2021.01.13 |