본문 바로가기

iOS & Swift

Swift 문법 정리 [기본]

Swift 언어를 공부 하면서 암기가 필요한 내용, 특히 기존 배웠던 언어들 과의 차이점에 중점을 둬서 정리한 글.

마크 예쁘다

1. About Swift


  • POP(Protocol Oriented Programming)
  • 함수형 언어

2. 변수와 상수


  • var : 변수 선언 키워드
  • let : 상수 선언 키워드
  1. Swift에서는 boolean 대신 Bool, char 대신 Character를 사용하며 모든 자료형들은 대문자로 시작한다.
  2. String과 Character형은 모두 쌍따옴표 “”로 표현되며 홀따옴표’’는 안된다
  3. 모든 타입을 지칭하는 Any 타입과 AnyObject 타입. (마치 Object 클래스)
  4. null 대신 nil 을 사용한다.

Swift에서는 기본적으로 모든 변수에 null(nil)값을 허용하지 않는다.
Java와 비교하면 일반 int, double과 같은 값타입에 null값이 들어가지 않는 것은 마찬가지이다.
Swift에서 변수/상수에 nil값을 허용하려면 옵셔널이라는 별도의 타입을 사용해야만 한다.

3. 옵셔널(Optional)


옵셔널은 왜 필요한걸까?

일반적으로 Java나 C에서 변수에 null 값이 들어가면 실행도중 NullPointerException 과 같은 예기치 못한 오류가 발생할 가능성이 크다. 따라서 변수에 보통 값을 넣기전에 null인지 아닌지 확인하는 작업을 거친다.
Swift에서는 이런 문제를 줄이기 위해 애초에 nil이 포함될 여지가 있는 모든 변수를 Optional로 감싼다. 이는 일종의 예외처리 라고 봐도 될 것이다.

vs Java

    String a="abc";
    int b=Integer.parseInt(k);

자바에서 위와 같은 코드는 null값을 허용하는 String타입을 자연스럽게 매개변수로 사용했을 뿐이니 컴파일 에러는 발생하지 않는다. 하지만 막상 실행시켜보면 런타임 에러가 발생한다.

    var aa: String = "abc"
    var bb: Int = Int(aa)!

Swift에서는 애초에 String->Int로 parse 할 때 옵셔널로 wrapping하여 반환한다. 즉 사용자가 parsing한 결과를 직접 “!”으로 풀어서 사용해야 하며 이 때 위처럼 Int로 변환이 불가능한 변수일 경우 예외를 발생시킨다.

만약 String이 아닌 타입을 Int로 형변환 한다면?

Overriding되어있는 걸 보면 애초에 입력 타입마다 반환 타입이 다르다

  • 옵셔널 문법 = enum + general ( 차후 서술)
  • 옵셔널 추출

4. 컬렉션 타입


Array, Dictionary, Set 모두 Java와 동일하게 사용가능

  • Array의 경우 [Int], Dictionary의 경우 [String:Any]와 같이 선언가능
  • Set은 General과 함께 선언해야하고 A.union(B) 합집합, A.intersection(B)교집합, A.subtracting(B)차집합 메서드 사용가능.
  • ::Sorting??::

5. 함수


  • 매개변수의 기본값을 지정할 수 있음
    : 매개변수란에 할당함으로서 지정하며, 기본값을 가지면 호출시 생략 가능
  • 전달인자 레이블(Argument Label)
    : 전달인자(Argument)와 매개변수(Parameter)를 구분함
    func greeting(to friend: String, from me: String) {
      print("Hello \(friend)! I'm \(me)")
    }

예를들면 위처럼 메서드를 선언하면 메서드 내에서는 friend와 me를 매개변수로 사용하지만 함수를 호출할 때는 to, 와 from을 통한 별도의 전달인자로 값을 전달함.

가변 매개변수

: 전달받을 값의 개수를 알기 어려울 때 사용하며, 함수당 하나만 가질 수 있음.
매개변수가 0개, 1개일 때도 사용되며 함수 내에서 사용할땐 size가 N개인 배열로 사용됨.

6. Swift에서 함수는 ::1급객체::


:Java, C와는 달리 Swift, Python과 같은 언어에서 함수는 1급객체이다.
우선 아래와 같은 3가지 조건을 충족한다면 1급객체라고 할 수 있다.

  1. 변수나 데이터에 할당할 수 있다.
  2. 객체의 인자로 넘길 수 있다.
  3. 객체의 리턴값으로 리턴할 수 있다.

즉 Java의 함수(메서드)는 Class에 종속되며 단일 객체로 위와같은 역할을 수행할 수 없기 때문에 2급객체라고 볼 수 있다.

var someFunc: (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)

사실 위와같이 함수를 어떤변수에 할당하고 또 복사하는 작업을 많이 사용할지는 모르겠다.
하지만 함수가 1급객체라는 점이 중요한 이유는 바로 고차함수에서 활용할 수 있다는 점 때문이다.
고차함수는 이름그대로 함수 자체를 매개변수로 받아서 사용하는 한차원 높은 함수이다. 예를들면 map, filter와 같은 함수가 대표적인 고차함수라고 할 수 있는데, 이들은 매개변수로 함수를 받기 때문에 Java와 같은 언어환경에선 존재하지 않지만, Python, Swift와 같은 환경에선 편리하게 사용된다는걸 알 수 있다.

7. 형변환(Type Casting)


  • 타입확인
    A is B -> is-A관계를 확인하여 결과를 Bool형태로 반환한다.
  • 자바와 마찬가지로 is-A관계가 성립한다면 업캐스팅은 자동으로 성립한다.다운 캐스팅
  1. 조건부 다운 캐스팅( as? )
    캐스팅에 실패하면 nil을, 성공하면 해당 옵셔널 타입을 반환함.
  2. 강제 다운 캐스팅( as! )
    캐스팅에 실패하면 런타임 오류가 발생하며, 성공하면 일반 타입을 반환함.

8. Assertion / Guard


Assertion

  • Assertion은 문제가 생겼을때 강제로 동작을 중지하는 기능이다.
  • 가장 많이 사용하는 구문은 assert(), assertionFailure(), precondition()이다.
  • assert는 assert(조건문, 문자열)과 같이 동작하며 메세지(문자열)은 생략이 가능하다.
  • assertionFailure()나 preconditionFailure()의 경우 조건문을 전달받지 않는데, 이들은 해당 구문이 동작할때 무조건 프로그램 동작을 중지시킨다. 즉 들어오면 안되는 블럭 안에다가 넣어주는 것.
  • 보통은 디버깅모드에서만 작동하고 배포 때는 제외해서 컴파일되는데 precondition()의 경우 배포할 때도 포함되며, 정상적으로 작동한다.

Guard

  • if->break나 if->break 문을 축약해놓은 형태며 100% 동일한 기능을 수행한다고 생각하면 된다.
  • 형태는 guard 조건문 else {break or return}의 형태다
  • break와 return중 하나는 무조건 들어가야만 한다.

9. 오류처리


기능적 정의

Swift에서 오류(Error)는 error라는 프로토콜을 준수하는 타입(주로 열거형).

  enum VendingMachineError: Error {  
  case invalidInput  
  case insufficientFunds(moneyNeeded: Int)  
  case outOfStock  
}

오류 처리 방법

Java의 try-catch문과 마찬가지로 Swift에서는 do-catch 문을 사용함


do {  
try machine.receiveMoney(0)  
} catch VendingMachineError.invalidInput {  
print("입력이 잘못되었습니다")  
} catch VendingMachineError.insufficientFunds(let moneyNeeded) {  
print("(moneyNeeded)원이 부족합니다")  
} catch VendingMachineError.outOfStock {  
print("수량이 부족합니다")  
} // 입력이 잘못되었습니다

위와같은 형식을 가지며 Java와의 차이점은 try가 각각 오류발생 여지가 있는 메서드 앞에 붙는다는 점.

try?, try!

try?

별도의 오류처리 결과를 통보받지 않고 오류가 발생하면 nil값을 없으면 옵셔널 타입 을 반환함

try!

오류가 발생하지 않을 것이라는 확신을 가질 때 사용하며 발생시 런타임오류 발생

    ```
    result = try? machine.vend(numberOfItems: 2)
    result = try! machine.vend(numberOfItems: 1)
    ```