Swift 문법 정리본

shstl98·2022년 1월 19일
0
post-thumbnail

Swift 문법 정리

변수

변수 선언

var 변수 =var 변수:유형 =var 변수:유형	// 선언만 해둠

여러개의 변수 선언

var (변수1, 변수2, ...) = (1,2, ...)

상수

let 상수 =let 상수:유형 =

오버플로우 방지

값이 이상해져도 좋으니까 오류를 발생시키지 말았으면"할 때 사용

var x = y & + 100000

캐스팅(형 변환)

// 정수로 변환
123 + Int(45.67)
// 텍스트로 변환
"123"+ String(456)

Any, AnyObject, Nil

Any

Swift의 모든 타입을 지칭하는 키워드

var someAny: Any = 100
someAny = "어떤 타입도 수용 가능합니다"
someAny = 123.12

AnyObject

모든 클래스 타입을 지칭하는 프로토콜

class SomeClass {}
var someAnyObject: AnyObject = SomeClass()

nil

없음을 의미하는 키워드

컬렉션 타입

Array

멤버가 순서(인덱스)를 가진 리스트 형태의 컬렉션 타입

// Array 선언 및 생성
var integers: Array<Int> = Array<Int>()

// 같은 표현
// var integers: Array<Int> = [Int]()
// var integers: Array<Int> = []
// var integers: [Int] = Array<Int>()
// var integers: [Int] = [Int]()
// var integers: [Int] = []
// var integers = [Int]()


// 활용

integers.append(1)
integers.append(100)

print(integers)	// [1, 100]

// 멤버 포함 여부 확인
print(integers.contains(100)) // true
print(integers.contains(99)) // false

// 멤버 교체
integers[0] = 99

// 멤버 삭제
integers.remove(at: 0)
integers.removeLast()
integers.removeAll()

// 멤버 수 확인
print(integers.count)

// 인덱스를 벗어나 접근하려면 익셉션 런타임 오류발생
//integers[0]

Dictionary

키와 값의 쌍으로 이루어진 컬렉션 타입

선언

var anyDictionary: Dictionary<String, Any> = [String: Any]()
// Key가 String 타입이고 Value가 Any인 빈 Dictionary

// 같은 표현
// var anyDictionary: Dictionary <String, Any> = Dictionary<String, Any>()
// var anyDictionary: Dictionary <String, Any> = [:]
// var anyDictionary: [String: Any] = Dictionary<String, Any>()
// var anyDictionary: [String: Any] = [String: Any]()
// var anyDictionary: [String: Any] = [:]
// var anyDictionary = [String: Any]()

활용

// 키에 해당하는 값 할당
anyDictionary["someKey"] = "value"
anyDictionary["anotherKey"] = 100

print(anyDictionary) // ["someKey": "value", "anotherKey": 100]

// 키에 해당하는 값 변경
anyDictionary["someKey"] = "dictionary"
print(anyDictionary) // ["someKey": "dictionary", "anotherKey": 100]

// 키에 해당하는 값 제거
anyDictionary.removeValue(forKey: "anotherKey")
anyDictionary["someKey"] = nil
print(anyDictionary)

Set

순서가 없고, 멤버가 유일한 것을 보장하는 컬렉션 타입

선언과 생성

var integerSet: Set<Int> = Set<Int>()
integerSet.insert(1)
integerSet.insert(100)
integerSet.insert(99)
integerSet.insert(99)
integerSet.insert(99)

print(integerSet) // [100, 99, 1]
print(integerSet.contains(1)) // true
print(integerSet.contains(2)) // false

integerSet.remove(100)
integerSet.removeFirst()

print(integerSet.count) // 1

집합 연산

// Set는 집합 연산에 꽤 유용합니다
let setA: Set<Int> = [1, 2, 3, 4, 5]
let setB: Set<Int> = [3, 4, 5, 6, 7]

// 합집합
let union: Set<Int> = setA.union(setB)
print(union) // [2, 4, 5, 6, 7, 3, 1]

// 합집합 오름차순 정렬
let sortedUnion: [Int] = union.sorted()
print(sortedUnion) // [1, 2, 3, 4, 5, 6, 7]

// 교집합
let intersection: Set<Int> = setA.intersection(setB)
print(intersection) // [5, 3, 4]

// 차집합
let subtracting: Set<Int> = setA.subtracting(setB)
print(subtracting) // [2, 1]

제어 구문

if 문

if 조건문 {
    ...... 처리 ......
} else if 조건문 {
    ...... 처리 ......
} else if ...... 필요한 만큼 계속 쓴다 ......

}

switch 문

var x = 300
 
switch x {
case 0:
    "zero"
case 1...9:
    "1번"
case 10...99:
    "2번"
case 100...999:
    "3번"
default:
    "없다"
}

for 문

기본형 1

var integers = [1, 2, 3]
let people = ["yagom": 10, "eric": 15, "mike": 12]

for integer in integers {
    print(integer)
}

// Dictionary의 item은 key와 value로 구성된 튜플 타입입니다
for (name, age) in people {
    print("\(name): \(age)")
}

기본형 2

for 초기화 처리; 조건; 후 처리 {
    ...... 반복 처리 ......
}

// 예제 
for var i = 0; i <10; i ++ {
    "index :"+ String (i)
}

while 문

while의 기본형

while 조건 {
    ...... 반복 처리 ......
}

do while 구문

do {
    ...... 반복 처리 ......
} while 조건

repeat-while 구문

repeat {
    /* 실행 구문 */
} while 조건

함수 기본

함수 정의

func 함수명(인수) -> 반환 값 {
    ...... 수행할 작업 ......
    return}

함수 사용

// 예제 1
func calc(num:Int) -> Int {
    var total:Int = 0
    for i in 1...num {
        total += i
    }
    return total
}
 
calc(100)

// 반환 값이 없는 경우 void로 지정 (생략 가능)

인수의 외부명

(외부명 변수명:유형)
외부명은 코드를 보다 알기 쉽게하는데 필수적인 기능

기본형

func tax(price p:Int, rate r:Double) -> Int {
    return Int(Double(p) * (1.0 + r))
}
 
var res:Int = tax(price:10000, rate:0.08)

숏헤드 (shorthead)

함수 내에서 사용할 변수명과 외부명이 같기 때문에 소스 코드도 깔끔해지고 가독성 높아짐

func tax(price:Int, rate:Double) -> Int {
    return Int(Double(price) * (1.0 + rate))
}

var res:Int = tax(10000, rate:0.08)

여러 반환값과 튜플(tuple)

튜플

여러 값을 한곳에 모아 처리하는 것
(이름:값, 이름:값, ...)

var person = (name:"Taro", age:35)
person.name
person.age

튜플을 반환값으로 사용

func tax(price:Int) -> (kakaku:Int, zei:Int) {
    let zei:Int = Int(Double(price) * 0.08)
    let kakaku:Int = price - zei
    return (kakaku:kakaku, zei:zei)
}

var res = tax(10000)
res.kakaku
res.zei

함수 고급

매개 변수의 기본값

func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 = 매개변수 기본값 ...) -> 반환타입 {
    /* 함수 구현부 */
    return 반환값
}

// 예제
func tax(price:Int, rate:Double = 0.08) -> Int {
    return Int(Double(price) * (1.0 + rate))
}
 
var res:Int = tax(price:10000, rate:0.08)
var res3:Int = tax(price:12300)

전달인자 레이블

func 함수이름(전달인자 레이블 매개변수1이름: 매개변수1타입, 전달인자 레이블 매개변수2이름: 매개변수2타입 ...) -> 반환타입 {
    /* 함수 구현부 */
    return
}

// 함수 내부에서 전달인자를 사용할 때에는 매개변수 이름을 사용합니다
func greeting(to friend: String, from me: String) {
    print("Hello \(friend)! I'm \(me)")
}

// 함수를 호출할 때에는 전달인자 레이블을 사용해야 합니다
greeting(to: "hana", from: "yagom") // Hello hana! I'm yagom

가변 매개변수

전달 받을 값의 개수를 알기 어려울 때 사용

func 함수이름(매개변수1이름: 매개변수1타입, 전달인자 레이블 매개변수2이름: 매개변수2타입...) -> 반환타입 {
    /* 함수 구현부 */
    return
}

func sayHelloToFriends(me: String, friends: String...) -> String {
    return "Hello \(friends)! I'm \(me)!"
}
print(sayHelloToFriends(me: "yagom", friends: "hana", "eric", "wing"))
// Hello ["hana", "eric", "wing"]! I'm yagom!

print(sayHelloToFriends(me: "yagom"))
// Hello []! I'm yagom!

데이터 타입으로서의 함수

함수의 타입표현

반환타입을 생략할 수 없음

(매개변수1타입, 매개변수2타입 ...) -> 반환타입

함수타입 사용

func greeting(to friend: String, from me: String) {
    print("Hello \(friend)! I'm \(me)")
}

var someFunction: (String, String) -> Void = greeting(to:from:)
someFunction("eric", "yagom") // Hello eric! I'm yagom

someFunction = greeting(friend:me:)
someFunction("eric", "yagom") // Hello eric! I'm yagom


// 타입이 다른 함수는 할당할 수 없습니다 - 컴파일 오류 발생
//someFunction = sayHelloToFriends(me: friends:)


func runAnother(function: (String, String) -> Void) {
    function("jenny", "mike")
}

// Hello jenny! I'm mike
runAnother(function: greeting(friend:me:))

// Hello jenny! I'm mike
runAnother(function: someFunction)

구조체

정의 문법

struct 이름 {
	/* 구현부 */
}

프로퍼티 및 메서드 구현

struct Sample {
    // 가변 프로퍼티
    var mutableProperty: Int = 100 
    
    // 불변 프로퍼티
    let immutableProperty: Int = 100 
    
    // 타입 프로퍼티
    static var typeProperty: Int = 100 
    
    // 인스턴스 메서드
    func instanceMethod() {
        print("instance method")
    }
    
    // 타입 메서드
    static func typeMethod() {
        print("type method")
    }
}

구조체 사용

// 가변 인스턴스 생성
var mutable: Sample = Sample()

mutable.mutableProperty = 200		
mutable.immutableProperty = 200		// 컴파일 오류 발생
// 불변 프로퍼티는 인스턴스 생성 후 수정할 수 없습니다

// 불변 인스턴스 생성
let immutable: Sample = Sample()

immutable.mutableProperty = 200		// 컴파일 오류 발생
immutable.immutableProperty = 200	// 컴파일 오류 발생
// 불변 인스턴스는 아무리 가변 프로퍼티라도 인스턴스 생성 후에 수정 불가

// 타입 프로퍼티 및 메서드
Sample.typeProperty = 300
Sample.typeMethod() // type method

mutable.typeProperty = 400 		// 컴파일 오류 발생
mutable.typeMethod()			// 컴파일 오류 발생
// 인스턴스에서는 타입 프로퍼티나 타입 메서드 사용 불가

Class

정의

class 클래스명 {
    // 변수(속성, property)과 함수(메소드, method)를 작성한다
}

인스턴스 생성

class Sample {
    // 가변 프로퍼티
    var mutableProperty: Int = 100 

    // 불변 프로퍼티
    let immutableProperty: Int = 100 
    
    // 타입 프로퍼티
    static var typeProperty: Int = 100 
    
    // 인스턴스 메서드
    func instanceMethod() {
        print("instance method")
    }
    
    // 타입 메서드
    // 재정의 불가 타입 메서드 - static
    static func typeMethod() {
        print("type method - static")
    }
    
    // 재정의 가능 타입 메서드 - class
    class func classMethod() {
        print("type method - class")
    }
}

클래스 사용

// 인스턴스 생성 - 참조정보 수정 가능
var mutableReference: Sample = Sample()

mutableReference.mutableProperty = 200
mutableReference.immutableProperty = 200	// 컴파일 오류 발생
// 불변 프로퍼티는 인스턴스 생성 후 수정 불가

// 인스턴스 생성 - 참조정보 수정 불가
let immutableReference: Sample = Sample()

immutableReference.mutableProperty = 200
// 클래스의 인스턴스는 참조 타입이므로 let으로 선언되었더라도 인스턴스 프로퍼티의 값 변경 가능
immutableReference = mutableReference	// 컴파일 오류 발생
// 참조정보는 변경 불가
immutableReference.immutableProperty = 200	// 컴파일 오류 발생
// 참조 타입이라도 불변 인스턴스는 인스턴스 생성 후에 수정 불가

// 타입 프로퍼티 및 메서드
Sample.typeProperty = 300
Sample.typeMethod() // type method

mutableReference.typeProperty = 400	// 컴파일 오류 발생
mutableReference.typeMethod()	// 컴파일 오류 발생
// 인스턴스에서는 타입 프로퍼티나 타입 메서드를 사용 불가

클래스 상속

class 클래스명:슈퍼 클래스명 {
    // 슈퍼 클래스 : 상속 근원이 되는 클래스
    // 서브 클래스 : 슈퍼 클래스를 계승하여 만든 클래스
}

// 예제 1
import Cocoa

class Helo {
    var name:String = "Taro";
    
    func say(){
        print("Hello, " + name + "!");
    }
}

class Hello:Helo {		// 서브 클래스 선언
    var name2:String = "YAMADA";
    
    func say2(){
        print("Hi," + name + "-" + name2 + "!");
    }
}

var obj:Hello = Hello();	// 인스턴스 선언

obj.name = "Hanako";		
obj.name2 = "TANAKA";		// 상속
obj.say();
obj.say2();		// 상속


// 예제 2
class Friend {
    var name:String
    
    init(name:String) {		// initializer (뒤에 나옴)
        self.name = name
    }
}

class BestFriend : Friend {
    var age:Int
    
    init(name:String, age:Int) {
        self.age = age
        super.init(name:name)	// 슈퍼 클래스
    }
    
}

var you = BestFriend(name: "Taro", age: 30)
print("\(you.name) (\(you.age))")

이니셜라이저 (initalizer)

인스턴스를 만들 때 필요한 값 등을 인수로 전달
인스턴스를 만들 때 자동으로 호출되는 초기화 처리 전용의 메소드
생성자와 유사한 개념?

import Cocoa

class Helo {
    var name:String;
    
    init(name:String){		// 이니셜라이저를 통해 name 프로퍼티를 인수로 만듬
        self.name = name;	// self : Helo 클래스
    }
    
    func say(){
        print("Hello, " + name + "!");
    }
}

var obj:Helo = Helo(name:"Taro");	// 'Taro'가 인수로 전달됨
obj.say();

메소드 오버라이드 (override)

슈퍼 클래스에 있는 메소드를 재정의하는 기술
메소드명뿐만 아니라 인수와 반환 값도 정확하게 슈퍼 클래스의 메소드와 동일해야 함.

import Cocoa

class Helo {
    var name:String = "Taro";
    
    func say(){
        print("Hello, " + name + "!");
    }
}

class Hello:Helo {
    var name2:String = "YAMADA";
    
    override func say(){	// 슈퍼 클래스(Helo)에 있는 메소드(say) 재정의
        print("Hi," + name + "-" + name2 + "!");
    }
}

옵셔널

정의

값이 있을 수도 있고 없을 수도 있는 변수를 정의
옵셔널에 초깃값을 지정하지 않으면 기본값은 nil

// 예제 1
var email: String?
print(email) // nil

email = "devxoul@gmail.com"
print(email) // Optional("devxoul@gmail.com")

// 예제 2
// 열거형으로 값 구분 가능
switch optionalValue {
case .none:
	print("This Optional variable is nil")
case .some(let value):
	print("Value is \(value)")
}

// nil 할당 가능
optionalValue = nil

// 기존 변수처럼 사용 불가
optionalValue = optionalValue + 1	// 연산 불가

암시적 추출 옵셔널

var optionalValue: Int! = 100

// 열거형으로 값 구분 가능
switch optionalValue {
case .none:
	print("This Optional variable is nil")
case .some(let value):
	print("Value is \(value)")
}

// 기본 변수처럼 사용 가능
optionalValue = optionalValue + 1

// nil 할당 가능
optionalValue = nil

// 잘못된 접근(nil값에 접근)
optionalValue = optionalValue + 1	// 런타임 오류 발생

옵셔널 바인딩 (Optional Binding)

func printName(_ name: String){
	print(name)
}

var myname: String? = nil
printName(myName)	// 컴파일 오류
// 전달되는 값의 타입이 다름

if-let 방식으로 바인딩

// 예제 1
func printName(_ name: String){
	print(name)
}

var myname: String! = nil

if let name: String = myName {
	printName(name)
} else {
	print("myName == nil")
}
// name 상수는 if-let 구문 내에서만 사용 가능

printName(name) 	// 컴파일 오류 발생
// 상수 사용범위를 벗어남


// 예제 2
var myName: String? = "yagom"
var yourName: String? = nil

if let name = myName, let friend = yourName {
	print("\(name) and \(friend)")
}
// yourName이 nil이기 때문에 실행 X

yourName = "haha"

if let name = myName, let friend = yourName {
	print("\(name) and \(friend)")
}
// yagom and haha

Force Unwrapping (옵셔널 값 강제 추출)

func printName(_ name: String) {
	print(name)
}

var myName: String? = "yagom"
printName(myName!) // yagom

myName = nil
print(myName!)
// 값이 없으므로 런타임 오류 발생

var yourName: String! = nil
printName(yourName)
// nil값이 전달되기 때문에 런타임 오류 발생

열거형

열거형 기본

  • enum은 타입이므로 대문자 카멜케이스를 사용하여 이름을 정의
  • 각 case는 소문자 카멜케이스로 정의
  • 각 case는 그 자체가 고유의 값
  • 각 케이스는 한 줄에 개별로도, 한 줄에 여러개도 정의 가능
enum 이름 {
	case 이름1
	case 이름2
	case 이름3, 이름4, 이름5
	// ...
}

열거형 사용

enum Weekday {
    case mon
    case tue
    case wed
    case thu, fri, sat, sun
}

// 열거형 타입과 케이스를 모두 사용 가능
var day: Weekday = Weekday.mon

// 타입이 명확하다면 .케이스 처럼 표현 가능
var day: Weekday = .tue

print(day) // tue

// switch의 비교값에 열거형 타입이 위치할 때
// 모든 열거형 케이스를 포함한다면 default를 작성할 필요 없음
switch day {
case .mon, .tue, .wed, .thu:
    print("평일입니다")
case Weekday.fri:
    print("불금 파티!!")
case .sat, .sun:
    print("신나는 주말!!")
}
// 평일입니다

원시값 (raw value)

enum에 type지정 가능. 이는 rawValue의 타입을 의미.

Int로 타입지정
rawValue에 아무 값도 할당하지 않으면, 첫 번째부터 0, 1, 2 순으로 값이 매겨짐

enum Fruit: Int {
    case apple = 0
    case grape = 1
    case peach
    case mango = 0    // 정의 불가
    // mango와 apple의 원시값이 같음

}

print("Fruit.peach.rawValue == \(Fruit.peach.rawValue)")
// Fruit.peach.rawValue == 2

String 타입지정
rawValue를 할당하지 않으면 case의 값 자체가 rawValue가 됨

enum School: String {
    case elementary = "초등"
    case middle = "중등"
    case high = "고등"
    case university
}

print("School.middle.rawValue == \(School.middle.rawValue)")
// School.middle.rawValue == 중등

// 열거형의 원시값 타입이 String일 때, 원시값이 지정되지 않았다면
// case의 이름을 원시값으로 사용합니다
print("School.university.rawValue == \(School.university.rawValue)")
// School.middle.rawValue == university

원시값을 통한 초기화

  • rawValue를 통해 초기화 가능
  • rawValue가 case에 해당하지 않을 수 있으므로 rawValue를 통해 초기화 한 인스턴스는 옵셔널 타입
// rawValue를 통해 초기화 한 열거형 값은 옵셔널 타입이므로 Fruit 타입이 아닙니다
// let apple: Fruit = Fruit(rawValue: 0)
let apple: Fruit? = Fruit(rawValue: 0)

// if let 구문을 사용하면 rawValue에 해당하는 케이스를 곧바로 사용할 수 있습니다
if let orange: Fruit = Fruit(rawValue: 5) {
    print("rawValue 5에 해당하는 케이스는 \(orange)입니다")
} else {
    print("rawValue 5에 해당하는 케이스가 없습니다")
} // rawValue 5에 해당하는 케이스가 없습니다

메소드

enum Month {
    case dec, jan, feb
    case mar, apr, may
    case jun, jul, aug
    case sep, oct, nov
    
    func printMessage() {
        switch self {
        case .mar, .apr, .may:
            print("따스한 봄~")
        case .jun, .jul, .aug:
            print("여름 더워요~")
        case .sep, .oct, .nov:
            print("가을은 독서의 계절!")
        case .dec, .jan, .feb:
            print("추운 겨울입니다")
        }
    }
}

Month.mar.printMessage()
// 따스한 봄~

값 타입과 참조 타입

.타입상속
열거형, 구조체값 타입불가능
클래스참조 타입가능
struct ValueType {
    var property = 1
}

class ReferenceType {
    var property = 1
}

// 첫 번째 구조체 인스턴스
let firstStructInstance = ValueType()
// 두 번째 구조체 인스턴스에 첫 번째 인스턴스 값 복사
var secondStructInstance = firstStructInstance
// 두 번째 구조체 인스턴스 프로퍼티 값 수정
secondStructInstance.property = 2

// 두 번째 구조체 인스턴스 : 첫 번째 구조체를 똑같이 복사한 별도의 인스턴스
// 두 번째 구조체 인스턴스의 프로퍼티 값을 변경해도 첫 번째 구조체 인스턴스의 프로퍼티 값에는 영향 없음
print("first struct instance property : \(firstStructInstance.property)")    // 1
print("second struct instance property : \(secondStructInstance.property)")  // 2


// 클래스 인스턴스 생성 후 첫 번째 참조 생성
let firstClassReference = ReferenceType()
// 두 번째 참조 변수에 첫 번째 참조 할당
let secondClassReference = firstClassReference
secondClassReference.property = 2

// 두 번째 클래스 참조는 첫 번째 클래스 인스턴스를 참조
// 두 번째 참조를 통해 인스턴스의 프로퍼티 값을 변경하면 첫 번째 클래스 인스턴스의 프로퍼티 값 변경
print("first class reference property : \(firstClassReference.property)")    // 2
print("second class reference property : \(secondClassReference.property)")  // 2

클로저

  • 코드의 블럭
  • 일급 시민 : 전달 인자, 변수, 상수 등으로 저장과 전달이 가능
  • 함수는 이름이 있는 클로저

기본 클로저 문법

{ (매개변수 목록) -> 반환타입 in
    실행 코드
}

클로저의 사용

// 함수를 사용한다면
func sumFunction(a: Int, b: Int) -> Int{
    return a + b
}
var sumResult: Int = sumFunction(a: 1, b: 2)
print(sumResult) // 3

// 클로저를 사용한다면
var sum: (Int, Int) -> Int = { (a: Int, b: Int) -> Int in
    return a + b
}

sumResult = sum(1, 2)
print(sumResult) // 3

함수의 전달 인자로서의 클로저

let add: (Int, Int) -> Int
add = { (a: Int, b: Int) in
    return a + b
}

let substract: (Int, Int) -> Int
substract = { (a: Int, b: Int) in
    return a - b
}

let divide: (Int, Int) -> Int
divide = { (a: Int, b: Int) in
    return a / b
}

func calculate(a: Int, b: Int, method: (Int, Int) -> Int) -> Int {
    return method(a, b)
}

var calculated: Int

calculated = calculate(a: 50, b: 10, method: add)
print(calculated) // 60
calculated = calculate(a: 50, b: 10, method: substract)
print(calculated) // 40
calculated = calculate(a: 50, b: 10, method: divide)
print(calculated) // 5

// 따로 클로저를 상수, 변수에 넣어 전달하지 않고 함수를 호출할 때 클로저를 작성하여 전달 가능

calculated = calculate(a: 50, b: 10, method: { (left: Int, right: Int) -> Int in
    return left * right
})

print(calculated) // 500

다양한 클로저 표현

후행 클로저

// 클로저가 함수의 마지막 전달인자일 때
// 마지막 매개변수 이름을 생략한 후 함수 소괄호 외부에 클로저를 구현 가능
result = calculate(a: 10, b: 10) { (left: Int, right: Int) -> Int in
    return left + right
}

print(result) // 20

반환 타입 생략

// Int 타입을 반환할 것이라는 사실을 컴파일러도 알기 때문에 굳이 클로저에서 반환타입을 명시해 줄 필요 X
// 대신 in 키워드는 생략 불가

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
}

print(result) // 20

단축 인자 이름

// 클로저의 매개변수 이름이 굳이 불필요하다면 단축 인자이름을 활용 가능
// 단축 인자이름은 클로저의 매개변수의 순서대로 $0, $1, $2… 처럼 표현

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 }

print(result) // 20

축약 전후 비교

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

//축약 후
result = calculate(a: 10, b: 10) { $0 + $1 }

print(result) // 20

IBAction, IBOutlet

StoryBoard에서 버튼이나 레이블같은 컴포넌트와 연결이 가능

IBAction : Event가 일어난 경우 호출되는 Action
IBOutlet : 값에 접근하기 위한 변수

뒤에 나오는 :UI ~~

UI 중에서 어떤 항목을 가리키도록 설정할것인가를 의미

@IBAction :UIButton // 버튼을 가리키기위해 사용
profile
허쓸하는 좀비

0개의 댓글