2017년 5월 1일 월요일

iOS & Swift: Keyboard로 사용자 입력할 때, ToolBar 위로 이동하기

이전 글인 Keyboard 이벤트를 이용해서, ToolBar를 이동하는 예제를 만들어 봅니다.

ViewController에서, 하단에 Toolbar가 있고, 사용자가 입력을 할 때, View를 위로 이동시켜서, 입력하는 내용이 화면에 표시되도록 하면, 어떤 내용을 입력하는지 알기 쉬운 UI가 됩니다.

ToolBar만 위로 이동해도 되지만, AutoLayout의 내용들을 다 무시하게 되므로, 전체 View를 Keyboard표시되는 것 만큼 위로 이동하게 만들어 봅니다.



 Keyboard 이벤트 설명 블로그에서 이벤트 등록과 이벤트 발생 때, 실행되는 함수를 등록하는 방법을 이미 설명했습니다.
이제 표시될 때, ToolBar를 위로 올려주고, 입력이 끝나면 밑으로 내려줘야 합니다. 그리고, 입력 중에 화면이 회전되면, 적당하게 ToolBar의 위치를 옮겨줘야 합니다.
위로 얼마나 올려야 되는지는

키보드 표시될 때와, 사라질 때 함수 호출하기.

    override func viewWillAppear(_ animated: Bool) {
        //화면이 표시될때, Keyboard표시에 대한 이벤트가 발생하면 호출되는 함수를 등록한다.
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }
    func keyboardWillShow(_ notification:NSNotification) {
        //키보드가 표시 될때, ToolBar의 위치를 올려준다.
        moveToolbarUp(with: notification)
    }
    func keyboardWillHide(_ notification:NSNotification) {
        //키보드가 사라질 때, ToolBar의 위치를 아래로 내려준다.
        moveToolbarDown(with: notification)
    }

Toolbar를 위로 올려주고, 아래로 내려주는 함수
    fileprivate func moveToolbarUp(with notification:NSNotification) {
        self.moveToolBar(isUp: true, with: notification)
    }
    fileprivate func moveToolbarDown(with notification:NSNotification) {
        self.moveToolBar(isUp: false, with: notification)
    }
    fileprivate func moveToolBar(isUp up:Bool, with notification:NSNotification) {
        if let userInfo = notification.userInfo {
            //let beginFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
            let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
            let duration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
            let animationOptions = UIViewAnimationOptions(rawValue: (userInfo[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).uintValue)
            
            let frame = self.toolbar.frame
            let rect:CGRect = CGRect(x: frame.origin.x,
                                     y: frame.origin.y + endFrame.size.height * (up ? -1 : 1),
                                     width: frame.size.width,
                                     height: frame.size.height)
            UIView.animate(withDuration: duration,
                           delay: 0.0,
                           options: animationOptions,
                           animations: { () -> Void in
                            self.toolbar.frame = rect
            }, completion: nil)
            
        }else{
            //UserInfo가 없을 경우..
        }
    } 

ToolBar가 올라가 있는 상태에서 화면을 옆으로 돌리면, 툴바의 위치가 이상하게 되어 버리는 예외를 처리하기 위해서, 화면이 회전할 때, 키보드를 사라지게 해줍니다. 더 좋은 방법이 있겠지만, 이정도로 마무리..

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        //화면이 옆으로 돌아갈 때, 호출되는 이벤트로, 이벤트 발생 시, 키보드를 아래로 내려주면 이동 후에 다시 선택하면 되도록 한다
        self.inputTextField.resignFirstResponder();
    }


2017년 3월 28일 화요일

iOS & Swift : Keyboard가 표시될 때, 사라질 때 이벤트와 그 키보드의 위치를 알아보자

지난 블로그에서는 Objective-C를 기준으로 정리하였는데, 이제는 Swift를 기준으로 정리한다.
(링크 [iOS] Keyboard가 표시될 때, 사라질 때 이벤트와 그 키보드의 위치는?)

일반적인 UIViewController 내에서는 표시할 위치를 이동시켜야, 키보드에 덮히지 않고, 사용자에게 표시할 수 있습니다.

1. 키보드가 화면에 나타나거나, 사라지는 Event는 무엇이고, 어떻게 알아낼까?

키보드가 표시될 때 전달되는 이벤트는...
  • NSNotification.Name.UIKeyboardWillShow : 키보드가 표시되기 전에 호출
  • NSNotification.Name.UIKeyboardDidShow : 키보드가 표시되고 난 후에 호출
  • NSNotification.Name.UIKeyboardWillHide : 키보드를 숨기기 전에 호출
  • NSNotification.Name.UIKeyboardDidHide : 키보드를 숨기고 난 후에 호출
  • NSNotification.Name.UIKeyboardWillChangeFrame : 키보드 모양이 바뀌기 전 (iOS 5 이상)
  • NSNotification.Name.UIKeyboardDidChangeFrame : 키보드 모양이 바뀐 후 (iOS 5 이상)
필요한 이벤트를 viewWillAppear 함수에서 NotificationCenter에 등록합니다.
Source Code
    override func viewWillAppear(_ animated: Bool) {
        //화면이 표시될때, Keyboard표시에 대한 이벤트가 발생하면 호출되는 함수를 등록한다.
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidShow(_:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidHide(_:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
    }

화면이 사라질 때, 등록한 것을 삭제해야 한다. 물론 삭제하면 더 이상 이벤트가 발생해도 해당 함수를 호출하지 않습니다.

SourceCode
    override func viewWillDisappear(_ animated: Bool) {
        //화면이 사라질 때, keyboard 표시에 대한 이벤트를 받지 않도록, 등록을 삭제한다.
        NotificationCenter.default.removeObserver(self)
    }


이벤트가 발생할 때, 호출하는 함수들을 정의한다. 해당 이름은 뭐든지 관계없으나 인자로 받는 것은 명시를 해줘야 합니다.

SourceCode
    //키보드가 표시 될 때 호출 되는 함수
    func keyboardWillShow(_ notification:NSNotification) {
        print(notification)
        info(name: "Keyboard Will beShown", with: notification)
        somethingDo(with: notification)
    }
    func keyboardDidShow(_ notification:NSNotification) {
        info(name: "Keyboard Was  Shown", with: notification)
    }
    
    //키보드가 사라질 때, 호출 되는 함수
    func keyboardWillHide(_ notification:NSNotification) {
        info(name: "Keyboard Will beHidden", with: notification)
        somethingDo(with: notification)
    }
    func keyboardDidHide(_ notification:NSNotification) {
        info(name: "Keyboard Was  Hidden", with: notification)
    }

자 이제, 키보드가 표시될 때 마다, 해당 함수들이 호출이 된다.
그럼 다음으로 넘어가자.

2. 호출된 키보드 이벤트 함수에서 키보드의 크기를 알아야, 다른 컴포넌트의 위치를 조정할 수 있다.

이벤트로 전달되는 NSNotification 클래스의 userInfo에서 해당 내용을 가져와야 알 수 있습니다.
키보드가 표시되는 Frame의 정보는 시작할 때와 표시가 다 되었을 때, 어디에 위치할지 알아낼 수 있습니다.
userInfo를 가져와서 description을 출력해 보면 아래와 같습니다.

NSConcreteNotification 0x610000242460 {name = UIKeyboardWillShowNotification; userInfo = {
    UIKeyboardAnimationCurveUserInfoKey = 7;
    UIKeyboardAnimationDurationUserInfoKey = "0.25";
    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";
    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 796}";
    UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 538}";
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";
    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";
    UIKeyboardIsLocalUserInfoKey = 1;
}}

위에서 표시되는 각 UserInfoKey에 대해서 조금 더 자세히 봅시다.
  • UIKeyboardAnimationCurveUserInfoKey : 키보드가 표시될 때 Animation Curve
  • UIKeyboardAnimationDurationUserInfoKey : 키보드 표시되는 시간
  • UIKeyboardBoundsUserInfoKey : 키보드의 Bounds로 크기를 알 수 있는 bound
  • UIKeyboardCenterBeginUserInfoKey : 키보드 표시되기 시작할 때의 중심 Point
  • UIKeyboardCenterEndUserInfoKey : 키보드 표시된 후의 중심 Point
  • UIKeyboardFrameBeginUserInfoKey : 키보드가 표시되기 시작할 때의 frame
  • UIKeyboardFrameEndUserInfoKey : 키보드가 표시된 후의 Frame
  • UIKeyboardIsLocalUserInfoKey : 지금 표시되는 키보드가 Current App에 속한 것인지 True/False로 가지고 있음. iPad의 경우 여러 App이 화면에 표시될 수 있는데, 다른 App이 표시하는 키보드인지 내가 표시한 키보드인지 구분할 수 있음. 이것이 False이면 반응하면 안됨. (iOS 9 이상에서 지원)
아래 처럼 각 호출되는 함수에서 정보를 출력해 봅니다.

SourceCode

    fileprivate func info(name str:String, with notification:NSNotification) {
        if let userInfo = notification.userInfo {
            let frameBegin = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue ?? CGRect.zero
            let frameEnd = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue ?? CGRect.zero
            let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber ?? NSNumber.init(value: 0)
            let duration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber ).doubleValue
            print("\(str) (\(Int(frameBegin.origin.x)),\(Int(frameBegin.origin.y)),\(Int(frameBegin.size.width)),\(Int(frameBegin.size.height))), (\(Int(frameEnd.origin.x)),\(Int(frameEnd.origin.y)),\(Int(frameEnd.size.width)),\(Int(frameEnd.size.height))) curve:\(curve), duration:\(duration)")
        }
    }



3. 결과로 나오는 값은 어떻게 될까요?


iPhone7
세로
Keyboard Will beShown (0,667,375,258), (0,409,375,258) curve:7, duration:0.25
Keyboard Was  Shown    (0,667,375,258), (0,409,375,258) curve:7, duration:0.25
Keyboard Will beHidden (0,409,375,258), (0,667,375,258) curve:7, duration:0.25
Keyboard Was  Hidden   (0,409,375,258), (0,667,375,258) curve:7, duration:0.25
가로
Keyboard Will beShown (0,375,667,194), (0,181,667,194) curve:7, duration:0.25
Keyboard Was  Shown    (0,375,667,194), (0,181,667,194) curve:7, duration:0.25
Keyboard Will beHidden (0,181,667,194), (0,375,667,194) curve:7, duration:0.25
Keyboard Was  Hidden   (0,181,667,194), (0,375,667,194) curve:7, duration:0.25

위 결과를 보시면, 표시되기 전에는 화면 아래 부분에 있다가 표시되면, 위로 올라오게 됩니다.
가로/세로 모드일때 따라서, 키보드의 위치와 크기가 달라집니다.

위 정보를 이용해서, UIViewController에서  ToolBar나 TextField가 키보드 아래에 있을 때, 키보드가 표시될 때 위로 이동시켜서 화면에 표시할 수 있고, 키보드가 사라질 때, 원래 위치로 이동할 수 있습니다.

2016년 6월 29일 수요일

Swift에서 Singletons 구현하기. (Singletons in Swift)


Swift에서 Class를 싱글톤으로 구현하기 위해서는 접근자를 Private로 막아서 별도로 생성하지 못하도록 해야 합니다.
그리고, sharedInstance를 클래스 변수로 두어서, 이 변수를 통해서만 instance를 읽어 가도록 하면 되겠습니다.
final class SingletonObject {
    static let sharedInstance = SingletonObject()
    private init() {
    }
}

이 클래스를 읽어서 쓸 경우는 아래 같이 가져오면 되겠습니다.

    let theInstance = SingletonObject.sharedInstance 



원본: http://www.thomashanning.com/singletons-in-swift/

2015년 2월 12일 목요일

[iOS] OpenSSL을 iOS용으로 컴파일하기.

단계별로, 직접 컴파일 하는 방법과, build script를 이용해서 자동으로 하는 방법이 있습니다.

1. 자동으로 하는 방법

 웹사이트 :  https://github.com/x2on/OpenSSL-for-iPhone
 위 웹사이트에서 소스를 내려받습니다. (Download Zip)
 터미널에서 build-libssl.sh 를 실행하면, 자동을 만들어 줍니다.

 5개의 lib를 만들고, 그것을 하나로 합쳐서, universal lib로 만들어줍니다.
 해당 라이브러리는 /lib 밑에 libcrypto.a, libssl.a로 생성이 되고, /include에 헤더파일을 만들어 줍니다.
 사용하기 위해서는 lib에 있는 2개의 lib를 프로젝트에 추가하고, include를 프로젝트에서 찾을 수 있도록 추가해주면 됩니다.

2. 직접 컴파일하는 방법

- 소스 구하기.

  : 웹사이트(www.openssl.org)에서 버전을 내려 받습니다. 웹사이트에서 받거나 curl을 이용해서 받을 수 있습니다. 다운받을 버전은 1.0.1l 버전입니다.

DavidBaeui-iMac:Test DavidBae$ curl -O https://www.openssl.org/source/openssl-1.0.1l.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 4326k  100 4326k    0     0   279k      0  0:00:15  0:00:15 --:--:--  820k


- 받은 파일 압출 풀기.

  : Finder에서 풀거나, tar로 압축 풀기.

DavidBaeui-iMac:Test DavidBae$ mkdir src
openssl-1.0.1l.tar.gz src
DavidBaeui-iMac:Test DavidBae$ tar zxf openssl-1.0.1l.tar.gz -C /Users/DavidBae/Downloads/OpenSSL/Test/src
 이제 소스는 src 에 들어 있습니다.

- 소스에서 내용을 수정합니다.

//파일이름: crypto/ui/ui_openssl.c
//413 line
//static volatile sig_atomic_t intr_signal; //sig_atomic_t를 int로 변경
static volatile int intr_signal;
 : 소스의 413라인 쯤에서, sig_atomic_t 를 int로 변경해야 합니다.

소스가 준비가 되었으면, 총 5가지 타겟으로 컴파일을 하게 됩니다.
먼저, 시뮬레이터에서 사용할 32bit(i386), 64bit(x86_64)버전,
그리고, 실제 iOS에서 사용할 armv7, armv7s, arm64 버전을 각각 만듭니다.
아래에서 각각 만들고 마지막에 만들어진 5개를 하나의 lib로 묶는 작업을 합니다.


- i386 타겟으로 컴파일하기.

결과를 저장할 디렉토리는 현재 디렉토리의 bin/iPhoneSimulator8.1-i386.sdk 입니다.
물론 만들어놔야 겠지요.

./Configure 명령으로 Makefile을 만듭니다. iphoneos-cross 옵션과, 결과를 저장할 곳을 지정합니다.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$./Configure iphoneos-cross --openssldir=/Users/DavidBae/Downloads/OpenSSL/Test/bin/iPhoneSimulator8.1-i386.sdk
..
..
make[1]: Nothing to be done for `links'.
generating dummy tests (if needed)...
make[1]: Nothing to be done for `generate'.

Configured for iphoneos-cross.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ //<--make파일이 다 만들어졌습니다.

이제 make파일을 수정해야합니다.
makefile을 열어서 아래부분을 수정합니다.

CC = /Applications/Xcode.app/Contents/Developer/usr/bin/gcc -arch i386
//CFLAG= -DOPENSSL_THREADS.....
CFLAG= -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.1.sdk -miphoneos-version-min=7.0 -DOPENSSL....//원래 있던 옵션은 그대로 연결..

makefile내부의 CFLAG에 -isysroot 옵션을 추가해 줍니다. makefile을 저장합니다.
Make를 실행합니다.

DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make
.....
making all in tools...
make[1]: Nothing to be done for `all'.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make install
..
..
cp openssl.pc /Users/DavidBae/Downloads/OpenSSL/Test//bin/iPhoneSimulator8.1-i386.sdk/lib/pkgconfig
chmod 644 /Users/DavidBae/Downloads/OpenSSL/Test//bin/iPhoneSimulator8.1-i386.sdk/lib/pkgconfig/openssl.pc
DavidBaeui-iMac:openssl-1.0.1l DavidBae$
//완료되었음. bin/iPhoneSimulator8.1-i386.sdk 아래에 보면 있습니다.
결과는 /User/DavidBae/Download/OpenSSL/Test/bin/iPhoneSimulator8.1-i386.sdk 디렉토리에 들어 있습니다.
 여기에 있는 lib는 simulator의 32비트 환경에서만 동작하게 됩니다.
 다른 타겟으로도 컴파일하고, 이것과 같이 합쳐두어야 모든 플랫폼에서 사용할 수 있는 universal library가 됩니다.

- x86_64 타겟으로 컴파일하기.

결과를 저장할 디렉토리는 현재 디렉토리의 bin/iPhoneSimulator8.1-x86_64.sdk 입니다.
물론 만들어놔야 겠지요.

./Configure 명령으로 Makefile을 만듭니다. 옵션으로 darwin64-x86_64-cc가 사용되어 i386과는 다르게 설정합니다. 출력할 디렉토리도 같이 설정해 줍니다.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ ./Configure darwin64-x86_64-cc --openssldir=/Users/DavidBae/Downloads/OpenSSL/Test//bin/iPhoneSimulator8.1-x86_64.sdk
...
...
generating dummy tests (if needed)...
make[1]: Nothing to be done for `generate'.

Configured for darwin64-x86_64-cc.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$

makefile 변경하기.
CC = /Applications/Xcode.app/Contents/Developer/usr/bin/gcc -arch x86_64
//CFLAG= -DOPENSSL_THREADS.....
CFLAG= -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.1.sdk -miphoneos-version-min=7.0 -DOPENSSL....//원래 있던 옵션은 그대로 연결..

makefile내부의 CC를 변경하고, CFLAG에 -isysroot 옵션을 추가해 줍니다. makefile을 저장합니다.
Make를 실행합니다.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make
.....
making all in tools...
make[1]: Nothing to be done for `all'.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make install
..
..
cp openssl.pc /Users/DavidBae/Downloads/OpenSSL/Test//bin/iPhoneSimulator8.1-x86_64.sdk/lib/pkgconfig
chmod 644 /Users/DavidBae/Downloads/OpenSSL/Test//bin/iPhoneSimulator8.1-x86_64.sdk/lib/pkgconfig/openssl.pc
DavidBaeui-iMac:openssl-1.0.1l DavidBae$
//완료되었음. bin/iPhoneSimulator8.1-x86_64.sdk 아래에 보면 있습니다.


bin의 iPhoneSimulator8.1-x86_64.sdk의 lib와 include에 파일이 생성이 됨.

- armv7 타겟으로 컴파일하기.

결과를 저장할 디렉토리는 현재 디렉토리의 bin/iPhoneSimulator8.1-x86_64.sdk 입니다.
물론 만들어놔야 겠지요.

./Configure 명령으로 Makefile을 만듭니다. 옵션으로 darwin64-x86_64-cc가 사용되어 i386과는 다르게 설정합니다. 출력할 디렉토리도 같이 설정해 줍니다.

DavidBaeui-iMac:openssl-1.0.1l DavidBae$ ./Configure iphoneos-cross --openssldir=/Users/DavidBae/Downloads/OpenSSL/Test/bin/armv7/
...
...
generating dummy tests (if needed)...
make[1]: Nothing to be done for `generate'.

Configured for iphoneos-cross.

DavidBaeui-iMac:openssl-1.0.1l DavidBae$ 

makefile 변경하기.
CC = /Applications/Xcode.app/Contents/Developer/usr/bin/gcc -arch armv7
//CFLAG= -DOPENSSL_THREADS.....
CFLAG= -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk -miphoneos-version-min=7.0 -DOPENSSL....//원래 있던 옵션은 그대로 연결.. CFLAG에 다른 -isysroot가 있는지 확인이 필요함.

makefile내부의 CC를 변경하고, CFLAG에 -isysroot 옵션을 추가해 줍니다. makefile을 저장합니다.
Make를 실행합니다.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make
.....
making all in tools...
make[1]: Nothing to be done for `all'.
DavidBaeui-iMac:openssl-1.0.1l DavidBae$ make install
..
..
cp openssl.pc /Users/DavidBae/Downloads/OpenSSL/Test//bin/armv7/lib/pkgconfig
chmod 644 /Users/DavidBae/Downloads/OpenSSL/Test//bin/armv7/lib/pkgconfig/openssl.pc
DavidBaeui-iMac:openssl-1.0.1l DavidBae$
//완료되었음. bin/armv7 아래에 보면 있습니다.

bin/armv7/lib와 include에 파일이 생성이 됨.

- armv7s 타겟으로 컴파일하기.
: armv7을 armv7s로 변경해서, 진행

- arm64 타겟으로 컴파일하기.
: arm7s를 arm64로 변경해서 진행


- Universal Library 만들기

 만들어진 5개의 lib를 하나로 합친다.

DavidBaeui-iMac:openssl-1.0.1l DavidBae$ lipo -create /Users/DavidBae/Downloads/OpenSSL/Test/bin/i386/lib/libssl.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/x86_64/lib/libssl.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/armv7/lib/libssl.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/armv7s/lib/libssl.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/arm64/lib/libssl.a -output /Users/DavidBae/Downloads/OpenSSL/Test/lib/libssl.

DavidBaeui-iMac:openssl-1.0.1l DavidBae$ lipo -create /Users/DavidBae/Downloads/OpenSSL/Test/bin/i386/lib/libcrypto.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/x86_64/lib/libcrypto.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/armv7/lib/libcrypto.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/armv7s/lib/libcrypto.a /Users/DavidBae/Downloads/OpenSSL/Test/bin/arm64/lib/libcrypto.a -output /Users/DavidBae/Downloads/OpenSSL/Test/lib/libcrypto.a

DavidBaeui-iMac:openssl-1.0.1l DavidBae$

OpenSSL에 대한 라이브러리가 생성이 되었다.

1번에서 build-libssl.sh 을 실행하면, 2번을 했던거와 같은 방법으로, 라이브러리를 만들어 준다.

잘 사용하시길....



2015년 1월 19일 월요일

[iOS] CoreData에서 Entity의 개수를 효율적으로 읽어오기.

먼저 TableViewController의 경우, NSFetchedResultController를 사용하면 가장 효율적으로 관리할 수 있습니다.
특정 개수만 로딩 시켜서, 화면에 표시하므로 모든 데이터를 가져올 필요가 없게 됩니다.

하지만, 특정 경우, 지금 그 Entity의 개수가 몇개인지 알아야 할 경우가 있습니다.
이런때, 해당 Entity가 데이터가 크면, 그 개수 만큼의 NSManagedObject가 만들어지고, 데이터도 다 로딩 되므로, 순간 메모리 사용량이 커지게 됩니다.

이 경우, NSFetchRequest의  setIncludeSubentities를 NO로 해서 subentity들이 로딩 되지 않도록 하고,
context의 countForFetchRequest를 사용해서 해당되는 개수만 읽어 올 수 있게 됩니다.

참조: StackOverflow: Cocoa Core Data efficient way to count entities!

[iOS] unwind 함수를 코딩으로 호출하기.

Storyboard에서 Exit할 수 있는 Unwind segue를 만든다.
- 버튼에서 Exit로 Ctrl-Drag에서 만들 수도 있고
- 해당 View Controller의 아이콘에서 Exit로 Ctrl-Drag해서 Unwind segue를 만든다.

왼쪽 리스트에서 Unwind Segue from XXViewController를 선택하고, 오른쪽 Attribute Inspector에서 Identifier를 설정할 수 있다.

그러면,  코드상에서 performSegueWithIdentifier로 호출할 수 있다.

[참고: stackoverflow - How to perform Unwind segue programmatically?]


2014년 12월 26일 금요일

[iOS] 원형의 그라디언트 이미지를 그려봅시다. (Rendering a radial gradient)

Radial Gradient

원형으로 배경을 은은하게 채워야하는 경우에, 아래와 같이 그림이 필요합니다.
이미지를 만들어서 넣으면 좋겠지만, Core Graphics를 사용해서 그릴 수 있습니다.
만들 이미지
source code
- (void)drawRadialGradient:(UIColor *)startColor
                  endColor:(UIColor *)endColor
                startPoint:(CGPoint)startPoint
               startRadius:(CGFloat)startRadius
                  endPoint:(CGPoint)endPoint
                 endRadius:(CGFloat)endRadius
                   context:(CGContextRef)context
{
    CGColorRef colorRef = startColor.CGColor;
    CGColorRef endColorRef = endColor.CGColor;
    NSArray *marrColors=[NSArray arrayWithObjects:
                         (__bridge id)colorRef,    //start color
                         (__bridge id)endColorRef, //end color
                         nil];
    CFArrayRef colors =(__bridge CFArrayRef)(marrColors);
    CGColorSpaceRef colorSpc = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpc, colors, Nil);
    
    // generates Radial Gradient
    CGContextDrawRadialGradient(context, gradient,
                                startPoint, startRadius,
                                endPoint, endRadius,
                                0);
    CGColorSpaceRelease(colorSpc);
    CGGradientRelease(gradient);
}
 



이 함수를 이용해서, 중심에 그리면, 위 만들이미지와 같은 효과를 얻을 수 있습니다.

Drawing a radial gradient like Lens


그러면, Gradient에 이미지를 추가하면 중간에 이미지가 추가가 됩니다.
source code
- (void)drawRadialGradient:(UIColor *)startColor
                  midColor:(UIColor *)midColor
                  endColor:(UIColor *)endColor
                startPoint:(CGPoint)startPoint
               startRadius:(CGFloat)startRadius
                  endPoint:(CGPoint)endPoint
                 endRadius:(CGFloat)endRadius
                   context:(CGContextRef)context
{
    CGColorRef colorRef = startColor.CGColor;
    CGColorRef midColorRef = midColor.CGColor;
    CGColorRef endColorRef = endColor.CGColor;
    NSArray *marrColors=[NSArray arrayWithObjects:(__bridge id)colorRef,
                         (__bridge id)midColorRef,
                         (__bridge id)endColorRef, nil];
    CFArrayRef colors =(__bridge CFArrayRef)(marrColors);
    CGColorSpaceRef colorSpc = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpc, colors, Nil);
    
    // generates Radial Gradient
    CGContextDrawRadialGradient(context, gradient,
                                startPoint, startRadius,
                                endPoint, endRadius,
                                0);
    CGColorSpaceRelease(colorSpc);
    CGGradientRelease(gradient);
}
호출하는 소스
- (void)drawRect:(CGRect)rect {
    
    CGContextRef context = UIGraphicsGetCurrentContext();

    
    // Drawing code
    UIColor *whiteColor = [UIColor whiteColor];
    UIColor *blueColor = [UIColor blueColor];
    UIColor *greenColor = [UIColor greenColor];
    
    CGSize size = self.frame.size;
    CGPoint center = CGPointMake(size.width/2, size.height/2);
    /*/
    [self drawRadialGradient:greenColor endColor:self.backgroundColor
                  startPoint:center startRadius:0
                    endPoint:center endRadius:size.width/2
                     context:context];
    /*/
    [self drawRadialGradient:greenColor midColor:blueColor endColor:whiteColor
                  startPoint:center startRadius:0
                    endPoint:center endRadius:size.width/2
                     context:context];
    CGPoint point2 = CGPointMake(size.width/2-15, size.height/2-15);
    [self drawRadialGradient:whiteColor endColor:greenColor
                  startPoint:point2 startRadius:0
                    endPoint:point2 endRadius:5
                     context:context];
    point2 = CGPointMake(size.width/2+15, size.height/2+15);
    [self drawRadialGradient:whiteColor endColor:greenColor
                  startPoint:point2 startRadius:0
                    endPoint:point2 endRadius:2
                     context:context];
     //*/
}


결과물
3가지 색으로만
3가지 색에, 점 2개 찍은것


나름 랜즈와 비슷한 것이 나온것 같군요.