선언문에서 자료형뒤에 쓰는 옵셔널 !, ? 차이(중요)
공통점: 옵셔널 타입
var x : Int! // 경우에 따라 컴파일러가 자동으로 옵셔널을 풀어줌, nil일 때 강제 사용하면 에러
var x : Int?
!로 풀면 크래시가 날 수 도 있어서 안전한 방법인 ?를 사용
옵셔널 타입 객체
!로 푸는 방법
print(han!.age)
?로 푸는 방법
옵셔널 타입으로 출력됨
최종값은 옵셔널이기 때문에 마지막에 사용할 때는 옵셔널바인딩을 해야함
예제 소스
class Company {
var ceo: Person?
}
class Person {
var name: String
init(name: String) {
self.name = name
}
}
let apple = Company()
apple.ceo = Person(name: "Kim")
//print(apple.ceo.name) //오류
// 옵셔널 체이닝 없이면:
if let ceo = apple.ceo {
print(ceo.name) //kim
}
print(apple.ceo!.name) //kim
print(apple.ceo?.name) //Optional("Kim")
// 옵셔널 체이닝
if let name = apple.ceo?.name {
print(name) //kim
}
print(apple.ceo?.name ?? "CEO가 없습니다") // kim
옵셔널 체이닝 쓰는 이유: !로 푸는 것이 편하지만 에러가 발생할 가능성이 있기 때문에 ?를 사용
예외 처리
try!
에러가 발생하지 않을 것이라고 가정할 때 사용(거의 사용안함)
try?
에러를 간단히 무시하거나 실패 여부만 확인하고 싶을 때 사용
throws가 붙은 소스는 반드시 예외 처리를 하고 사용해야 됨
do~catch을 이용한 error handling 기본 형태
do {
try 오류 발생 코드
오류가 발생하지 않으면 실행할 코드
} catch 오류패턴1 {
처리 코드
} catch 오류패턴2 where 조건 {
처리 코드
} catch {
처리 코드
}
제네릭(자료형을 나중에 결정할 때)
제네릭이 필요한 경우
func myPrint(a: Int, b: Int) {
print(b,a)
}
myPrint(a:1,b:2)
myPrint(a:2.5,b:3.5)
func myPrint <T> (a: T, b: T) {
print(b,a)
}
//func myPrint(a: Double, b: Double) {
//print(b,a)
//}
myPrint(a:1,b:2)
myPrint(a:2.5,b:3.5)
myPrint(a: "aaaaa", b: "bbbb")
결정되지 않은 자료형을 <>안에 씀
class Box <T> {
var item: T
init(item: T) {
self.item = item
}
func getItem() -> T {
return item
}
}
let intBox = Box<Int>(item: 12)
// Box<Int>(item: 123), generic class는 이렇게 쓰지만 타입 추론으로 <Int> 생략 가능
print(intBox.getItem()) // 12
let stringBox = Box(item: "Hello") // Box<String>(item: "Hello")
print(stringBox.getItem()) // Hello
배열(Array)
Swift의 Array는 순서가 있는 컬렉션 타입으로, 동일한 타입의 데이터를 저장
let number = [1,2,3,4] // 타입 추론
let odd: [Int] = [1,3,5]
let even: Array<Int> = [2,4,6]
print(type(of: number)) // Array<Int>
print(number) // [1, 2, 3, 4]
print(type(of: odd)) // Array<Int>
print(odd) // [1, 3, 5]
print(type(of: even)) // Array<Int>
print(even) // [2, 4, 6]
let animal = ["dog","cat","cow"]
print(type(of: animal)) // Array<String>
print(animal) // ["dog", "cat", "cow"]
빈 배열
let number : [Int] = []
//빈 배열을 let으로 만들 수는 있지만 초기값에서 변경 불가이니 배열의 의미 없음
var odd = [Int]()
var even : Array<Int> = Array()
print(number) //[]
print(number[0]) //오류, 빈 배열을 값을 넣은 다음에 접근
number.append(100) //let으로 선언한 불변형 배열이라 추가 불가능
//error: cannot use mutating member on immutable value: 'number' is a 'let' constant
print(number[0])
number.append(200)
print(number[0], number[1],number)
초기값에서 변경하지않는 배열은 let으로 만드는 것이 성능이 좋다.
Array(repeating:count:)
특정값(repeating)으로 원하는 개수(count)만큼 초기화
var x = [0,0,0,0,0]
print(x)
var x1 = Array(repeating: 0, count: 5)
print(x1)
var x2 = [Int](repeating: 1, count: 3)
print(x2)
var x3 = [String](repeating: "A", count: 4)
print(x3)
first, last: 옵셔널 타입으로 나오는 이유: 빈 배열에는 first, last 값이 없기 때문에 에러가 발생하는 상황이 생기는 것을 방지하기 위해
첨자로 요소 접근(중요)
var num = [1, 2, 3, 4]
print(num[0], num[3]) // 1 4
print(num.first!) // 1
for i in 0...num.count-1{
print(num[i]) // 1\n 2\n 3\n 4
}
print(num[1...2]) // [2, 3]
num[0...2] = [10,20,30]
print(num) // [10, 20, 30, 4]
Array는 구조체이므로 값 타입
var num = [1,2,3]
var x = num //x는 num의 복사본, 별개의 배열
num[0]=100
print(num) // [100, 2, 3]
print(x) // [1, 2, 3]
Array 요소의 정렬(중요)
var num = [1,5,3,2,4]
num.sort() //오름차순 정렬하여 원본 변경
print(num) //[1, 2, 3, 4, 5]
num[0...4] = [2,3,4,5,1]
num.sort(by:>) //내림차순 정렬하여 원본 변경
print(num) //[5, 4, 3, 2, 1]
num[0...4] = [2,3,4,5,1]
num.reverse() //반대로 정렬하여 원본 변경
print(num) //[1, 5, 4, 3, 2]
print(num.sorted()) //오름차순 정렬 결과를 리턴하고, 원본은 그대로, var x = num.sorted()
//[1, 2, 3, 4, 5]
print(num) //[1, 5, 4, 3, 2]
print(num.sorted(by:>)) //내림차순 정렬 결과를 리턴하고, 원본은 그대로
//[5, 4, 3, 2, 1]
print(num)//[1, 5, 4, 3, 2]
sort: 정렬한 결과를 원본에 반영
sorted: 정렬한 결과를 리턴, 원본은 변경이 안됨
접근제어(중요)
public class MyClass{
// 모듈의 모든 소스 파일 내에서 접근+정의한 모듈을 가져오는 다른 모듈의 소스파일에서도 접근 가능
fileprivate var name : String = "Kim"
//현재 소스 파일 내에서만 사용 가능
private func play() {}
//현재 블럭 내에서만 사용 가능
func display(){} //internal은 디폴트 속성으로 생략됨
// internal 접근은 해당 모듈의 모든 소스 파일 내에서 사용
}
internal 접근 제어는 모듈 내부에서만 접근 가능하도록 제한하는 접근 수준(접근 제어를 생략하면 internal이 기본)
모듈 (Module) 이란?
Swift에서 모듈은 코드의 배포 단위입니다. 일반적으로 프레임워크나 라이브러리가 하나의 모듈로 구성됩니다.
Xcode 프로젝트에서 타겟(Target)은 기본적으로 하나의 모듈을 생성합니다.
즉, 같은 Xcode 프로젝트 내에 있는 여러 파일들은 기본적으로 같은 모듈에 속하게 됩니다.
'iOS' 카테고리의 다른 글
iOS 실무 9주차 (0) | 2025.05.05 |
---|---|
iOS 실무 7주차 (0) | 2025.04.16 |
iOS 실무 5주차 (0) | 2025.04.02 |
iOS 실무 4주차 (0) | 2025.03.26 |
iOS 프로그래밍 실무 3주차 (0) | 2025.03.19 |