iOS6부터 새로 추가된 AutoLayout 기능은 너무 편리하다. (사실... iOS6에서는 인터페이스가 엉망이라 불편했는데 iOS7부터는 많이 개선되었다.)


본론으로 들어가서, 스토리보드에AutoLayout을 적용하면 동적으로 프레임 좌표변경이 불가능하다.

정확히 말하면 분명 메모리상에서는 이미 바뀌어 있지만 화면에 표시될땐 변경된 좌표로 표시되지 않는 현상이 발생한다.

그 뿐만아니라 layer에 회전을 시키는 것도 제대로 동작하지 않는다.


지금까지 해결방법으로 스토리보드에서 AutoLayout를 해제하여 해결해왔는데 (정확히 말하면 AutoLayout사용을 포기한거임) 이제서야 제대로 된 해결방법을 알아냈다.



그 방법이란 좌표를 변경할 뷰를 일단 한번 띄어냈다가 다시붙이는 방법이다. 그렇게 하면 그부분만 AutoLayout의 쓸데없는 방해를 피할 수 있다.


예를들어..


for (UIView *v in moveView.subviews) {

        

        if ([v isKindOfClass:[UIView class]] == YES) {

            //변경을 원하지 않으면 패스

            continue;

        }

        

        [v removeFromSuperview];

        

        //프레임을 변경

        v.frame = CGRectMake(0, 0, 100, 200);

        

        [self.view addSubview:v];

        

    }



대충 이런식의 코딩이 가능하다.

참고로 뷰를 띄었다가 붙였을경우 IBOutlet에 연결된 커넥션이 무효화될까 걱정했었는데 무사히 동작한다.


혹시 모를 AutoLayout 때문에 고생하시는 개발자분들은 참고하시길.


2013.03.22 추가내용.

AutoLayout적용한 컨트롤러에서 UIScollView(스크롤뷰)에서 컨텐츠사이즈가 적용안되는문제가 발생하는데 아래와 같은 방법으로 해결할 수있다.


- (void)viewDidLayoutSubviews {

    

    [super viewDidLayoutSubviews];

    

    // 스코롤 컨텐츠사이즈 변경

    [scView setContentSize:CGSizeMake((_rView.frame.size.width + _tView.frame.size.width),

                                      [UIScreen mainScreen].bounds.size.height)];

    

    [self.view layoutSubviews]; //이부분이 중요

}



Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

아이폰개발시 자주사용하는 매크로를 메모해 둔다.

매번 인터넷 찾기도 귀찮고 만들기도 귀찮고 해서..


계속 추가 갱신예정. 2014.10.111


시간지연실행GCD

- (void)doSomething {
    
    NSData *data = [NSData data];
    int64_t delay = 3.0; // In seconds
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC);
    dispatch_after(time, dispatch_get_main_queue(), ^(void){

        [self doSomethingLater:data];
 
        // Or put the code from doSomethingLater: inline here
    });
}

- (void)doSomethingLater:(NSData *)data {

    // Do something cool with data.
}


좌표지정매크로

#define CGRectSetPosition(r, p)             CGRectMake(p.x, p.y, r.size.width, r.size.height)

#define CGRectSetXY(r, x, y)                CGRectMake(x, y, r.size.width, r.size.height)

#define CGRectSetX(r, x)                    CGRectMake(x, r.origin.y, r.size.width, r.size.height)

#define CGRectSetY(r, y)                    CGRectMake(r.origin.x, y, r.size.width, r.size.height)

#define CGRectSetSize(r, s)                 CGRectMake(r.origin.x, r.origin.y, s.width, s.height)

#define CGRectSetWidthAndHeight(r, w, h)    CGRectMake(r.origin.x, r.origin.y, w, h)

#define CGRectSetWidth(r, w)                CGRectMake(r.origin.x, r.origin.y, w, r.size.height)

#define CGRectSetHeight(r, h)               CGRectMake(r.origin.x, r.origin.y, r.size.width, h)



메인스레드에서의 처리가 필요할때 사용하는 dispatch구문

dispatch_async(dispatch_get_main_queue(), ^{

        //Animation..

        

    });



싱글톤 사용시 사용하는 dispatch구문

+ (AppContext* )sharedInstance

{

    static dispatch_once_t  onceToken;

    dispatch_once(&onceToken, ^{

        _sharedInstance = [[AppContext alloc] init];

        

        //initialize

        [_sharedInstance loadData];

        

    });

    

    return _sharedInstance;

}



deprecated메소드 표시 매크로 

__attribute((deprecated("use x method")))


+(void)myMethod:(NSString*)abc __attribute((deprecated("use xxx method")));

+(void)myMethod:(NSString*)abc __deprecated;    //메세지없이 간단히 표시


//프로퍼티도 같은 방식으로

@property (strong) NSObject *object __attribute((deprecated("use xxxx property")));



디버그모드 일때만 로그출력하는 매크로

#ifdef DEBUG

#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);

#else

#define DLog(...)

#endif


UIColor 생성 매크로 

#define RGB(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]

#define RGBA(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:a]



UIColor - Hex값으로 색상지정 카테고리 메소드

+ (id)colorWithHexString:(NSString *)hex alpha:(CGFloat)a

{

    

    NSScanner *colorScanner = [NSScanner scannerWithString:hex];

    unsigned int color;

    if (![colorScanner scanHexInt:&color]) return nil;

    CGFloat r = ((color & 0xFF0000) >> 16)/255.0f;

    CGFloat g = ((color & 0x00FF00) >> 8) /255.0f;

    CGFloat b =  (color & 0x0000FF) /255.0f;


    return [UIColor colorWithRed:r green:g blue:b alpha:a];

}



시뮬레이터 상태에서만 실행


#if TARGET_IPHONE_SIMULATOR
    // TODO:
#endif



라디안 계산 


*여기서 d는 각도를 뜻한다.

#define DEGREES_TO_RADIANS(d) (d * M_PI / 180)


덧붙여 설명하자면,

원둘레 = 2*M_PI*R

호의 길이 = 2*M_PI*R*각도/360 --> 각도가 360도일경우에는 원둘레가 되므로..

즉, R*M_PI*각도/180


여기서 라디안이라함은 위에 색칠한 부분을 가르킨다. 


/** Degrees to Radian **/
#define degreesToRadians( degrees ) ( ( degrees ) / 180.0 * M_PI )

/** Radians to Degrees **/
#define radiansToDegrees( radians ) ( ( radians ) * ( 180.0 / M_PI ) )




웹사이트 링크모음.


appledoc로 도큐멘트생성하기 (Doxygen과 비슷한거.)

http://qiita.com/mtgto/items/c97c59d93fe67d748055


iOS개발관련 최신기술 소개해주는곳.

http://safx-dev.blogspot.jp/p/ios.html

Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

iOS부터 가능해진 블럭코드 ^{}  (대충 이런형식의 처리로직?을 파라메터로 넘기는 방법) 에서 "ARC Retain Cycle Error " 라는 경고가 발생하는 경우가 있다.


Capturing 'self' strongly in this block is likely to lead to a retain cycle


ARC로 된 프로젝트에서 블럭코딩을 할 경우 블럭 밖에 선언된 변수가 블럭안에서 값이 변할때 위와같은 에러가 발생한다고 한다.

내자신도 블럭코드는 아직 지식이없어 자신있게 말할순 없지만...


어쨋든 해결방법은 문제의 변수를 __block 로 선언하면 경고가 사라진다.


만약 이런소스가 있다고 가정하면,

@implementation Hoge
-(void)hogeMethod{
  hogeHandler = ^(Fuga *fuga){
    [self someMethod:fuga];
  };
}
@end


이런식으로 변경.

@implementation Hoge
-(void)hogeMethod{
  // 여기서self를 카피
  __block Hoge *blockself = self;
  hogeHandler = ^(Fuga *fuga){
    [blockself someMethod:fuga];
  };
}
@end

Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

전글에서 XCode상에서 C++모듈을 사용하는 방법을 알아보았다.

이번엔 단순이 wrapper클래스를 만들어 C++모듈을 의식하지 않고 Objective-C에서 사용할 수 있도록 wrapper메소드를 만들어보자.


아래와 같은  C++ 클래스 라이브러리가 있다고 치자.

Wrapped.hpp

#ifndef __WRAPPED_H__

#define __WRAPPED_H__


class CWrapped

{

public:

 CWrapped(int param1, int param2);

 unsigned int doSomething();

}


#endif

Wrapped.cpp

#include "Wrapped.hpp"


CWrapped::CWrapped(int param1, int param2)

{

 // do something

}


unsigned int CWrapped::doSomething()

{

 // do something

 return 0;

}


이것을Objective-C++의 문법으로 wrap해야 하지만 이 wrap를 Objective-C에서 이용하기 위해서는 조금 해더파일의 C++의 문법을 사용하지 않는 단순한 Objective-C 문법으로 하지 않으면 안된다.

특히 class키워드를 사용하지 않기위해 Objective-C++ 의 헤더파일은 #ifdef 을 사용한다.


Wrapper.h (헤더파일)

#import <Foundation/NSObject.h>


// declare CWrapped class for .mm (Obj-C++) files

#ifdef __cplusplus

class CWrapped;

#endif

// declare CWrapped class for .m (Obj-C) files (do not use the "class" keyword.)

#ifdef __OBJC__

#ifndef __cplusplus

typedef void CWrapped;

#endif

#endif


@interface Wrapper : NSObject {

 CWrapped* mWrapped;

}

- (id)init:(int)param param2:(int)param2;

- (unsigned int)doSomething;

@end


Wrapper.mm (구현부분)

#import "Wrapper.h"


@implementation Wrapper


- (id)init:(int)param1 param2:(int)param2

{

 if (self = [super init]) {

  mWrapped = new CWrapped(param1, param2);

 }

 return self;

}


- (void)dealloc

{

 delete mWrapped;

 [super dealloc];

}


- (unsigned int)doSomething

{

 return mWrapped->doSomething();

}


@end


Objective-C에서는 아래와 같이 이용할 수 있다.


main.m

#import "Wrapper.h" // Objective-C 에서 보는 class CWrapped 가 아닌 typedef void CWrapped 이기때문에 컴파일이 됨.


int main(int argc, char **argv)

{

 Wrapper *wrapper = [[Wrapper alloc] init:10 param2:10];

 unsigned int result = [wrapper doSomething];

 [wrapper dealloc];

}


위의 코드는 실제로 돌려보지는 않았다. 아래는 참고사이트

http://note.sonots.com/Comp/CompLang/Cocoa/ObjectiveCWrapper.html


이 코드를 베이스로 Wrapper클래스를 만들기 했는데 귀찮아서 올리기는 그렇고..

위의 코드를 참고로 기본틀을 만들고 필요한 것은 적당히 스택플로우를 참고하면 원하는 Wrapper클래스를 만들 수 있을것이다.


나의 경우는 unsigned char*를 NSData로 형변환해야 하는등에 귀찮은 작업이 있었지만 스택플로우의 힘으로 모두 클리어.

생각대로 잘 동작한다.


끝.

Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

XCode로 로 개발중에 C++로 개발된 모듈을 추가해야 할 일이 생겼다.

어차피 Objective-C도 C언어에서부터 나온거라 그냥 추가해주면 될줄 알았지만 당연하게도XCode는  에러를 뱉어내면서 저항을 했다.

나중에 이런작업을 또 할까... 없을거라 생각되지만 혹시나 해서 잊어버리기전에 블로그에 적어놓자.

인터넷을 찾아본 결과 몇가지 설정이 필요하고 XCode에 필요한 규칙이 있었다.


먼저 샘플 cpp 파일을 만들어보자. 파일추가에서 아래와같이 선택하면 간단히 템플릿이 만들어진다.



추가된 파일에 cpp형식으로 샘플코드를 넣어보자.


Sample.h 와 Sample.cpp파일            

 


자..이제 실제로 뷰 콘트롤러에서 불러보자.

참고로 cpp파일을 이용하기 위해서는 ViewController.mm와 같이 확장자를 mm 으로 변경 해 주어야 한다.



Hello 함수가 정상적으로 잘 호출되었다.



그러나.. 실제 프로젝트에 적용하니 또다시 XCode에서 반항하며 알수없는 에러들을 내뱉었다.

인터넷으로 여기저기 알아본 결과 스택플로우에서 해결방법 발견!

http://stackoverflow.com/questions/6913637/xcode-4-2-c0x-libc-cannot-find-iostream


읽어보니 이유는 모르겠지만 설정을 두군데 정도 손으 봐야 한다.

Build Settings에서 C++ Standrad Library 를 libstdc++로 변경 그리고 Compile Sources As 를 Objective-C++로 바꿔준다.



어쨋든 성공은 했으니 좋다.



Posted by 악당잰 트랙백 0 : 댓글 2

댓글을 달아 주세요

  1. addr | edit/del | reply BlogIcon 곱게자란녀석 2015.01.11 17:16 신고

    안녕하세요. 같은 문제에 봉착하였는데.. 전 해결이 안되서.. 여쭤보려고 문의드렸습니다.
    전 c 파일과 cpp 파일을 전부 사용해야 하는 경우인데요.. Apple Mach 0 linker error 를 자꾸 내뱉습니다.
    cpp로 작성된 함수명들에 대해 에러를 내뿜고 있구요.
    댓글엔 그림을 넣을 수 없어 제가 다른곳에 질문글 올렸던 링크도 같이 드립니다...
    http://www.clien.net/cs2/bbs/board.php?bo_table=cm_app&wr_id=12324

    • addr | edit/del BlogIcon 악당잰 2015.01.11 19:07 신고

      도움이 될지는 모르겠으나 제가 아는 한도내에서 답변을 드리자면..

      C, C++로 만들어진 정적 라이브러리를 이용하시나요?
      그렇다면 arm64를 적용하지 않은채 빌드된 라이브러리에선 캡쳐와 같은 에러가 발생한 경험이 있습니다.
      라이브러리를 arm64용으로 빌드해서 달라고 하면 됩니다.

      c, cpp 파일을 직접 프로젝트에 넣어서 사용하신다면 캡쳐에러만 가지고는 알수가 없네요.
      다만, objective-c 에서는 기본적으로 c++은 그냥그대로 사용 못하는걸루 알고 있구요. c의 경우도 구조체 같은 경우 ARC를 먹지 않기 때문에
      결국은 오브젝티브C용으로 랩핑을 해줘야 합니다.

      도움이 되었는지 모르겠네요..

테스트 데이터를 읽어들여 기본값을 셋팅하거나 할때 csv형식의 파일을 사용하게 된다.

그렇지만 윈도우나 맥의경우 각각 캐리지리턴(개행문자)가 다르므로 개행을 구분할 필요가 있는데 한번에 간단히 처리되는 방법이 있다.


XCode상에 프로퍼티에서 파일형식을 확인할 수 있다.




소스는 다음과 같다.


    // 1.ラインフィードバックで行を区別する。

    NSScanner *scanner = [NSScanner scannerWithString:text];

    

    // 改行文字の集合を取得

    NSCharacterSet *chSet = [NSCharacterSet newlineCharacterSet];

    // 一行ずつの読み込み

    NSString *line = nil;

    

    while(![scanner isAtEnd]) {

        // 一行読み込み

        [scanner scanUpToCharactersFromSet:chSet intoString:&line];

        NSLog(@"line = %@", line);

        // カンマ「,」で区切る。

        NSArray *subTmp = [line componentsSeparatedByString:@","];

        

        //TODO:

        NSString *tmp1 = [NSString stringWithString:[subTmp objectAtIndex:0]];

        NSString *tmp2 = [NSString stringWithString:[subTmp objectAtIndex:1]];

        NSString *tmp3 = [NSString stringWithString:[subTmp objectAtIndex:2]];

        

        // 改行文字をスキップする。

        [scanner scanCharactersFromSet:chSet intoString:NULL];

    }


Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

Objective-C에서 텍스트필드에 입력된 입력값을 체크해야 될 경우가 있는데 Web개발시 사용하던 정규표현으로 입력값 체크하는 방법을 발견하여 소개하려한다.



1. RegexKitLite 을 다운로드 

http://regexkit.sourceforge.net/RegexKitLite/

2. RegexKitLite.h , RegexKitLite.m 파일을 프로젝트에 추가 (다운로드 파일 전부 추가할 필요는 없는것 같음.)

3. 프로젝트 파일에 Other Linker Flags에 -licucore 문자열추가

4. 사용할 콘트롤러에 RegexKitLite.h 를 임포트

사용예 )

NSString *strFormat = @"^[0-9a-zA-Z]*$";
       
       NSString *result = [oldpasswd.text stringByMatching:strFormat];
       if (result == nil) {
           [self showAlertWindows:@"確認" withMessage:@"変更前のパスワードは英数字(半額)のみ入力可能です。"];
           return;
       }

이외에도 여러가지 편리한 함수들이 있다.


URL과Email을 추출하는 예

https://kldp.org/node/105673


Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

프로파티의 목록을 취득하려고 하려면 어떻게 해야할까?




출처: http://stackoverflow.com/questions/780897/how-do-i-find-all-the-property-keys-of-a-kvc-compliant-objective-c-object


프로파티 말고도 메소드이름이라던가 취득가능한것 같음. 

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html



Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요