콘텐츠로 건너뛰기
Home » Development » iOS - Cocoa Touch » Page 3

iOS – Cocoa Touch

Objective-C / Swift :: NSRegularExpression

NSRegularExpression Foundation은 유니코드 문자열에 대해서 정규식을 적용할 수 있는 NSRegularExpression 클래스를 제공한다. 이 클래스의 인스턴스는 컴파일된 정규식 패턴을 나타낸다. 여기서 사용되는 정규식 표현 패턴은 ICU의 안을 따르고 있다. (파이썬 정규식과 거의 유사하다.) http://userguide.icu-project.org/strings/regexp 기본적으로 정규식 객체는 자신의 패턴을 문자열에 적용해서 매치 결과들에 대해서 실행되는 블럭 이터레이터를 제공한다. 그 외에도 매치 결과를 배열로 리턴하거나, 매치의 수를 찾거나, 첫 매치를 찾는 등의 편의 메소드도 제공한다. 각각의 매치 결과는 NSTextCheckingResult 객체인데, 이는 전체 매치의 범위(NSRange) 및 개별 캡쳐 그룹의 범위값을 가지고 있다. 객체… 더 보기 »Objective-C / Swift :: NSRegularExpression

NSApplicationMain

NSApplicationMain int NSApplicationMain(int argc, const char* argv[]); 코코아 앱이 실행될 때 main 함수가 곧장 호출하는 함수로, 앱 객체를 생성하고 앱의 런칭 과정을 처리한다. 앱 객체의 클래스는 무조건 NSApplication이며, 앱 델리게이트는 nib 파일 내에 정의되어 있어야 한다. (iOS는 앱 델리게이트 클래스명을 전달하는 인자 부분이 마련되어 있음) argc, argv 파라미터가 정의되어 있지만, 실제로 값을 전달해도 무시한다. 코코아 내에서는 프로그램 실행시의 arguments를 _NSGetArgv, _NSGetArgc, _NSGetEnviron 함수들을 통해서 얻어야 한다.

UIApplicationMain

UIApplicationMain UIKit에서 앱의 런칭 프로세스를 처리하는 함수. UIApplication 객체를 생성하고, 앱의 기본 설정을 Info.plist 파일로부터 읽어들인다. int UIApplicationMain(int argc, char *argv[], NSString *pricipalClassName, NSString *delegateClassName); principalClassName : UIApplication 클래스를 서브클래싱한 경우 해당 클래스 이름을 전달한다. nil을 쓰는 경우 이 값은 UIApplication으로 고정된다. delegateClassName : 앱 델리게이트 클래스 이름. 만약 nib 파일 내에 앱 델리게이트 객체가 정의되어 있다면 nil을 전달해야 한다.

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 – 문자열 자르기

NSScanner

http://nshipster.com/nsscanner/

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

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

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

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

Selector in Swift

셀렉터(Swift) 셀렉터는 Objective-C 메소드의 이름을 가리키는 참조타입이다. @selector() 디렉티브를 써서 메소드 이름을 정수값으로 맵핑하여 표시한다. Swift에서는 이 셀렉터는 Selector라는 구조체로 표현되며 문자열 리터럴로 만들 수 있다. 만드는 방법은 Objective-C 스타일과 거의 유사하다. import UIKit class MyViewController: UIViewController { let myButton = UIButton(frame: CGRect(x:0, y:0, width:100, height:50)) init(nibName nibNameOrNil:String?, bundle nibBundleOrNil:NSBundle?) { super.init(nibName:nibNameOrNil, bundle: nibBundleOrNil) myButton.addTarget(self, action:"tappedButton:", forControlEvents:.TouchUpInside) } func tappedButton(sender:UIButton!) { println("tapped inside") } } NSObject의 performSelector:의 경우 안정성의 문제로 현재(2015. 01)까지는 Swift에서는 불가능하다. 만약 Swift 클래스가 Objective-C의 클래스를 상속받지… 더 보기 »Selector in Swift

날짜와 시간을 다루기(Swift)

날짜와 시간 다루기 (Swift)

Swift에서 날짜와 시간을 다루는 방법은 Foundation 프레임워크의 NSDate, NSCalendar, NSDateFormatter, NSDateComponents 등을 사용하게 되므로 Objective-C의 그것과 약간의 문법 차이만 있을 뿐이다.

날짜 계산의 기본 개념

날짜 계산의 단위가 되는 객체는 NSDate이다. 이 클래스는 특정한 시점을 가리키는 정보를 담고 있다. 기본적으로는 기준일시로부터 몇초가 지났는지를 담아서 타임라인 상의 특정한 지점을 가리키게 된다.
Foundation에서 NSDate는 특정한 시점을 가리키는 포인터에 지나지 않는다. 다른 언어들의 date/datetime 객체와 달리 NSDate 클래스 자체로부터 이 날이 무슨 요일인지 등의 정보는 구할 수 없다. 그 이유는 Foundation은 특정 국가나 문화권에 종속되는 규격이 아니기 때문에 어떤 로케일을 적용하느냐에 따라서 한달의 길이라든가 그런 것들이 다를 수 있기 때문이다. 더 보기 »날짜와 시간을 다루기(Swift)

NSOperation Tutorial in Swift

NSOperation in Swift

http://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift

버튼을 탭하거나 텍스트 편집을 시작할 때 iOS/Mac앱이 반응을 멈추는 당혹스러운 경험을 해본적이 있을 것이다. Mac 앱이라면 마우스포인터(흔히 말하는 커서)가 형형색색의 비치볼로 변하는 것으로 지금 UI 반응을 할 수 없다는 것을 알려주는데, iOS앱에서는 이런 기제가 없으므로 사용자는 항상 UI에 반응할 수 있다고 기대하게 된다. 반응하지 않는 앱은 문제가 있거나 느리다고 느껴지고 리뷰에서 좋은 평가를 받기 힘들다.
앱이 항상 반응하도록 하는 것은 말처럼 쉽지 않다. 앱이 한가지 이상의 일을 동시에(사용자 터치에 반응하면서 다른 작업을 하는)해야 한다면 순식간에 여러가지 것들이 꼬이기 쉽다. 메인 런루프에서는 많은 작업을 처리할 시간이 없고 이는 오롯이 UI 반응에 집중해야 한다.
이제 불쌍한 개발자는 메인스레드에서 병렬작업으로 이행해야 한다. 병렬작업은 동시에 여러 개의 작업 스트림이 진행된다는 의미이며, 이를 통해 메인스레드는 항상 사용자의 터치에 반응하게 된다.
iOS에서 이런 작업을 수행하는 방법 중 하나는 NSOperation과 NSOperationQueue를 사용하는 것이다. 먼저 병렬작업을 사용하지 않은 앱을 만들어보자. 이 앱은 매우 버벅이고 느릴 것이다. 그리고 이 앱에 병렬작업을 추가하면 보다 반응이 좋은 UI를 제공하게 될 것이다. 더 보기 »NSOperation Tutorial in Swift

tableview 셀 생성

테이블 뷰의 데이터소스 프로토콜에는 -tableView:cellForRowAtIndexPath: 라는 메소드가 있다. 이 메소드는 테이블 뷰 상의 특정 위치에 들어갈 cell 객체를 알려주는 메소드로 프로그래머가 작성해주어야 하는 부분이다. 일반적으로는 이렇게 작성했다.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    const NSString *reuseID = @"cell";
    UITableViewCell *cell = [tableView dequeReusableCellWithIdentifier:reuseID];
    if (cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseID];
    }
    ...
    return cell;
}

더 보기 »tableview 셀 생성