Hi yoahn 개발블로그

[Swift] #2 Swift 기초 문법 2 본문

프로그래밍 언어/swift

[Swift] #2 Swift 기초 문법 2

hi._.0seon 2021. 1. 19. 20:29
반응형

1. 함수

func 함수이름(매개변수이름1: 매개변수타입1, 매개변수이름2: 매개변수타입2...) -> 반환타입(없으면 Void, 생략 가능) {
    함수 구현부
    return 반환값
}

호출 방법 함수이름(매개변수이름1: 값,,,)

1) 매개변수 기본 값 지정

func greeting(friend: String, me: String = "yoahn"){
    print("hello \(friend)! I'm \(me)")
}
  • 기본값을 가지는 매개변수는 호출 시 생략 가능

2) 전달인자 레이블

  • 함수를 호출할 때 함수 사용자의 입장에서 매개변수의 역할을 좀 더 명확하게 표현하고자 할 때 사용합니다.
  • 전달인자 레이블은 변경하여 동일한 이름의 함수를 중복으로 생성가능합니다.(함수 중복정의 가능)
  • 함수 내부에서 전달인자를 사용할 때는 매개변수 이름 사용
  • 함수 호출 시에는 전달인자 레이블을 사용

3) 가변 매개변수

  • 함수당 하나만 가질 수 있다
  • 매개변수의 맨 뒤에 위치

4) 데이터 타입으로서의 함수

  • 스위프트는 함수형 프로그래밍 패러다임을 포함하는 다중 패러다임 언어이므로 스위프트의 함수는 일급객체입니다. 그래서 함수를 변수, 상수 등에 할당이 가능하고 매개변수를 통해 전달할 수도 있습니다.
  • 함수의 타입 표현 : 반환 타입을 생략할 수 없습니다.
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

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)

2. 조건문, 반복문

1) 조건문

  • if-else 기본 형태 조건문을 감싸는 소괄호는 없어도 됨 조건 값은 Bool 타입의 값만 위치해야 함 중괄호 생략 불가

  • switch 구문 기본적으로 사용하던 정수타입의 값만 비교하는 것이 아니라 대부분의 스위프트 기본 타입을 지원하며, 다양한 패턴과 응용이 가능합니다.

  • 스위프트의 다양한 패턴은 Swift Programming Language Reference의 패턴(아래링크)에서 확인할 수 있습니다. 각각의 case 내부에는 실행가능한 코드가 반드시 위치해야 합니다.

  • 매우 한정적인 값(ex. enum의 case 등)이 비교값이 아닌 한 default 구문은 반드시 작성해야 합니다.

  • 명시적 break를 하지 않아도 자동으로 case마다 break 됩니다. fallthrough 키워드를 사용하여 break를 무시할 수 있습니다.

  • 쉼표(,)를 사용하여 하나의 case에 여러 패턴을 명시할 수 있습니다.

2) 반복문

  • 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 conditions {} 조건 괄호 생략 가능 Bool 타입 값만 조건으로 넣을 수 있음

  • repeat-while == do-while

3. 옵셔널

  • 값이 있을 수도, 없을 수도 있음을 표현
  • nil이 할당 될 수 있는지 없는지 표현
// someOptionalParm에 nil이 할당 될 수 있다.
func someFunction(someOptionalParam: Int**?**) {
       // ....
}

/// someOptionalParm에 nil이 할당 될 수 없다.
func someFunction(someOptionalParam: Int) {
       // ....
}

someFunction(someOptionalParam: nil)
// someFunction(someParam: nil)  오류
// -> 컴파일단계에서 체크

1) 옵셔널을 쓰는 이유

  • 명시적 표현
    1. nil의 가능성을 코드만으로 표현가능
    2. 문서/주석 작성 시간 절약
  • 안전한 사용
    1. 전달받은 값이 옵셔널이 아니라면 nil 체크를 하지 않고 사용가능
    2. 예외 상황을 최소화 하는 안전한 코딩
    3. 효율적 코딩
enum Optional<Wrapped>: ExpressibleByNiliteral {
         case none
         case some(Wrapped)
}

let optionalValue: Optional<Int> = nil
let optionalValue: Int? =nil

2) 옵셔널 표현

1. 느낌표(!)를 이용한 암시적 추출 옵셔널

- 선언할 때부터 강제 추출을 가정하고 선언하는 것

// 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

// 잘못된 접근으로 인한 런타임 오류 발생
//implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1

 

2. 물음표(?)를 이용한 옵셔널

// Optional
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

4. 옵셔널 추출

- 옵셔널에 들어있는 값을 사용하기 위해 꺼내오는 것

4.1 옵셔널 방식

1 ) 옵셔널 바인딩

1. nil 체크 + 안전한 추출

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

var myName: String? = nil

//printName(myName)
// 전달되는 값의 타입이 다르기 때문에 컴파일 오류발생

2. 옵셔널 안에 값이 들어있는지 확인하고 값이 있으면 값을 꺼내옵니다.

- 일반 데이터 타입과 옵셔널 타입은 다른 타입으로 취급

ex) String != String?


3. if-let 방식 사용

- if-let 에서 선언된 상수는 if-let 구문 안에서만 사용이 가능

- 한번에 여러 옵셔널 바인딩 가능

if let name = myName, let friend = yourName

- 모든 옵셔널 변수에 값이 들어있어야 if-let 구문이 실행됨

if let name: String = myName {
    printName(name)
} else {
    print("myName == nil")
}


var yourName: String! = nil

if let name: String = yourName {
    printName(name)
} else {
    print("yourName == nil")
}

// name 상수는 if-let 구문 내에서만 사용가능합니다
// 상수 사용범위를 벗어났기 때문에 컴파일 오류 발생
//printName(name)


// ,를 사용해 한 번에 여러 옵셔널을 바인딩 할 수 있습니다
// 모든 옵셔널에 값이 있을 때만 동작합니다
myName = "yagom"
yourName = 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

 

4. 강제추출 : 옵셔널에 값이 들어있는지 아닌지 확인하지 않고 강제로 값을 꺼내는 방식

- 만약 값이 없을경우(nil) 런타임 오류가 발생하기 때문에 추천되지 않습니다

printName(myName!)

- 안전하게 사용하기 위해서는 옵셔널 바인딩 사용하는 것이 좋다

 

암시적 추출 옵셔널 형식

- 선언할 때부터 강제 추출을 가정하고 선언하는 것

var myName: String? = yagom
var youName: String! = nil


printName(myName!) // yagom
myName = nil

//print(myName!)
// 강제추출시 값이 없으므로 런타임 오류 발생
yourName = nil

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

 

반응형
Comments