[iOS] (아직도 헷갈린다고?) Swift - 타입(자료형) 심화

Madeline👩🏻‍💻·2024년 4월 18일
1

iOS study

목록 보기
46/61
post-custom-banner

swift 공부와 개발 어연 8개월차,, 아직도 이 개념이 헷갈리다니
너 진짜 마지막으로 공부해준다
이 정리는 " 열거형은 인스턴스 생성이 안된다 "에서 시작되었다. 왜지? 왜 안되지? 나 이거 헷갈리나?

아래 내용은 야곰의 swift 문법 교재와 ChatGPT 선생, 그리고 매 피셜로 작성되었다.
많은 swift 문법중 아직도 머릿속에서 떠다니고 있던 '타입'에 대한 내용이다.
기초적인 내용은 다소 넘어가고, 개발이나 면접 용 심화개념일 수 있으니, 주의 바란다.

🧐 타입 == 데이터의 종류 == 자료형

데이터 타입은 프로그램 내에서 다뤄지는 데이터의 종류를 말한다.
Swift의 기본 데이터 타입은 모두 구조체를 기반으로 구현되어 있다.
그리고 Swift는 타입에 민감하고 엄격하기 때문에, 타입을 명시하고, 데이터 교환 시에도 서로 타입을 맞춰줘야 한다.

서로 다른 타입끼리의 데이터 교환은 꼭 타입캐스팅(==형변환) 을 거쳐야 한다.

값 타입의 데이터 교환은 엄밀히 말하면, 타입 캐스팅이 아닌, 새로운 인스턴스를 생성해서 할당하는 거다.

기본타입(Primitive Type)

: Int, Double, String, Bool

복합 타입(Complex Type)

: 여러 값을 그룹화하여 하나의 데이터 유닛으로 만든다.

  • 구조체(Structure): 값 타입, 여러 프로퍼티를 한 묶음으로 취급.
  • 클래스(Class): 참조 타입, 인스턴스가 변수에 할당될 때 참조로 처리됨
  • 열거형(Enumerations): 연관된 항목을 그룹화하여, 그룹 내에서 선택하는 타입
  • 튜플(Tuple): 개발자 맘대로 만드는 타입의 묶음

컬렉션 타입(Collection Type)

: 여러 데이터를 한 곳에 모아 관리한다.

  • 배열(Array)
  • 집합(Set)
  • 딕셔너리(Dictionary)

Int와 UInt

  • 정수 타입이다.
  1. Int
    +, - 부호를 포함한 정수

  2. UInt
    (음수 말고) 0을 포함한 양의 정수

  • Int와 UInt는 8비트, 16비트, 32비트, 64비트의 형태가 있어서, 각각 Int8, Int32, Int64, UInt8, UInt16, UInt32, UInt64, ...

Float과 Double

  • 부동소수점을 사용하는 실수, 부동소수 타입

부동소수? 실수를 소수점의 위치가 고정되지 않고 "부동"할 수 있도록 표현한다. 부동이 뭐야..영어로는 Floating Point다. 그러니깐 소수점(Point)가 떠다니는거다. 고정되지 않다!!를 뜻하는 듯 하다. 그래서 이런 소수점이 부동하는 특성 덕분에 엄청 크거나 엄청 작은 값을 효율적으로 처리할 수 있게 해준다.

그러니까 부동소수점을 사용하는 실수 == 소수점이 있는 수!
Swift에는 64비트의 부동소수 표현을 하는 Double, 32비트의 부동 소수 표현을 하는 Float이 있다.
Float은 32비트의 메모리 공간을 사용해서 숫자를 지정한다.
Double은 64비트의 메모리 공간을 사용해서 약 15~16자리의 유효숫자를 정밀도로 가진다. 그래서 더 정밀한 계산을 해야될 때 사용된다.
필요에 따라 둘 중 하나를 선택해서 쓰는 건데, 그게 뭔데?할 때는 Double을 사용하자.

String

  • 문자의 나열(== 문자열)

  • 유니코드를 사용할 수 있다. Swift는 문자열을 다루는 메서드와 프로퍼티들이 비교적 많고 쉬운 편이다.

  • 특정 인덱스에 접근한다던지, 문자열 길이, 일부 추출, 포함여부 확인 등 다양한 메서드가 있다.

💧 Any, AbyObject

  • Any: Swift의 모든 데이터 타입을 사용할 수 있다는 뜻
    변수나 상수가 Any로 지정되어 있다면, 그 변수나 상수에는 어떤 정류의 데이터 타입이든지 상관없이 할당할 수 잇다.

  • AnyObject: 모든 클래스타입의 인스턴스를 참조할 수 있는 프로토콜
    클래스의 인스턴스만을 대상으로 할 때 사용된다.
    예를 들어, 여러 종류의 클래스 인스턴스를 배열에 저장하고 싶을 때, 해당 배열의 타입을 '[AnyObject]'로 지정할 수 있다.

근데 이건 안쓰는 편이 좋다~ Swift는 타입에 엄격한 특성이 있어서, 매번 얘가 타입을 확인하고 변환하고 해야하고, 오류의 위험이 있다. 타입은 될 수 있는 한 명시하는 게 좋다!!

typealias

내가 타입 만들어서 쓰고 싶을 땐 기존 데이터 타입이나 내가 만든 타입에 다른 이름을 붙일 수 있다. 닉네임 그 자체다.

typealias MyInt = Int

let age: MyInt = 100

🤩 열거형

  • 연관된 항목들을 묶어서 표현할 수 있는 타입
  • 항목 추가, 수정 불가!
  • switch case 구문이랑 찰떡

🛠️ 메모리 측면에서의 열거형
기본적으로 메모리 사용이 매우 효율적이다. 내부적으로 정수로 표현되기 때문에, 각 케이스는 기본적으로 메모리 내에서 최소한의 공간을 차지한다. 일반적으로 정수와 같은 양의 메모리를 사용한다는 뜻이다.

  • 열거형 타입 자체가 하나의 값으로 사용된다. 그래서 인스턴스를 생성하는 클래스나 구조체와는 좀 다르다. 열거형의 각 케이스가 열거형 타입의 인스턴스처럼 동작한다. 각 케이스가 열거형의 하나의 값으로 간주된다.

원시값(Raw Value)

  • 열거형 각 케이스에 고정된 값을 미리 할당해두는 것
  • 변경X

원시값 변경 안됨. 원시값은 열거형의 각 케이스에 고정되어서 정의되고, 인스턴스 생성 후에 변경할 수 없다. 원시값은 열거형 케이스를 쉽게 식별하고, 특정 값에 의미를 부여하기 위해서 사용되는데, 이 값은 열거형의 정의 시점에 고정됨! -> 컴파일 타임에 결정됨

연관값(Associated Values)

  • 열거형의 케이스마다 다른 타입의 값을 저장할 수 있도록 해줌
  • 케이스의 상황에 따라 다른 정보 저장하고 싶을 때 유용함!
enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

let productBarcode = Barcode.upc(8, 85909, 51226, 3)
let qrCode = Barcode.qrCode("ABCDEFGHIJKLMNOP")

-> 하나는 Int, 하나는 String

🛠️ 메모리 측면에서의 연관값이 있는 열거형
연관값을 가지는 열거형은 각 케이스에 추가 데이터를 연결할 수 있다. 연관값이 있는 경우, 열거형은 해당 연관값을 저장하기 위한 추가 메모리를 필요로 한다. 그러면 연관값의 타입에 따라 필요한 메모리 양이 달라진다.

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

이 예시에서, 바코드 열거형은 두 가지 바코드 타입을 나타내고 있는데, 하나는 4개의 정수를, 하나는 1개의 문자열을 저장한다. -> 그 만큼의 메모리가 필요해진다.

Swift 컴파일러는 메모리 사용을 최적화하기 위해, 열거형 데이터를 효율적으로 관리한다.
예를 들어, 모든 케이스가 같은 타입의 연관값을 가질 때, Swift는 메모리 내에서 효율적으로 이를 처리하여, 각 케이스에 대한 메모리 사용을 최소화한다.
또한, 케이스에 따라 다른 타입의 연관값을 가질 때에는 각 타입에 필요한 메모리만큼을 추가적으로 할당한다.

CaseIterable 프로토콜

  • 열거형의 모든 케이스를 컬렉션으로 다룰 수 있게 된다.
    (열거형의 모든 케이스를 배열과 같은 형태로 순회하거나 접근할 수 있음)

  • 열거형에 CaseIterable 프로토콜을 적용하면, 자동으로 .allCases 프로퍼티가 추가된다.

@available 속성(attribute)

  • 특정 기능이나 메서드가 특정 플랫폼 또는 특정 버전에서 사용 가능한지 여부를 나타내기 위해 사용된다. 이 속성을 사용하여 코드의 일부가 특정 iOS 버전이나 macOS 버전 등에서만 사용되도록 제한할 수 있다. 이는 앱의 호환성을 관리하고, 새로운 API를 안전하게 도입하면서도 이전 시스템에서의 실행을 보장하는 데 도움이 된다.
enum Device {
    case iPhone
    case iPad
    case mac

    @available(iOS 13, macOS 10.15, *)
    case watch
}

결론

열거형은 인스턴스 생성이 안된다.
열거형은 값을 미리 정의해두고 변경할 수도 없는 타입이다. 컴파일 시점에 다 정의되어있다. 그래서 새로운 인스턴스를 생성할 필요가 없다. 각각의 열거형의 케이스들이 열거형 그 자체를 타입으로 가지며, 이게 인스턴스마냥 쓰인다. 인스턴스 생성하지 않고, 각 케이스를 직접 써서 값에 접근하고, 처리한다!!!

profile
🍎 Apple Developer Academy@POSTECH 2기, 🍀 SeSAC iOS 4기
post-custom-banner

0개의 댓글