함수
함수선언의 기본 형태
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 ...) -> 반환타입 {
/* 함수 구현부 */
return 반환값
}
// 예)
// sum이라는 이름을 가지고
// a와 b라는 Int 타입의 매개변수를 가지며
// Int 타입의 값을 반환하는 함수
func sum(a: Int, b: Int) -> Int {
return a + b
}
변환 값이 없는 함수
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 ...) -> Void {
/* 함수 구현부 */
return
}
// 예)
func printMyName(name: String) -> Void {
print(name)
}
// 반환 값이 없는 경우, 반환 타입(Void)을 생략해 줄 수 있습니다
func printYourName(name: String) {
print(name)
}
매개변수가 없는 함수
func 함수이름() -> 반환타입 {
/* 함수 구현부 */
return 반환값
}
// 예)
func maximumIntegerValue() -> Int {
return Int.max
}
매개변수와 반환값이 없는 함수
func 함수이름() -> Void {
/* 함수 구현부 */
return
}
// 함수 구현이 짧은 경우
// 가독성을 해치지 않는 범위에서
// 줄바꿈을 하지 않고 한 줄에 표현해도 무관합니다
func hello() -> Void { print("hello") }
// 반환 값이 없는 경우, 반환 타입(Void)을 생략해 줄 수 있습니다
func 함수이름() {
/* 함수 구현부 */
return
}
func bye() { print("bye") }
함수 호출
sum(a: 3, b: 5) // 8
printMyName(name: "yagom") // yagom
printYourName(name: "hana") // hana
maximumIntegerValue() // Int의 최댓값
hello() // hello
bye() // bye
매개변수 기본 값
- 매개변수에 기본적으로 전달될 값을 미리 저장할 수 있다.
- 기본값을 갖는 매개변수는 매개변수 목록중에 뒤쪽에 위치하는 것이 좋다.
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 = 매개변수 기본값 ...) -> 반환타입 {
/* 함수 구현부 */
return 반환값
}
func greeting(friend: String, me: String = "yagom") {
print("Hello \(friend)! I'm \(me)")
}
// 매개변수 기본값을 가지는 매개변수는 호출시 생략할 수 있습니다
greeting(friend: "hana") // Hello hana! I'm yagom
greeting(friend: "john", me: "eric") // Hello john! I'm eric
전달인자 레이블
- 함수를 호출할 때 함수 사용자의 입장에서 매개변수의 역할을 좀 더 명확하게 수행하고자 할 때 사용한다.
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타입 ...) -> 반환타입
- 함수 타입 사용
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)
제어 구문
조건문
if-else문
- 기본 형태
- if문만 단독적으로 사용해도 되고, else if, else와 조합해서 사용 가능하다.
- if 뒤의 조건 값에는 Bool타입 값만 위치해야 하며, 조건을 감싸는 소괄호는 선택 사항이다.
- 중괄호는 생략할 수 없다.
if 조건 {
/* 실행 구문 */
} else if 조건 {
/* 실행 구문 */
} else {
/* 실행 구문 */
}
- if-else문 사용
let someInteger = 100
if someInteger < 100 {
print("100 미만")
} else if someInteger > 100 {
print("100 초과")
} else {
print("100")
} // 100
// 스위프트의 조건에는 항상 Bool 타입이 들어와야합니다
// someInteger는 Bool 타입이 아닌 Int 타입이기 때문에
// 컴파일 오류가 발생합니다
//if someInteger { }
switch 구문
- 각각의 case 내부에는 실행 가능한 코드가 반드시 있어야 한다.
- 매우 한정적인 값이 비교값이 아닌 한 defaul 구문은 반드시 작성해야 한다.
- 명시적 break를 하지 않아도 자동으로 case마다 break 된다.
- fallthrough 키워드를 사용하여 break를 무시할 수 있다.
- 쉼표(,)를 사용하여 하나의 case에 여러 패턴을 명시할 수 있다.
//기본 형태
switch 비교값 {
case 패턴:
/* 실행 구문 */
default:
/* 실행 구문 */
}
//사용
// 범위 연산자를 활용하면 더욱 쉽고 유용합니다
switch someInteger {
case 0:
print("zero")
case 1..<100:
print("1~99")
case 100:
print("100")
case 101...Int.max:
print("over 100")
default:
print("unknown")
} // 100
// 정수 외의 대부분의 기본 타입을 사용할 수 있습니다
switch "yagom" {
case "jake":
print("jake")
case "mina":
print("mina")
case "yagom":
print("yagom!!")
default:
print("unknown")
} // yagom!!
반복문
for-in구문
- 기존 언어의 for-each문과 비슷한다.
//기본 형태
for item in items {
/* 실행 구문 */
}
//for-in 구문의 사용
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)")
}
while문
//while 구문의 기본 형태
while 조건 {
/* 실행 구문 */
}
//while 구문의 사용
while integers.count > 1 {
integers.removeLast()
}
repeat-while문
- 기존 언어의 do-while구문과 형태 및 동작이 유사하다
//repeat-while 구문의 기본 형태
repeat {
/* 실행 구문 */
} while 조건
//repeat-while 구문의 사용
repeat {
integers.removeLast()
} while integers.count > 0
옵셔널
옵셔널
- 값이 있을 수도 있고 없을 수도 있다라는 것을 뜻한다.
- nil의 가능성을 명시적으로 표현하기 위해 사용
- nil 가능성을 문서화 하지 않아도 코드만으로 충분히 표현 가능 -> 문서/주석 작성 시간 절약
- 전달받은 값이 옵셔널이 아니라면 nil 체크를 하지 않더라도 안전하게 사용 가능 -> 효율적이고 안전한 코딩
- 옵셔널을 사용할 때 타입 뒤에 ?나 !를 붙여서 사용
암시적 추출 옵셔널(Implicitly Unwrapped Optional)
- 타입 뒤에 !를 붙여서 사용
var implicitlyUnwrappedOptionalValue: Int! = 100
switch implicitlyUnwrappedOptionalValue {
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
// 기존 변수처럼 사용 가능
implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1
// nil 할당 가능
implicitlyUnwrappedOptionalValue = nil
옵셔널
- 타입 뒤에 ?를 붙여서 사용
var optionalValue: Int? = 100
switch optionalValue {
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
// nil 할당 가능
optionalValue = nil
// 기존 변수처럼 사용불가 - 옵셔널과 일반 값은 다른 타입이므로 연산불가
//optionalValue = optionalValue + 1
옵셔널 값 추출(Optional Unwrapping)
옵셔널 바인딩(Optional Binding)
- nil 체크를 함과 동시에 안전한 값 추출 가능
- if-let 구문을 사용하여 옵셔널 값을 추출한다.
func printName(_ name: String) {
print(name)
}
var myName: String? = nil
//printName(myName)
// 전달되는 값의 타입이 다르기 때문에 컴파일 오류발생
if let name: String = myName {
printName(name)
} else {
print("myName == nil")
}
// name 상수는 if-let 구문 내에서만 사용가능합니다
// ,를 사용해 한 번에 여러 옵셔널을 바인딩 할 수 있습니다
// 모든 옵셔널에 값이 있을 때만 동작합니다
var myName: String? = "yagom
var yourName: String? = nil
if let name = myName, let friend = yourName {
print("\(name) and \(friend)")
}
// yourName이 nil이기 때문에 실행되지 않습니다
yourName = "hana"
if let name = myName, let friend = yourName {
print("\(name) and \(friend)")
}
// yagom and hana
강제 추출(Forced Unwrapping)
- 옵셔널의 값을 강제 추출
func printName(_ name: String) {
print(name)
}
var myName: String? = "yagom"
printName(myName!) //강제 언래핑, yagom
myName = nil
printName(myName) //값이 nil이므로 오류 발생
var myName: String! = nil //!로 선언하면 강제 언래핑을 가정하고 선언하는 것
printName(myName) //!를 붙인 것과 같은 효과를 가짐, nil값이 전달되기 때문에 오류 발생
'iOS-Study' 카테고리의 다른 글
iOS Study : 4주차 - 사용자 정의 타입, 클로저 (0) | 2022.11.27 |
---|---|
iOS Study : 3주차 - SwiftUI (0) | 2022.11.19 |
iOS Study : 2주차 내용정리 - SwiftUI (0) | 2022.11.11 |
iOS Study : 2주차 내용정리 - 기초 개념, 데이터 타입 (0) | 2022.11.11 |
iOS-study : 1주차 내용 정리 (0) | 2022.11.04 |