콘텐츠로 건너뛰기
Home » Development » Swift » 페이지 14

Swift

Swift / Cocoa / Foundation / Programming Language / UIKit / AppKit / Swift Standard Library / Swift 문법과 기능 / 공부하면서 알게된 내용들을 정리 / 어느 프로그래밍 언어 덕후의 연습장

WWDC의 자동 메모이제이션 코드 분석

소수 판별이나 소인수분해와 같이 시간이 오래 소요될 수 있는 연산량이 큰 작업이 있고, 이 연산을 반복해서 수행할 일이 많을 때 성능을 개선할 수 있는 가장 손쉬운 방법으로는 연산 결과를 캐싱하는 것이 있을 수 있다. 즉 함수의 외부에 사전과 같은 캐시 저장소를 하나 준비해 두고 입력값을 키로 캐시값을 감사하여 있으면 사용, 없으면 원래 함수 코드를 실행하여 캐시값을 기록하고 리턴하는 방식을 사용하는 것이다. 이는 일일이 그러한 함수를 작성하기 보다는 클로저를 인자로 받아 클로저를 리턴하는 함수를 사용하여 조금 더 유연하게 사용할 수 있다.… 더 보기 »WWDC의 자동 메모이제이션 코드 분석

GCD in Swift

GCD in Swift

Swift에서도 GCD를 여전히 쓸 수 있다. 먼저 dispatch_async 함수는 Objective-C 에서는 아래와 같이 쓴다.

void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

똑같은 방식으로 swift에서도 아래와 같이 정의된다.

func dispatch_async(queue:dispatch_queue_t!, block: dispatch_block_t!)

물론 swift에서 코드 블럭은 클로져이고, trailing closure 문법을 이용하면 보통은

dispatch_async(dispatch_get_main_queue()){
    println("Currently dispatched asynchronously.")
}

이런 식으로 쓸 수 있다.더 보기 »GCD in Swift

Swift :: 문자열로부터 Int/Double 타입 값 얻기

문자열의 숫자를 값으로 변환하기 Int 타입의 경우에는 String.toInt() 메소드가 있어서 Int? 타입의 값을 얻을 수 있다. 당연히 toDouble() 메소드가 있을 줄 알았는데, swiftstub.com에서는 이런 멤버가 없다는 에러가 나왔다.  Swift 2.0 부터는 문자열의 toInt()가 제거되고, Int, Double의 생성자에 문자열을 넣어 옵셔널 타입을 얻을 수 있게 되었다.   let str = "123456" let strInt = Int(str) // Optional(123456) let strDouble = Double(str) // Optional(123456) 하지만 아래의 방법 역시 여전히 유효하긴하다. NSString의 -doubleValue를 이용한다. (2.0에서 제거됨) NSNumberFormatter를 이용한다.   let str = "123.456"… 더 보기 »Swift :: 문자열로부터 Int/Double 타입 값 얻기

enum in Swift

Enumerations

Enumeration(열거) 타입은 서로 연관을 맺고 있는 특정한 값들의 그룹을 의미한다. C의 enum과 비슷하다고 할 수 있는데, 그것보다는 하스켈의 대수타입과 보다 더 닮아있다.
C의 enum의 개념에 익숙하다면, C에서는 enum이 일련의 정수에 대해서 고유의 이름을 붙이는 것과 같다는 것을 알 수 있다. 하지만 Swift에서는 보다 유연한데, 각각의 멤버에 대해서 고유한 값을 붙일 수 있으며(물론 붙이지 않아도 상관없다) 이 값은 정수 뿐만 아니라 실수나 문자열, 유니코드 문자가 될 수도 있다.
또한, 열거 멤버 하나하나가 대수 데이터 타입으로 쓰일 수도 있다. 연관이 있는 멤버들을 하나의 열거 타입에 정의하되, 각각의 멤버는 다시 멤버를 구성하고 있는 하나 혹은 그 이상의 다른 값의 세트를 가질 수 있다.
열거 타입은 Swift에서 일급 객체이며, computed property 라든지, 인스턴스 메소드를 가질 수 있다. 또 initializer를 정의하여 기본적인 초기값을 가지고 생성될 수도 있다.더 보기 »enum in Swift

두 수 사이의 구간을 만드는 stride 함수 (Swift)

stride() 함수는 파이썬의 range() 함수처럼 특정한 닫힌 구간에서 임의의 간격으로 나열된 숫자들을 표현하는 시퀀스 타입을 생성하는 함수이다. func stride<T: Strideable>(from start:T, to end: T, by stride: T.Stride) -> StrideTo<T> 혹은 func stride<T:Strideable>(from start:T, through end: T, by stride: T.Stride) -> StrideThrogh<T> to: 를 쓰면 최종값이 범위에 포함되지 않으며, through:를 쓰면 최종값이 범위에 포함된다. 업데이트: Swift3로 넘어오면서 다시 자유함수로 넘어오게 되었다. is unavailable: Use stride(from:to:by:) free function instead for i in 1.stride(to:22, by:7) { print(i) } ^~~~~~ Swift.Strideable:3:17: note: 'stride(to:by:)' has… 더 보기 »두 수 사이의 구간을 만드는 stride 함수 (Swift)

Swift – 문자열 자르기

문자열을 쪼개기

Swift 4에서의 변경

Swift 4에서 문자열은 그 자체로 시퀀스이고, 서브시퀀스에 접근하기 위해 characters 속성을 사용하지 않게 되었다. (characters 속성 자체가 제거되었다.). split(separator:)를 사용해서 문자열을 자른 결과는 Array<Substring> 타입으로 반환된다. Substring 타입 역시 StringProtocol을 따르고 있기 때문에, 다시 join(separator:)로 묶은 경우 최종 결과는 String이 될 수 있다.

let a = "12,34,56,78"
let xs = a.split(separator:",")
let b = xs.joined(separator:"+")
print(b)
// 12+34+56+78

참고로 split(separator:)에는 빈 문자열을 구분자로 넣을 수 없다. (구분자의 타입은 Character이다.) 따라서 개별 글자로 쪼개진 배열을 얻고 싶다면, unicodeScalars 프로퍼티를 이용한다. (이 스칼라 코드값을 사용하면 Character나 String을 만들 수 있다.)

let ys = a.unicodeScalars.map(String.init)
// ["1", "2", ",", "3", ... ]

Swift3 버전을 중심으로 업데이트.

Swift 문자열은 Collection 타입이 아니기때문에 문자열을 쪼개는 작업은 characters 속성을 이용해야 하는 것은 Swift2와 동일하다. 다만 API의 이름 변경 정책에 따라서 split(_:) 함수가 split(separator:)로 바뀌었다는 것 정도가 차이점이다.

let a = "12,34,56,78"
let xs = a.characters.split(separator:",").map{ String($0) }
let b = xs.joined(separator:"+")
print(b)
//12+34+56+78

  Swift 2.0 버전으로 업데이트 (2015-08-19)

기본적으로 Swift의 String 타입은 Foundation을 임포트하게되면 NSString과 거의 같은 API를 제공하기 때문에 아래와 같이   -componentsSeparatedByString: (Swift3에서는 components(separatedBy:)메소드를 써서 문자열을 분해할 수 있다.

let string = "Fizz Buzz Fizz Buzz FizzBuzz"
let separated = string.componentsSeparatedByString(" ")

하지만 이렇게 해서 얻은 결과는 [AnyObject] 이다. 만약 우리가 얻고자 하는 결과가 [String] 타입이라면 이를 다시 맵핑해야 한다. Foundation이 제공하는 API를 통해 잘라낸 배열은 [String] 타입이다.

더 보기 »Swift – 문자열 자르기

UnicodeScalar

UnicodeScalar 유니코드 문자 1개에 해당하는 코드 포인트값을 담고 있는 데이터이다. UnicodeScalar는 4바이트 유니코드 값 1개에 대응되기 때문에 UInt32 타입으로 변환하거나, UInt32값으로부터 생성해낼 수 있다. let i:Uint32 = 0xac01 let c = UnicodeScalar(i) print(c) let v:UInt32 = c.value Swift의 Character 타입은 글자 1개를 나타내는 자료형이지만, 유니코드 문자 중에서는 여러 개의 코드 값이 하나로 합쳐진 글자들이 있기 때문에 1개의 Character 타입 값은 1개 혹은 그 이상의 UnicodeScalar 값으로 표현된다. 예를 들어 한글 "학"은 1개의 글자로 그 자체로 유니코드 코드포인트 값 1개에 대응될… 더 보기 »UnicodeScalar

클로져 사용방법(Swift)

클로저 사용 시 인자 전달방법

함수의 인자로 클로저를 전달하는 경우를 생각해보자. 배열의 정렬된 사본을 만드는 sorted(_:,_:)의 경우 대략 다음과 같은 시그니처를 가지고 있다.

func sorted<C: SequenceType>(source: C, isOrderedBefore: (C.Geneartor.Element, C.Generator.Element) -> Bool) -> [C.Generator.Element]

만약 정수 배열을 정렬한다고하면 다음과 같이 사용한다.

let arr = [5, 8, 2, 4, 2, 1, 7]
let sortedArr = sorted(arr, { (x:Int, y:Int) -> Bool  in
    return x < y
})

이 때 함수의 마지막 인자는 trailing closure라고 해서 괄호 밖으로 빼낼 수 있다.

let sortedArr = sorted(arr){ (x:Int, y:Int) -> Bool in return x < y }

이때 클로저가 받는 각 인자는 순서대로 $0, $1, … 로 명명하는 것이 가능하다. 이 표현방식도 많이 알려져있는 형태이다. 더 보기 »클로져 사용방법(Swift)

NSScanner

http://nshipster.com/nsscanner/

문자열은 모든 곳에 있고 컴퓨팅의 여러 부분을 담당하고 있다. 이메일, 에세이, 시, 소설, 이 글도 그렇고 심지어 블로그의 코드도 모두 문자열로 되어 있다. 문자열을 쪼개고 특정한 부분을 추출해 내는 능력은 프로그래밍에서 강력한 무기가 될 수 있다. 코코아는 문자열을 쪼개고 합치는 다양한 방법을 제공하는데, 그 중 몇 가지 유명한 예를 들자면,

  • string.componentsSeparatedByCharactersInSet / string.componentsSeparatedByString : 문자열을 특정 토큰을 기준으로 잘라 배열로 쪼갠다.
  • NSRegularExpression : 정규식을 적용한다. 하지만 정규식은 복잡한 문자열에 대해서는 꽤나 번거롭기도 하거니와 많은 주의를 기울일 필요가 있다.
  • NSDataScanner : 문자열에서 주소, 날짜와 시간, URL 등을 추출해 내지만 정해진 포맷에 대해서만 사용할 수 있다는 제약이 있다.
  • NSScanner : 고도로 커스터마징이 가능한 문자열 스캔 클래스.

NSScanner는 문자열의 래퍼처럼 사용하고, 내부의 문자열을 탐색해서 효과적으로 부분문자열 집합이나 숫자값등을 추출해 낼 수 있다. 이 동작을 제어하는 몇 가지 프로퍼티를 살펴보자면,

  • caseInsensitive:Bool : 문자열을 탐색할 때 대소문자 구분을 무시할 것인지 여부
  • charactersToBeSkipped:NSCharacterSet : 탐색시 무시할 글자들을 정의한다.
  • scanLocation:Int : 스캐너의 현재 위치이다. 이 값을 조정하면 빨리감기/되감기 등을 할 수 있다.
  • locale:NSLocale : 문자열을 숫자값으로 바꿔낼 때 사용할 로케일 값이다.
더 보기 »NSScanner

Swift 2 변경점

Swift 2에서 달라지는 점들을 끝판왕 급으로 정리한 블로그 포스트를 소개한다. http://www.russbishop.net/swift-2-0 개인적으로는 guard 문법 패턴 매칭 기법의 일반화 이름이 헷갈리던 함수들의 변경 (예를 들어 sort는 제자리 변경이고 sorted는 정렬된 사본을 리턴한다. 그런데 reverse는 뒤집은 사본을 리턴한다.) 같은 것들에 엄지척! 주고 싶다.