2015년 11월 22일 일요일

Xcode Log - Label / Attributed Text - Replace

        let mutableString:NSMutableString = (resultLabel.attributedText as! NSMutableAttributedString).mutableString
        mutableString.replaceOccurrencesOfString("@1", withString: "109", options: 
NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, mutableString.length))

결국 이 두 줄의 코드.

AS3 할때도 이런 경우가 있었는데 HTML 형식으로 formatting한 label을 다룰때 생각보다 간단하지 않았다.
물론 해결하고 나니 속 시원했었지만.


이게 다 저 @1 부분을 replace 하려고 시작한 일이었다.
조금 더 다양한 가능을 보려고 손을 좀 더 보았다.



Xcode 에서 이걸 직접 살펴보았다.

                                <attributedString key="attributedText">
                                    <fragment content="이거이 사람이 짓이 아닌가 봅니다.
"
>
                                        <attributes>
                                            <color key="NSColor" cocoaTouchSystemColor="darkTextColor"/>
                                            <font key="NSFont" size="17" name="AppleSDGothicNeo-Regular"/>
                                            <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
                                        </attributes>
                                    </fragment>
                                    <fragment content="진짜">
                                        <attributes>
                                            <color key="NSColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
                                            <font key="NSFont" size="24" name="AppleSDGothicNeo-Bold"/>
                                            <font key="NSOriginalFont" size="17" name="AppleSDGothicNeo-Bold"/>
                                            <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
                                        </attributes>
                                    </fragment>
                                    <fragment content=" 속이 상해서 참말로
"
>
                                        <attributes>
                                            <color key="NSColor" cocoaTouchSystemColor="darkTextColor"/>
                                            <font key="NSFont" size="17" name="AppleSDGothicNeo-Regular"/>
                                            <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
                                        </attributes>
                                    </fragment>
                                    <fragment content="@1%">
                                        <attributes>
                                            <color key="NSColor" cocoaTouchSystemColor="darkTextColor"/>
                                            <font key="NSFont" size="24" name="AppleSDGothicNeo-Regular"/>
                                            <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
                                        </attributes>
                                    </fragment>
                                    <fragment content=" 부분만 살짝 갈아끼워줍니다.">
                                        <attributes>
                                            <color key="NSColor" cocoaTouchSystemColor="darkTextColor"/>
                                            <font key="NSFont" size="17" name="AppleSDGothicNeo-Regular"/>
                                            <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
                                        </attributes>
                                    </fragment>
                                </attributedString>

보면 attributedString 아래에 fragment 단위로 누어져있고 그 아래 attributes 가 있고 그 안에 color/font/paragrapthStyle 등등이 있는 걸 볼 수 있다.

HTML DOM 을 만드는 것과 비슷하게 할 수 있지만 지금 당장 필요한 것은 본문을 손상하지 않고 내용만 바꾸고 싶은데 이걸 전체를 들었다가 다시 생성하는 건 너무 삽질이라고 생각.

debugger를 열고 attributedText를 관찰해보자

(lldb) print (resultLabel.attributedText)
(NSAttributedString?) $R10 = 0x00007fa99c8a2f90 {
  ObjectiveC.NSObject = {...}
}


이런게 있다.
Mutable!! 바꿀 수 있다는 소리다!

(lldb) po (resultLabel.attributedText as! NSMutableAttributedString).mutableString
이거이 사람이 짓이 아닌가 봅니다.
진짜 속이 상해서 참말로
@1%
부분만 살짝 갈아끼워줍니다.

오케이!
이거야 이거!
mutableString 이면 바꿀 수 있다.


mutableString 을 보니 NSMutableString 이다.

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSMutableString_Class/index.html#//apple_ref/occ/instm/NSMutableString/replaceOccurrencesOfString:withString:options:range:

MutableString 이라면 이런게 있지!
replaceOccurrencesOfString!!

Declaration

SWIFT
func replaceOccurrencesOfString(_ targetString,
                     withString replacementString,
                        options optionsNSStringCompareOptions,
                          range searchRangeNSRange) -> Int
OBJECTIVE-C
- (NSUInteger)replaceOccurrencesOfString:(NSString *)target                              withString:(NSString *)replacement                                 options:(NSStringCompareOptions)opts                                   range:(NSRange)searchRange
바꿀 것은 target 에 주고 withString 에 변경할 문자열을 지정한다.
정확한 일치를 원하므로 NSStringCompareOptions.LiteralSearch 를 사용한다.

여기에 Range 가 좀 걸리는데
만들어주자.

Declaration

SWIFT
func NSMakeRange(_ locInt_ lenInt) -> NSRange
OBJECTIVE-C
NSRange NSMakeRange ( NSUInteger loc, NSUInteger len );

Return Value

An NSRange with location location and length length.

Availability

Available in OS X v10.0 and later.
0부터 mutableString의 길이까지 지정해주면 된다.

새로 만드는 걸 했다면 거대한 삽질을 할뻔.



2015년 11월 19일 목요일

Xcode 개발 Log

AlamoFire 를 사용한 경우 swift에서 JSON 취급이 조금 헷갈렸다.


        Alamofire.upload(urlRequest.0, data: urlRequest.1)
            .progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) -> Void in
                print("\(totalBytesWritten) / \(totalBytesExpectedToWrite)")
            }
            .responseJSON { response in
                if response.result.isSuccess {
                    /* avoid optional */
                    let result:NSDictionary = response.result.value as! NSDictionary
                    print((result["facetype"] as! NSArray)[1])
                } else {
                    print("Cannot find face")
                }
            }

lldb에서 po 로 열심히 찍어본 결과
JSON으로 넘겨준 경우 NSDictionary 와 NSArray를 결국 열심히 찍어보는 수 밖에 없었다.
최종 결과물도 as String 형변환을 해줘야함.

swift는 좋은 언어지만 애플이 잘못했지.


2015년 11월 15일 일요일

Xcode Key binding

1. 우상단 컨트롤들


왼쪽부터 
Show the Standard View - Cmd + Enter
Show the Assistant View - Cmd + Option + Enter
Show the Version Editor - Cmd + Option + Shift + Enter


왼쪽부터
Hide or show the Navigation - Cmd + 0 
Hide or show the Debug Area - Cmd + Shift + Y
Hide or show the Utilities - Cmd + Alt + 0 

2. Storyboard

Hide or show Document Online - 바인딩 없음(Cmd + 9 로 설정) 

3. 우측 상단 바로 아래 Inspectors
왼쪽부터
Show the File inspector - Cmd + Shift + 1
Show Quick Help inspector - Cmd + Shift + 2
Show the Identity inspector - Cmd + Shift + 3
Show the Attributes inspector - Cmd + Shift + 4
Show the Size inspector - Cmd + Shift + 5
Show the Connections inspector - Cmd + Shift + 6

4. 우측 하단 Library
왼쪽부터
Show the File Template Library - Cmd + Ctrl + Option + 1
Show the Code Snippet Library - Cmd + Ctrl + Option + 2
Show the Object Library - Cmd + Ctrl + Option + 3
Show the Media Library - Cmd + Ctrl + Option + 4

5. 기타
Run - Cmd + R
Stop - Cmd + .
Resolve Auto Layout Issue - Update Frames - Cmd + Option + =

2015년 11월 13일 금요일

python log - opencv

opencv 를 프로젝트 때문에 사용

opencv 자체는
apt-get install python-opencv
만 하면 되니 간편

OS X에선
brew tap homebrew/science
brew install opencv
로 설치하고 심볼릭 링크를 꼭 만들어줘야함.
cd /Library/Python/2.7/site-packages 후
ln -s /usr/local/Cellar/opencv/2.4.12/lib/python2.7/site-packages/cv.py cv.py
ln -s /usr/local/Cellar/opencv/2.4.12/lib/python2.7/site-packages/cv2.so cv2.so

내 경우는 이렇게 opencv 버전에 따라 2.4.12 대신 다른 걸 사용할 수 있다.

libdc1394 error: Failed to initialize libdc1394

이런 오류가 발생할 수 있는데
http://stackoverflow.com/questions/12689304/ctypes-error-libdc1394-error-failed-to-initialize-libdc1394

여기 내용을 보고
sudo ln /dev/null /dev/raw1394

1394 관련 내용 추가

sudo apt-get install python-pip

로 pip 도 설치. orangepi 기준으론 시간이 좀 걸림 ( https://www.raspberrypi.org/documentation/linux/software/python.md ) 참조.

http://www.slideshare.net/arload/flask-restful-api
Stack을 줄이기 위해 사용해야하는 기존 엔진을 직접 flask로 웹서버화 할까도 생각 중


ImportError: No module named stasm 오류 난다.
Pystasm도 설치

pip install PyStasm

설치 중 오류난다.

src/stasm.h:33:30: fatal error: opencv2/opencv.hpp: No such file or directory

슬슬 괴롭다.
얘는 뭐 자료도 없고 stasm 뭐니. 
http://www.milbo.users.sonic.net/stasm/ 에서 tar.gz을 받고

https://github.com/alyssaq/stasm_build 따라서 빌드했더니

➜  stasm4.1.0  ./build/stasm_util -s -f data ../test_img/JH0516.jpg
뭐 이런건 잘 나옴.
...
499 671
474 681
446 685
418 682
394 674
x,y만 좌륵 나오고 친절하게 점까지 찍어준다


sklearn 추가.
sudo apt-get install python-sklearn  

OSX)
brew install scipy



pip install scikit-learn
답답해서 egg 파일 추가 PyStasm-0.3.0-py2.7-linux-x86_64.egg 를 다운받아 easy_install PyStasm-0.3.0-py2.7-linux-x86_64.egg 로 설치

ImportError: libopencv_core.so.3.0: cannot open shared object file: No such file or directory

이번엔 호환이 안된다.
sudo ldconfig -v | grep opencv_core


libopencv_core.so.2.4 -> libopencv_core.so.2.4.8

현재 버전이 3.0 이 아니다.
cmake 부터 받고

opencv 3.0 도 받자.

cmake 하고
make
sudo make install
sudo ldconfig
까지
OS X에선 실패했다.

근데 이번엔 numpy 쪽 오류
정확하게 이 증상.
답변자 말대로 하면 안되고
sudo apt-get remove python-joblib
sudo apt-get remove python-sklearn
설치 후 
pip install -U scikit-learn
하니 된다.

거의 다 되었다 싶은데 이젠
AttributeError: 'module' object has no attribute 'CV_LOAD_IMAGE_COLOR'

이 오류가;;
보니까 소스를 고쳐야겠다.

    targetImage = cv2.imread(fileName, cv2.CV_LOAD_IMAGE_COLOR)

이 부분을 이렇게
    targetImage = cv2.imread(fileName, cv2.IMREAD_COLOR)

고치니 일단 작동은 한다.
솔직히 속도는 한심하다.

2015년 11월 7일 토요일

iOS Autolayout 학습 로그

Constraint 값은 전체 뷰에 대한 절대값이라고 일단 이해.
가로가 320이라면 Width를 constraint로 줄 경우 160이면 50% 정도의 넓이가 됨.

위치 조정 시엔 조정하고 싶은 뷰를 선택 후 cmd 를 누르고 기준이 될 뷰까지 드래그.
뷰를 선택하고 Show the Size Inspector를 쓰면 좀 편함.


크기의 경우 상대적 값을 주고 싶으면
비교할 대상인 부모와 자신을 cmd 키를 누르고 복수 선택 후 Pin 에서 일단 Equal Width(Height)를 선택.
그 다음 비율은 해당 Constraint을 선택 후 Equal Width(Heights) Constraint 에서 Multiplier 값을 1보다 작은 값으로 조정.
http://stackoverflow.com/questions/14935825/autolayout-make-height-of-view-relative-to-half-superview-height/26700537#26700537

Navigation Controller 랑 연결한 ViewController 는 Ctrl+Drag 로 Relationship을 연결한다.

아, 별도로 굉장히 고생한 거

http://stackoverflow.com/a/33051150/880991
Could not launch "XXXX"
process launch failed: Security 시 대처법
iOS 장비에서 Settings > General > Profiles 선택
해당 계정에 대해 Trush를 시전

Podfile 에 RealmMeteor를 넣어봤더니 그 뒤로 언인스톨 해도 실기계에서 계속 오류

rm -rf ~/Library/Developer/Xcode/DerivedData/앱이름-* 으로 일단 비우고
다시 시작해본다.

2015년 11월 5일 목요일

iOS Swift 학습 로그

오래간만에 의뢰로 iOS app을 만들고 있다.
정말 많이 편해졌다. 놀랍다.
swift만해도 벌써 몇번이나 업데이트 하고;

일단 pod 파일. cocoapod은 정말 너무 좋다.
먼저 프로젝트 생성 하고 Meteor DDP를 쓰기 위해 touch Podfile 하고

platform :ios, '8.0'
use_frameworks!

pod 'Meteor'

이렇게 쓰면 끝
pod install 한 뒤 *.xcworkspace 를 열면 끝.
* 주의: install중 중간에 정지하면 기존 pod 가 망가질 수 있음

사용은 AppDelegate.swift를 열고
전역 변수로 
let Meteor = METCoreDataDDPClient(serverURL: NSURL(string: "ws://www.YOURMETEORAPP.com/websocket")!)

지정하고 

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        Meteor.connect()
        
        return true
    }

이런 식으로 Application 기동 시 Meteor 접속.

* swiftDDP 를 내장한 RealmMeteor가 더 좋아보인다.

Storyboard 의 segue (세그웨이라고 읽음) 상당히 좋았다.

일단 첨에 진입점이 되는 Controller 에 Show Attributes Inspector를 열고 

Is Initial View Controller를 체크.
실수로 지우거나 새로 Tab Bar/Split View/Collection View/Navigator Controller 등을 생성할 때 꼭 확인하자.

View와 연결되는 *.swift controller들을 만들 땐import Foundation

import UIKit

class YOURController:UIViewController {
}

으로 시작.

간단한 사용자 정보 저장은 Key/Value Store인 NSUserDefaults.standardUserDefaults() 를 사용.

읽기는 (Boolean의 경우)

userDefaults.boolForKey("KEY")

쓰기는

userDefaults.setBool(true, forKey: "KEY")

이런 식. 다른 타입도 대동소이.

Contstraint는 뭔가 헷갈린다.
배치를 다 한 뒤 해주는 게 삽집을 덜 하는 듯.

Segue는 swift안에서 수동으로 할 때 Identifier 를 지정해야 한다.



이렇게 Segue를 선택(파랑색으로 변함)하고 Attribute Inspector에서 Identifier를 지정.

performSegueWithIdentifier("noticeSegue", sender: self)
이런 식으로 Identifier를 넣어서 사용한다.
modal Popup의 경우 viewDidLoad() 에서 호출해도 잘 되더라.

닫을 때는
self.dismissViewControllerAnimated(true, completion: {})

이런 식으로 닫으면 됨.

스토리보드와 코드사이에서 ctrl 드래그로 IBOutlet 이나 IBAction을 지정할 때
오른쪽 상단에 원두개가 겹쳐있는 아이콘(Show Assistant editor)를 열면 편리.

주의할 점은 왼쪽에 있는 Project Navigator 에서 파일을 선택해도 왼쪽 에디터만 바뀐다.
오른쪽은 상단 바를 클릭해서 찾아가야함.

UIWebView 사용 시 info.plist 에 권한을 열어줘야함.
안그러면 사용할 수 없다.

App Transport Security Settings > Allow Arbitrary Loads 에서 Boolean 을 YES로

초기 로딩할 땐
webView.loadRequest(NSURLRequest(URL: NSURL(string: "http://YOURURL/")!)) 

이런 식으로 쓰면 된다.
Memory Warning이 나면서 Crash 할 수 있는데

    override func didReceiveMemoryWarning() {
        // prevent MemoryWarning
        NSURLCache.sharedURLCache().removeAllCachedResponses()
    }

didReceiveMemoryWarning를 받아서 캐쉬를 지워주면 좀 낫다고 한다.

UIImagePickerController 사용 시 해당 Controller 에 UIImagePickerControllerDelegate, UINavigationControllerDelegate 를 추가해야함.

class CameraController:UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
  ...
}

이런 식.

objective-c 형식의 파일은 header(*.h)가 들어간 파일을 swift로 bridge 파일 만들고 Build Settings 에 Swift Compiler - Code Generation > Objective-C Bridging Header 아래 Debug / Release 아래 각각 만들어 준다.


마지막으로 *.xcdatamodel 에서 Attribute명으로 description 을 사용할 수 없다. 주의.

2015년 11월 3일 화요일

Meteor Less 팁

meteor 는 자동(규칙에 맞게)으로 파일들을 모아서 만드는데
less 일 경우엔 @import 라는 게 있어서 조금 헷갈린다.

less-autofixer 패키지랑 같이 쓰니까 더욱 헷갈려서 결국 RTFM 하기로 함.
패키지 문제니까 https://github.com/meteor/meteor/tree/devel/packages/less 를 보았다.

예전에 쓰던 방법이랑 좀 다른 것도 있어서 정리.


  1. less 사용
    1. 기본
      meteor add less
    2. package 에서
      Package.onUse(function (api) {
        ...
        api.use('less');
        ...
      });
  2. 파일 규칙
    1. *.less  : 자동 추가. import 불가
    2. *.import.less : 자동 추가 x. import 가능
    3. imports 디렉토리 아래 *.less : 자동 추가 x. import 가능
    4. packages 인 경우 packages.js 에서 {isImport:true} 옵션을 사용.
      api.addFiles('x.less', 'client', {isImport: true}) 이런 식으로 지정한 경우 import 가능
  3. import
    1. 다른 패키지에서 import
      @import "{my-package:pretty-buttons}/buttons/styles.import.less"
    2. 대상 앱에서 import
      @import "{}/client/styles/imports/colors.less"
    3. package 안에서 import
      @import "/path/to/style.import.less";
이제까지 계속 *.import.less 패턴만 썼는데 **/imports/**/*.less 패턴도 써봐야겠다. 깔끔하네.