Objective-C 보다 Swift 가 좋은 점
제가 받은 느낌은 이렇습니다. Objective-C는 다른 언어와 다른 점이 많아서 코딩할 때 신경 써야 할 게 많았습니다. 반면 Swift는 다른 언어와 비슷한 점이 많아서, 따로 공부하거나 외우지 않아도 직관적으로 쓰기 좋습니다. 자세한 내용은 The Swift Programming Language: The Basics를 참고하시면 됩니다.
변수
타입을 명시하지 않아도 됩니다.
let label = "The width is " // 타입을 명시 안 해도 String 타입이 됨
let implicitInteger = 70 // 타입을 명시 안 해도 Integer 타입이 됨
let implicitDouble = 70.0 // 타입을 명시 안 해도 Double 타입이 됨
let explicitDouble: Double = 70 // 타입을 명시 할 수도 있다.
implicit(암묵적) 타입 변환은 아래와 같이 되지 않습니다. 명시적으로 변환해 주어야 합니다.
let label = "The width is "
let width = 94
let widthLabel = label + String(width) //직접 String 타입으로 변환해야 한다.
참고로 let은 상수, var는 변수입니다. 직관적입니다.
String Interpolation
String Interpolation이 가능합니다. javascript도 python도 이 기능은 없습니다.
//objc 라면 아래와 같은 스타일의 코드가
[NSString stringWithFormat:@"blah %@ asdf %@ test",firstName,lastName];
//아래와 같은 스타일로 바뀐다.
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
//게다가 함수 호출도 가능하다.
let fruitSummary = "I have \(testFunction(100)) pieces of fruit."
제어문
문자열에 대해 switch/case문이 가능합니다. 당연한 것 아니냐고 생각하실 수 있지만, objc에서는 그렇지 않았습니다.
let vegetable = "red pepper"
switch vegetable {
case "celery":
let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
let vegetableComment = "Is it a spicy \(x)?"
default:
let vegetableComment = "Everything tastes good in soup."
}
if let으로 if문 안에서 변수에 값을 대입할 수 있다는 점도 특이합니다.
let numberSymbol: Character = "三" // 한자로 숫자 3
// Int? 는 값이 대입되지 않은 상태인 nil 이 가능한 변수.
var possibleIntegerValue: Int?
// numberSymbol 값에 따라 switch/case 로 1~4로 매핑한다.
switch numberSymbol {
case "1", "١", "一", "๑":
possibleIntegerValue = 1
case "2", "٢", "二", "๒":
possibleIntegerValue = 2
case "3", "٣", "三", "๓":
possibleIntegerValue = 3
case "4", "٤", "四", "๔":
possibleIntegerValue = 4
default:
break
}
// possibleIntegerValue 에 값이 셋팅이 되었을때만 if가 true로 성공함.
// let 이 성공여부를 true/false 로 리턴한다고 이해하면 쉬울듯.
if let integerValue = possibleIntegerValue {
println("The integer value of \(numberSymbol) is \(integerValue).")
} else {
println("An integer value could not be found for \(numberSymbol).")
}
아래 코드와 같은 일도 가능합니다. optional chaining이라고 부르는 것 같습니다.
// residence 가 존재하면 residence 의 numberOfRooms 에 접근한다.
if let roomCount = john.residence?.numberOfRooms {
// roomCount 변수 사용
}
이런 기능은 마치 CoffeeScript에서 sangwook?.like를 하면 javascript 코드 typeof sangwook !== "undefined" && sangwook !== null ? sangwook.like로 변환되는 것과 비슷합니다. 좋습니다.
functions
함수 parameter에 name:String = "default"처럼 디폴트 값을 지정할 수 있습니다. ...를 사용해서 가변 parameter도 받을 수 있습니다. Variadic function 항목을 참고하시면 됩니다.
func join(string s1: String, toString s2: String, withJoiner joiner: String = " ") -> String {
return s1 + joiner + s2
}
함수가 두 개 이상의 값을 리턴할 수도 있습니다.
func count(string: String) -> (vowels: Int, consonants: Int, others: Int) {
var vowels = 0, consonants = 0, others = 0
for character in string {
// ... 블라블라
}
// 아래와 같이 tuple 로 여러개를 리턴하는것이 가능함.
return (vowels, consonants, others)
}
let total = count("some arbitrary string!")
println("\(total.vowels) vowels and \(total.consonants) consonants")
Closures
ObjC에서도 blocks로 클로저를 쓸 수 있긴 했지만, 직관적이지는 않았습니다.
swift의 클로저 문법은 다음과 같습니다.
{ (parameters) -> return type in
statements
}
클로저에 in을 쓰는 문법은 제가 본 언어들 중에서는 처음입니다.
다음은 numbers 배열의 각 값을 digitNames에 해당하는 문자로 치환하는 예제입니다.
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
let strings = numbers.map {
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
// 결과: strings 는 ["OneSix", "FiveEight", "FiveOneZero"] 이 들어간다.
클로저 함수입니다.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
// 매개변수 s1, s2 를 받아서, s1 이 더 큰지 여부를 리턴하는 함수:
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = sort(names, backwards)
// 결과: reversed 는 ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
표현식이 하나라면 아래처럼 짧게 쓸 수 있고, 리턴도 implicit하게 처리됩니다.
reversed = sort(names, { s1, s2 in s1 > s2 } )
아래처럼 더 짧게도 쓸 수 있습니다.
reversed = sort(names, { $0 > $1 } ) //$0 는 첫번째 매개변수, $1 는 두번째 매개변수의 의미.
함수를 반환하는 함수입니다.
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor // 함수를 리턴한다!
}
range
range가 됩니다.
for index in 1...5 {
println("\(index) times 5 is \(index * 5)")
}
// 이런것도 된다.
shoppingList[4...6] = ["Bananas", "Apples"]
추가
Swift는 Scala, Groovy, F#, CoffeeScript, ActionScript, C++, Haskell, C#, TypeScript, Clojure, Dart, go, ruby, Verilog, Kotlin, ML, Haxe, Java에서 영감을 얻은 언어라고 합니다. Groovy와 비슷한 점을 정리한 글도 있습니다.