
swift
는 2014년 공개된 프로그래밍 언어입니다. Apple 이 기존에 사용했던 objective-c
를 보완하고자 만든 현대적인 언어입니다. iOS, macOS, Apple TV 등의 프로그래밍에 사용되며 현재 오픈소스로 공개되었습니다.
이 글에서는 swift
의 아주 기본적인 문법에 대해 다루고자 합니다. [edwith]Swift 프로그래밍 입문 강좌에 대한 정리글입니다. 강좌는 무료이기 때문에 듣고 싶으시다면 언제든지 해당 링크를 통해 들어가시기 바랍니다.
콘솔로그 출력하기
print("var1") // 단순 문자열 출력
dump("var1") // 인스턴스의 요소들까지 모두 출력
문자열 보간법 (String Interpolation)
\(문자)
문자열 내의 실질적인 변수나 상수를 표현하기 위해 사용합니다.
괄호 안에 들어가는 문자가 변수나 상수가 되어 실행됩니다.
상수와 변수 선언하기
let 이름: 타입 = 값 // 상수
var 이름: 타입 = 값 // 변수
띄어쓰기를 그대로 지켜야 합니다. 이 점에 주의하시기 바랍니다.
만약 타입이 명확하다면 다음과 같이 생략할 수 있습니다.
let 이름: 타입 // 상수
var 이름: 타입 // 변수
선언만 하고 값은 나중에 할당하기 위해 다음과 같이 사용할 수도 있습니다.
기본 데이터 타입
var var1: Bool = true // 진리값
var1 = 0 // 에러
var1 = 1 // 에러
var var1: Int = -32 // 정수형
var var2: UInt = 32 // 양의 정수형
var1 = var2 // 에러
var var1: Float = 3.14 // 실수
var var2: Double = 3.14 // 64비트 실수
var1 = var2 // 에러
var var1: Character = "H" // 문자
var var2: String = "Hello, World" // 문자열
var1 = var2 // 에러
var var1: Any // 모든 타입
var var2: AnyObject // 모든 클래스 타입
nil // 없음을 의미, NULL 과 유사
타입이 다르면 값으로 절대 할당할 수 없습니다.
컬렉션 타입 (Array)
var array1: Array<타입> = Array<타입>() // 배열 생성 1
var array2: Array<타입> = [타입]() // 배열 생성 2
var array3: [타입] = [타입]() // 배열 생성 3
var array4: [타입] = [] // 배열 생성 4
let array5 = [1, 2, 3] // 상수 배열 생성
array1.append(1) // 배열에 1 추가
array1.append(2) // 배열에 2 추가
array1.append(1.5) // 에러
array1[0] // 배열의 0번 인덱스 값
array1[1] // 배열의 1번 인덱스 값
array1[2] // 에러
array1.contains(1) // 배열에 1 이 있으면 true 를 반환
array1.contains(100) // 배열에 100 이 없으면 false 를 반환
array1.remove(at: 0) // 배열에서 0번 인덱스에 있는 값을 제거
array1.removeLast() // 배열에서 가장 마지막에 있는 값을 제거
array1.removeAll() // 배열에서 모든 값을 제거
컬렉션 타입 (Dictionary)
var dictionary1: Dictionary<키타입, 값타입> = [키타입, 값타입]() // 딕셔너리 생성
let dictionary2: [키타입: 값타입] = [:] // 상수 딕셔너리 생성
dictionary1["key"] = "value" // "key-value" 값 할당
dictionary1.removeValue(forKey: "key") // 키의 모든 값 제거
컬렉션 타입 (Set)
var set1 Set<타입> = Set<타입>() // 셋 생성
set1.insert(1) // 셋에 1 추가
set1.insert2(2) // 셋에 2 추가
set1.insert2(2) // 셋에 이미 2 가 있으므로 변화 없음
set1.contains(1) // 셋에 1 이 있으면 true 반환
set1.contains(100) // 셋에 100 이 없으면 false 반환
set1.remove(1) // 셋에서 1 값 제거
set1.removeFirst() // 셋에서 가장 처음에 있는 값을 제거
set1.union(set2) // 합집합
set1.intersection(set2) // 교집합
set1.subtracting(set2) // 차집합
set1.sorted() // 오름차순 정렬
함수
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입) -> 반환타입 {
/* 내부코드 */
return 반환값
} // 함수 선언시
함수이름(매개변수이름: 값) // 함수 사용시
반환값이 없을 경우 반환타입을 생략하거나 Void 로 설정해야 합니다.
func 함수이름(매개변수1이름: 매개변수1타입 = 기본값) {
/* 내부코드 */
} // 기본값 있는 함수 선언시
func 함수이름(전달인자1 매개변수1이름: 매개변수1타입, 전달인자2 매개변수2이름: 매개변수2타입) {
/* 내부코드 */
} // 전달인자 레이블이 있는 함수 선언시
함수이름(전달인자1: 값, 전달인자2: 값)
전달인자 레이블을 다르게 사용하게 되면 같은 이름의 함수더라도 다른 함수가 됩니다.
func 함수이름(매개변수이름: 매개변수타입...) {
/* 내부코드 */
} // 가변 매개변수 함수 선언시
가장 뒤에 … 을 넣으면 변수가 여러개가 되어도 함수에 사용할 수 있습니다.
var 변수이름: (매개변수1타입: 매개변수2타입) -> 반환타입 = 함수이름(레이블1:레이블2:) // 변수에 함수 넣기 1
var 변수이름 = 함수이름(레이블1:레이블2:) // 변수에 함수 넣기 2
func 함수이름(매개함수(매개변수1타입: 매개변수2타입) -> 반환값) {} // 매개변수로 함수를 가지는 경우
Swift 에서 함수는 일급객체입니다. 그래서 변수에 함수를 값으로 넣을 수 있습니다.
조건문
if 조건 {
/* 내부코드 */
} else if 조건 {
/* 내부코드 */
} else {
/* 내부코드 */
}
if 조건에는 항상 Bool 타입의 값이 들어가야 합니다.
switch 변수 {
case 값1:
/* 내부코드 */
case 값2:
/* 내부코드 */
default:
/* 내부코드 */
}
반복문
for 변수 in 컬렉션타입 {
/* 내부코드 */
} // Array, Set
for (키, 값) in 컬렉션타입 {
/* 내부코드 */
} // Dictionary
while 조건 {
/* 내부코드 */
}
repeat {
/* 내부코드 */
} while 조건
옵셔널
Swift 에서 옵셔널이란 값이 있을수도 있고, 없을수도 있다는 것을 의미합니다. 예외사항을 최소화할 수 있어서 효율적입니다.
let var1: Optional<Int> = nil // 옵셔널
let var2: Int? = nil // 일반적인 옵셔널
let var3: Int! = nil // 암시적 추출 옵셔널
옵셔널은 일반적인 데이터 타입들과 다르기 때문에 함께 사용할 수는 없습니다. 옵셔널 값을 사용하기 위해서는 if-let 을 활용한 옵셔널 바인딩을 사용해야 안전합니다.
if let name: 타입 = 값 {
/* 값 == 타입 */
} else {
/* 값 == nil */
}
위의 경우 만약 값이 nil 이면 else 구문이 실행됩니다.
쉼표를 이용해서 여러 옵셔널 타입을 바인딩할 수도 있습니다.
구조체
구조체는 값 타입입니다.
값 타입이라는 말은, 값을 가져올때 메모리 주소를 가져오는 것이 아니라 값을 복사해서 가져온다는 의미입니다.
struct Struct1 {
var var1: 타입 = 값 // 가변 프로퍼티 (인스턴스 프로퍼티)
let var2: 타입 = 값 // 불변 프로퍼티 (인스턴스 프로퍼티)
static var var3: 타입 = 값 // 타입 프로퍼티
func method1() {/* 내부코드 */} // 인스턴스 메서드
static func method2() {/* 내부코드 */} // 타입 메서드
} // 구조체 생성
var instance1: Struct1 = Struct1() // 가변 인스턴스 생성
let instance2: Struct1 = Struct1() // 불면 인스턴스 생성
인스턴스 프로퍼티와 인스턴스 메서드는 구조체에서 만들어진 인스턴스들이 각각 가지는 값을 정의합니다. 반면에 타입 프로퍼티와 타입 메서드는 모든 구조체가 가지는 값을 정의합니다.
쉽게 말해 구조체 Struct1 에서 인스턴스 instance1 을 만들었다면 instance 에서 인스턴스 값들은 변경할 수 있지만 타입 값들은 변경할 수 없습니다.
클래스
클래스는 참조 타입입니다.
상속할 수 있습니다. 그러나 Swift 에서 다중 상속할 수는 없습니다.
class Class1 {
var var1: 타입 = 값 // 가변 프로퍼티
let var2: 타입 = 값 // 불변 프로퍼티
static var var3: 타입 = 값 // 타입 프로퍼티
func method1() {/* 내부코드 */} // 인스턴스 메소드
static method2() {/* 내부코드 */} // 스태틱 타입 메소드
class method3() {/* 내부코드 */} // 클래스 타입 메소드
} // 클래스 생성
var instance1: Class1 = Class1() // 가변 인스턴스 생성
let instance2: Class1 = Class1() // 불변 인스턴스 생성
상속을 제외하면 구조체와 유사합니다. 상속시 스태틱 타입 메소드는 제정의할 수 없지만, 클래스 타입 메소드는 재정의할 수 있습니다.
클래스는 참조 타입이기 때문에 불변 인스턴스로 생성되었다 하더라도 클래스 내의 가변 프로퍼티의 값을 변경할 수 있습니다. 물론 불변 프로퍼티는 안됩니다.
열거형
열거형은 값 타입입니다.
enum Weekday {
case sun
case mon
case tue
case wed, thu, fri, sat
func printWeekday () {/* 내부코드 */} // 메서드
} // 열거형 생성
var day = Weekday.sun // 열거형 사용 1
day = .mon // 열거형 사용 2
let apple: Fruit? = Fruit(rawValue: 0) // 옵셔널을 활용한 안전한 초기화
enum Price: Int {
case apple = 1000
case grape = 3000
case peach
} // 정수형을 가지는 열거형
var fruit = Price.apple.rawValue
값이 없을 경우, C 의 열거형과 마찬가지로 1 씩 증가한 값을 가집니다. 그래서 peach 는 3001 이 됩니다. 정수형이 아닌 경우, case 의 값을 그대로 기본값으로 가지게 됩니다.
Swift 에서 데이터 타입은 모두 구조체로 구현되어 있습니다. Swift 는 구조체와 열거형 사용을 권장합니다. 그리고 Apple 프레임워크는 대부분 클래스를 사용하고 있습니다. 물론 어떤 방식을 사용할지는 개발자의 선택에 달려있습니다.