타입 어노테이션(Type annotaion)
타입 어노테이션은 변수나 상수를 선언할 때, 그 변수나 상수가 어떤 타입의 값을 저장할 것인지 컴파일러에게 명시적으로 알려주는 문법
변수 또는 상수가 코드 내에서 선언되는 시점에 타입 어노테이션(type annotation)을 사용하는 것
변수 또는 상수 이름 다음에 타입 선언을 두면 된다.
Int 타입의 userCount 라는 이름의 변수를 선언
-var userCount : Int = 10 // : Int가 type annotation
선언부에 타입 어노테이션이 없으면 Swift 컴파일러는 상수 또는 변수의 타입을 식별하기 위하여 타입 추론(type inference)함
해당 상수 또는 변수에 값이 할당되는 시점에서 그 값의 타입을 확인하고 그와 같은 타입처럼 사용
튜플(Tuple): 여러 값을 하나의 개체에 일시적으로 묶는 방법
-괄호 안에 콤마로 구분된 타입들의 리스트
-튜플에 저장되는 항목들은 어떠한 타입도 될 수 있으며, 동일한 타입일 필요도 없음
단 한 줄의 코드로 튜플의 모든 값을 추출하여 변수 또는 상수에 할당
let myTuple = (10, 12.1, "Hi") //myTuple의 자료형?, print(type(of:myTuple))
let (myInt, myFloat, myString) = myTuple
튜플의 값을 선택적으로 추출할 수 있으며, 무시하고 싶은 값에 밑줄을 사용하면 그 값은 무시
var (myInt, _, myString) = myTuple //12.1 무시
튜플을 생성할 때 각 값에 이름을 할당할 수도 있음
let myTuple = (count: 10, length: 12.1, message: "Hi") //myTuple의 자료형?
튜플에 저장된 값에 할당된 이름은 각 값을 참조하는 데 사용
myTuple 인스턴스의 message 값을 출력하는 코드
print(myTuple.message, myTuple.2)
튜플의 가장 강력한 점은 함수에서 여러 값들을 한 번에 반환하는 것
Void는 빈 튜플(empty tuple)
ypealias Void = () //아무 내용도 없는 튜플, typealias 새로운자료형명 = 기존자료형명
반환값이 없는 함수의 자료형
옵셔널 타입(optional type)
옵셔널 변수는 값이 없을 수 있다. 값이 없을 때는 nil이라고 출력된다.
nil: 값이 없다는 의미
값을 반환할 때 오류가 발생할 가능성이 있는 값은 옵셔널 타입이라는 객체로 감싸서 반환함
-Int("123") 은 123이 아닌 Optional(123)을 리턴함,print(Int("123")), Int형 initializer
Int("Hi") 은 정수 값을 반환할 수 없음, 아무런 값도 반환할 수 없다는 의미로 nil을 반환
Swift에서 기본 자료형(Int, Double, String 등)은 nil값을 저장할 수 없음
nil을 저장하려면 옵셔널 타입으로 선언해야 함
옵셔널 타입 강제 언래핑(forced unwrapping)
옵셔널 변수에 값이 있으면 옵셔널로 "래핑되었다(wrapped)"고 함
옵셔널에 래핑된 값은 강제 언래핑(forced unwrapping)으로 풀어줌
옵셔널형 선언 : 자료형 뒤 - ?
옵셔널 언래핑 : 변수명 뒤 - !
var x : Int? //옵셔널 정수형 변수 x 선언
var y : Int = 0
x = 10 // 주석처리하면?
print(x) // Optional(10)
//옵셔널 값을 출력하면 경고 발생, warning: expression implicitly coerced from 'Int?' to 'Any‘
//print() 함수의 매개변수는 Any 타입을 받는데, Int?에서 Any로 자동 변환이 일어나면서 예상치못한
//동작일 발생할 수 있어서 경고
print(x!) // forced unwrapping해서 10이 나옴
print(y)
//x = x+2 //오류, x = Optional(10)+2, 옵셔널형 값은 연산 불가
//y = x //오류, y = Optional(10), 옵셔널 값은 일반 변수에 대입 불가
!를 통해서 값을 풀어주는 것이 간단하긴 하지만, 값이 없을 경우 앱이 다운되거나 crash가 났다고 한다.
따라서 강제 언랩핑(forced unwrapping)은 바로 하는 것이 아니라 nil이 아닐 때만 해야 한다.
var x : Int? //옵셔널 정수형 변수 x 선언
var y : Int = 0
print(x) // Optional(10)
if x != nil {
print(x!) // forced unwrapping해서 10이 나옴
}
에러 방지를 위해 위와 같이 if문을 사용하여 조건을 걸 수 있다.
if x != nil {
print(x!) // forced unwrapping해서 10이 나옴
}
x != nil
//if문을 사용할 때
x!=nil //이렇게 사용하면 안된다.
위와 같이 사용에 주의하여야 한다.
옵셔널 타입 언래핑(forced unwrapping) : optional binding
강제 언래핑보다 안전하고 추천하는 방법
옵셔널 바인딩(optional binding)을 이용하여 옵셔널에 할당된 값을 임시 변수 또는 상수에 할당
if let constantname = optionalName{
//옵셔널 변수가 값이 있다면 언래핑해서 일반 상수 constantname에 대입하고 if문 실행
//값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}
if var variablename = optionalName {
//옵셔널 변수가 값이 있다면 언래핑해서 일반 변수 variblename에 대입하고 if문 실행
//값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}
예시
var x : Int?
x = 10
if let xx = x { //옵셔널 변수 x가 값(10)이 있으므로 언래핑해서 일반 상수 xx에 대입하고 if문 실행
print(x,xx)
}
else {
print("nil")
}
// if let x = x라고 써도 된다.
//swift 5.7부터는 if let x 라고 써도 된다.
//short form of if-let to the Optional Binding
//그러면 아래와 같이 출력해도 된다.
방법2
if let x = x{
print(x)
}
else {
print("nil")
}
방법3 - //short form of if-let to the Optional Binding
if let x{
print(x)
}
else {
print("nil")
}
여러 옵셔널을 언래핑
여러 옵셔널 변수를 한번에 언래핑하는 방법은 콤마 사용
★주의 : let은 매 콤마마다 사용
방법1
var pet1: String?
var pet2: String?
pet1 = "cat"
pet2 = "dog"
if let firstPet = pet1, let secondPet = pet2 {
print(firstPet, secondPet)
}
else {
print("nil")
}
방법2
var pet1: String?
var pet2: String?
pet1 = "cat"
pet2 = "dog"
if let firstPet = pet1, let secondPet = pet2 {
print(firstPet, secondPet)
} else {
print("nil")
}
방법3
var pet1: String?
var pet2: String?
pet1 = "cat"
pet2 = "dog"
if let pet1, let pet2 {
print(pet1, pet2)
} else {
print("nil")
}
두 가지 옵셔널 타입 : Int? vs Int!
IUO캡쳐
옵셔널이 항상 유효한 값을 가질 경우 암묵적인 언래핑(implicitly unwrapped) 옵셔널로 선언할 수도 있음
클래스의 아웃렛 변수 초기화에서 많이 사용(Xcode에서 자동 생성되는 코드)
옵셔널 값을 강제 언래핑이나 옵셔널 바인딩을 하지 않아도 접근할 수 있음
암묵적인 언래핑으로 옵셔널 선언은 선언부에 물음표(?) 대신에 느낌표(!)를 사용
var x : Int? //옵셔널 변수 선언방법 1
var y : Int! //옵셔널 변수 선언방법 2, 암묵적인 언래핑(implicitly unwrapped)
let x : Int? = 1
let y : Int = x!
let z = x
print(x,y,z) //Optional(1) 1 Optional(1)
print(type(of:x),type(of:y),type(of:z))
//Optional<Int> Int Optional<Int>
let a : Int! = 1 //Implicitly Unwrapped Optional
let b : Int = a //일반 상수로 사용할 수 있으면 a를 자동으로 언래핑함
let c : Int = a! //물론 강제언래핑해도 됨
let d = a //Optional로 사용될 수 있으므로 Optional형임
let e = a + 1 //1과 더하려면 a를 일반형으로 자동으로 언래핑함
print(a,b,c,d,e) //Optional(1) 1 1 Optional(1) 2
print(type(of:a),type(of:b),type(of:c),type(of:d), type(of:e))
//Optional<Int> Int Int Optional<Int> Int
var x : Int?와 var y : Int! 의 공통점과 차이점
Any와 AnyObject
AnyObject(protocol)
모든 클래스 타입(객체)만 표현할 수 있음
구조체(struct), 열거형(enum), 기본 타입(Int, String 등)은 사용할 수 없음
Any
모든 타입(Int, String, Double, dtruct, enum, class, 함수 등)의 값을 표현할 수 있는 타입
클래스(class), 구조체(struct), 열거형(enum), 함수 타입도 가능
연산자
증가 연산자(++), 감소 연산자(--) : 지원하지 않음
x = x + 1 // x 변수의 값을 1 증가시킴, x+=1
x = x - 1 // x 변수의 값을 1 감소시킴, x-=1
위의 표현식은 x의 값을 1 증감
이러한 방법 대신 ++ 연산자와 --연산자를 사용할 수도 있었음
x++ // x를 1 증가시킴, Swift 3에서 없어짐, x+=1나 x=x+1을 사용
x-- // x를 1 감소시킴, Swift 3에서 없어짐, x-=1나 x=x-1을 사용
범위 연산자(range operator)
닫힌 범위 연산자(closed range operator)
x...y
x에서 시작하여 y로 끝나는 범위에 포함된 숫자
5…8
5, 6, 7, 8
반 열린 범위 연산자(half-open range operator)
x..<y
x부터 시작하여 y가 포함되지 않는 모든 숫자
5..<8
5, 6, 7
One-Sided Ranges
let names = ["A", "B", "C", "D"]
for name in names[1...] { //[...2], [..<2] //과제: 실행 결과
print(name)
}
nil-coalescing operator (nil병합연산자) ??
var x : Int? //= 1
print(x)
var y = x ?? 1
print(y)
Swift에서 매우 중요한 연산자
옵셔널변수 ?? nil일 때 할당되는 값
옵셔널 변수의 값이 nil이면 ?? 다음 값으로 할당됨
옵셔널 변수의 값이 nil이 아니면 언래핑된 값이 나옴
let defaultAge = 1
var age : Int?
age = 3
print(age) //과제:값은?
var myAge = age ?? defaultAge
//age가 nil이 아니므로 언래핑된 값이 나옴
print(myAge)
var x : Int? = 1
var y = x ?? 0
print(y)
옵셔널을 언랩핑하는 여러가지 방법
var x : String? = "Hi"
//forced unwrapping : unsafe
x!
//optional binding : safe
if let a = x { print(a) }
//nil coalescing operator : safe
let c = x ?? ""
//optional chaining : safe
let b = x?.count
var x : String? = "Hi"
print(x, x!)
if let a = x {
print(a)
}
let c = x ?? ""
print(c)
let b = x!.count
print(type(of:b),b)
let b1 = x?.count
print(type(of:b1),b1, b1!)
형 변환(as로 upcasting : 자식인스턴스를 부모클래스로 변환)
상속 관계가 있는 클래스들끼리는 타입 캐스팅 가능
자식(부모로부터 상속받아 더 많은 것을 가지고 있음)인스턴스를 부모로 캐스팅하는 것은 문제가 없음
-as 연산자를 이용한 타입 변환으로 upcasting이라 함
자식인스턴스 as 부모클래스 // upcasting 안전한 캐스팅. 자식이 추상화됨
-업캐스팅은 객체를 부모 클래스의 객체로 형 변환
-형 변환은 성공할 것이기 때문에 보장된 변환
형 변환(as! as?로 downcasting:부모인스턴스를 자식클래스로 변환)
다운캐스팅은 부모 인스턴스를 자식 클래스로 변환하는 데 사용
성공 확신이 있으면 as! 키워드를 사용하며 강제 변환
변환이 안되면 crash
성공 확신이 없으면 as?를 사용하여 안전하게 변환
변환이 안되면 nil을 리턴하므로 옵셔널 타입으로 반환함
부모인스턴스 as! 자식클래스 // downcasting 일반 타입으로 반환
// 다운캐스팅이 반드시 성공할 것이라는 확신이 있을 때
부모인스턴스 as? 자식클래스 // downcasting 옵셔널 타입으로 반환. 확신이 없을 경우
제어문
for-in 반복문
for-in 반복문은 컬렉션 또는 숫자 범위 내에 있는 목록을 반복
for 상수명 in 컬렉션 또는 범위 {
// 실행될 코드
}
for _ in 0..<10{ // _로 참조체 생략 가능
print("aaa")
}
'상수명'은 반복문이 돌면서 컬렉션(Array, Dictionary, Set) 또는 숫자 범위에서 가져온 항목을 담는 상수
for 문 다음의 실행 코드가 한 줄이라도 괄호({})를 필수적으로 사용
배열의 항목 접근
let names = ["A", "B", "C", "D"]
for name in names {
print(name)
}
dictionary의 항목 접근
let numberOfLegs = ["거미": 8, "개미": 6,"개": 4]
//dictionary는 key:value형식의 배열
for (animalName, legCount) in numberOfLegs {
print("\(animalName)는 \(legCount)개 다리")
}
while반복문
while 조건식 {
// 반복 코드
}
var myCount = 0
while myCount < 1000 {
myCount+=1
}
print(myCount)
repeat~while 반복문
repeat {
//
} while //조건식
var i = 5
repeat {
i=i-1
print(i) //출력 결과
} while (i > 0)
반복문에서 빠져나오기(break)
for i in 1..<10 {
if i > 5 {
break
}
//중요!! 에러 수정 과제: error: expected '{' after 'if' condition
//if 문 다음의 실행 코드가 한 줄이라도 괄호({})를 필수적으로 사용
print(i)
}
continue문
for i in 1...10 {
if i % 2 == 0 {
continue
}
print(i)
}
if문
if 표현식 {
// 표현식이 참일 경우 수행될 코드
}
다른 프로그래밍 언어들과는 다르게, Swift에서는 if 문 다음의 실행 코드가 한 줄이라도 중괄호({})를 필수적으로 사용해야 한다.
기본적으로 ‘표현식’이 참(true)으로 판단되면 중괄호로 감싼 코드 실행
‘표현식’이 거짓(false)이면 중괄호로 감싼 코드는 건너뜀
if문 조건에서 콤마:조건나열(condition-list)
var x = 1
var y = 2
if x == 1 && y==2 { //논리식이 둘 다 참일 때
print(x,y)
}
if x == 1, y==2 { //조건이 둘 다 참일 때, 두 조건을 콤마로 연결한 condition-list
print(x,y)
}
참조
if let s = Optional("Apple"), s.count > 3 {
print(s)
} //여기서 콤마 대신 &&는 불가능
'iOS앱개발' 카테고리의 다른 글
iOS프로그래밍 기초 - Swift 2주차 (0) | 2025.09.08 |
---|