2013년 9월 8일 일요일

sqlite3 사용 방법



+ (void)initDb {
    if (gTheDb == nil )
        [self openDatabase];
}

+ (void)openDatabase
{
    NSString *dir = [DbManager getDbPath];
    NSString *writableDBPath = [dir stringByAppendingPathComponent:kDbName];
    
    //check file
    NSFileManager *fileManager;
    fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:writableDBPath] == NO) {
        
        NSError *error;
        NSString *bundleDBPath = [[[NSBundle mainBundleresourcePathstringByAppendingPathComponent:kDbName];
BOOL success = [fileManager copyItemAtPath:bundleDBPath toPath:writableDBPath error:&error];
        if( !success )
        {
            NSLog(@"fail to create writable database into %@.(error=%@)",writableDBPath, error);
            return;
        }
    }
    
    // Open the database. 
    if (sqlite3_open([writableDBPath UTF8String], &gTheDb) != SQLITE_OK) {
        sqlite3_close(gTheDb);
        NSLog(@"Failed to open database. (%s)"sqlite3_errmsg(gTheDb));
        return;
    }
    NSLog(@"Success to open database. (%@)", writableDBPath);
}

+ (void)closeDatabase
{
    if (gTheDb) {
        sqlite3_close(gTheDb);
    }
}

+ (NSString *)getDbPath {
    NSString *path = [NSString stringWithFormat:@"%@/%@",
                      [Util getCachesPath],
                      KPATH_DB];
    // create directory
    [[NSFileManager defaultManagercreateDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
    return path;
}




//일반적인 쿼리 방법
    NSString *query = @"SELECT * FROM ZMESSAGE";
    NSString *query = [NSString stringWithFormat:@"SELECT * FROM ZTHREAD WHERE Z_PK=\"%@\"",ZTHREAD];
    const char *query_stmt = [query UTF8String];
    sqlite3_stmt *statement=nil;
    if (sqlite3_prepare_v2(theOldDb, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        NSNumber *ZSELECTEDDEFAULTSKIN = nil;
        NSString *ZSELECTEDSKINFILENAME = @"";
        if (sqlite3_step(statement) == SQLITE_ROW) {
            ZSELECTEDDEFAULTSKIN  = [NSNumber numberWithInt: sqlite3_column_int(statement, 4)];
            if( sqlite3_column_text(statement, 9) != NULL)
            ZSELECTEDSKINFILENAME = [NSString stringWithUTF8String:(const char *) sqlite3_column_text(statement, 9)];
        }
    }
    sqlite3_finalize(statement);




// 특수 문자 입력을 위한 처리 방법
query = [NSString stringWithFormat: @"INSERT INTO tbMessage (msg_kind,mt,call_mdn,message,ret,fc,ft,subject,status,read,port_height,land_height,spam,port_emo_rects,land_emo_rects,recipient,is_multirecipient) \
         VALUES (%d,%d,\'%@\',?4,\'%@\',%d,\'%@\',?8,%d,%d,%f,%f,%d,\'%@\',\'%@\',\'%@\',%d)", \
         msgkind,type,callmdn,/*message,*/receiveTime,attachedFileCount, \
         fileType,/*subject,*/status,read,port_height,land_height,isSpam,portEmoRects,landEmoRects,recipient,is_multirecipient];
query_stmt = [query UTF8String];

if (sqlite3_prepare_v2(gTheDb, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
    sqlite3_bind_text(statement, 4, [message cStringUsingEncoding:NSUTF8StringEncoding], -1,
                      SQLITE_TRANSIENT);
    sqlite3_bind_text(statement, 8, [subject cStringUsingEncoding:NSUTF8StringEncoding], -1,
                      SQLITE_TRANSIENT);
    if (sqlite3_step(statement) != SQLITE_DONE)
        NSLog(@"[migration]Fail inserting into tbMessage");
}







브로드 캐스팅 상용 방법





#define kShowLoginActionNotification @"kShowLoginActionNotification"



- (void)viewDidLoad
{
    [super viewDidLoad];


[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showLoginPage:) name:kShowLoginActionNotification object:nil];

}



- (void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self name:kShowLoginActionNotification object:nil];
}



- (void) showLoginPage:(NSNotification *) notification
{
  //실재 기능 구현
}



image Util 기능



//이미지 비율을 유지하면서 최대 가로사이즈보다 작은 이미지 사이즈
+ (CGSize)getScaledImageSize:(UIImage *)image scaledToMaxWidth:(CGFloat)maxWidth
{
    CGFloat oldWidth = image.size.width;
    CGFloat oldHeight = image.size.height;
    
    CGFloat scaleFactor=1;
    
    if (oldWidth > maxWidth) {
        scaleFactor = maxWidth / oldWidth;
    } else {
        //scaleFactor = height / oldHeight;
        return image.size;
    }
    
    CGFloat newHeight = oldHeight * scaleFactor;
    CGFloat newWidth = oldWidth * scaleFactor;
    CGSize newSize = CGSizeMake(newWidth, newHeight);
    return newSize;
}

//이미지 비율을 유지하면서 최대 가로 or 높이보다 작은 이미지 사이즈 생성
+ (UIImage *)getScaledImage:(UIImage *)image scaledToMaxWidth:(CGFloat)width maxHeight:(CGFloat)height {
    CGFloat oldWidth = image.size.width;
    CGFloat oldHeight = image.size.height;
    
    CGFloat scaleFactor=1;
    
    if (oldWidth > width) {
        scaleFactor = width / oldWidth;
    } else if(height){
        scaleFactor = height / oldHeight;
    } else  //oldWidth<width and height==0이면, scale하지 않음.
        return image;
    
    CGFloat newHeight = oldHeight * scaleFactor;
    CGFloat newWidth = oldWidth * scaleFactor;
    
    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
    [image drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}


//JPEG 이미지로 저장
UIImageJPEGRepresentation(scaledImage, 0.5);

//PNG 이미지로 저장
UIImagePNGRepresentation(scaledImage);




//이미지(썸네일) 캐슁 하는 방법

NSMutableDictionary *thumbnailCache_ = nil;


+ (void)initThumbnailCache {
    thumbnailCache_ = [[NSMutableDictionary alloc] initWithCapacity:20];
}


+ (UIImage *)addThumbnailToCache:(NSString *)path {
    if ([thumbnailCache_ count] >= 20) {
        id key = [[thumbnailCache_ allKeys] objectAtIndex:0];
        [thumbnailCache_ removeObjectForKey:key];
    }
    UIImage *image = [UIImage imageWithContentsOfFile:path];
    if (image) {
        [thumbnailCache_ setObject:image forKey:path];
        return image;
    }
    
    return nil;
}


+ (UIImage *)cachedThumbnail:(NSString *)fileName {
    UIImage *image = [thumbnailCache_ objectForKey:fileName];
    if (image == nil) {
        image = [Util addThumbnailToCache:fileName];
        //NSLog(@"load file image (%@)",fileName);
    } else {
        //NSLog(@"load cached image (%@)",fileName);
    }
    
    return image;
}

//실제 사용방법

NSString *imgName = @"실제 이미지 경로(이미지 이름 포함)";


img = [Util cachedThumbnail:imgName];


2013년 9월 3일 화요일

euc_kr로 변환


NSUInteger encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_KR);
const char * eucKRString = [string cStringUsingEncoding:encoding];

Grand Central Dispatch (GCD)


// Doing something on the main thread

dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
dispatch_async(myQueue, ^{
    // Perform long running process

    dispatch_async(dispatch_get_main_queue(), ^{
        // Update the UI

    });
}); 
If you want to run a single independent queued operation and you're not concerned with other concurrent operations, you can use the global concurrent queue:

dispatch_queue_t globalConcurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

euc_kr로 바이트 수 계산

한글은 2바이트,
영어는 1바이트로 계산해서 전체 바이트 계산하는 방법




// 표시기호 '₩' 있는 경우에, length 0으로 계산되는 문제 => length계산을 위해서 다른 한글 문자로 대치함.

NSString *inputString = [myInputBoxView.text stringByReplacingOccurrencesOfString:@"₩" withString:@""];
NSData *bytes = [inputString dataUsingEncoding:0x80000422];
NSLog(@"bytes length = %d",bytes.length);


로그 :
bytes length = 16 바이트

2013년 7월 4일 목요일

NSArray의 특정 값을 이용한 grouping

나이에 따라서 사람들을 그룹핑 하는 예제....




_Peoples = NSDictionary 타입의 Person들의 array

//나이에 따라서 구룹핑 함.
NSArray *groups = [_Peoples valueForKeyPath:@"@distinctUnionOfObjects.age"];
    
//age는 NSNumber *인 이유는 person NSDictionary의 age key에대한 value 타입이 NSNumber * 이기 때문임.
for (NSNumber *age in groups)
{   
   NSArray *filteredArr = [_Peoples filteredArrayUsingPredicate:[NSPredicate  predicateWithFormat:@"age = %@", age]];

NSLog(@"[age=%d] is = %@",[age integerValue], filteredArr);
}

2013년 4월 13일 토요일

객체를 생성하지 않고도 instance method를 호출하게 해주는 instanceMethodForSelector

NSObject를 상속받은 클래스의 인스턴스를 생성하지 않고도 모든 인스턴스 메소드를 호출할 수 있다.
+ (IMP)instanceMethodForSelector:(SEL)aSelector 는 aSelector함수를 구현한 어드레스(함수포인터)를 반환한다.

아래 소스는 NSOjbect의 클래스 메소드 instanceMethodForSelector를 어떻게 사용하는지에 대한 예제이다.

// Utility.h
@interface Utility : NSObject
{
}

+ (void)showLoadingView;



// Utility.m
static UIView *loadingView=nil;
static UIView *loadingContainerView=nil;
static bool isShowActivityIndicator = false;

+ (void)showLoadingView
{
IMP func = [Utility instanceMethodForSelector:@selector(performSelector:withObject:afterDelay:)];
func(self, @selector(performSelector:withObject:afterDelay:), @selector(doShowLoadingView),nil,0);
}

+ (void)doShowLoadingView
{
UIWindow *mainWindow = [[UIApplication sharedApplication].delegate window];

if (loadingView == nil) {

loadingContainerView = [[UIView alloc] initWithFrame:mainWindow.frame];
loadingView = [[UIView alloc] initWithFrame:CGRectMake(mainWindow.center.x-70,mainWindow.center.y-50,140,100)];
loadingView.opaque = NO;
loadingView.backgroundColor = [UIColor darkGrayColor];
loadingView.alpha = 0.7;
loadingView.layer.cornerRadius = 8;
loadingView.layer.masksToBounds = YES;
UIActivityIndicatorView *spinningWheel = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[spinningWheel setCenter:CGPointMake(loadingView.frame.size.width/2,(loadingView.frame.size.height/2)-10.0f)];
[loadingView addSubview:spinningWheel];
[spinningWheel release];
[spinningWheel startAnimating];

UILabel *loadingLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 62, 140, 25)];
[loadingLabel setFont:[UIFont boldSystemFontOfSize:14.0f]];
[loadingLabel setTextAlignment:UITextAlignmentCenter];
[loadingLabel setBackgroundColor:[UIColor clearColor]];
[loadingLabel setTextColor:[UIColor whiteColor]];
loadingLabel.text = @"Loading...";
[loadingView addSubview:loadingLabel];
[loadingLabel release];
[loadingContainerView addSubview:loadingView];
}

if (isShowActivityIndicator == false) {
[mainWindow addSubview:loadingContainerView];
isShowActivityIndicator=true;
}
}

어떤 곳에서도 [Utillity showLoadingView]를 호출하면 activity indicagtor view를 띄운다.
아래 그림은 activity indicator view를 띄운 화면을 캡쳐한 화면이다.






이와 더불어 class method에 대한 함수 포인터를 얻고 싶으면 - (IMP)methodForSelector:(SEL)aSelector 를 사용하면 된다.

숫자를 포함하고있는 NSString을 여러가지 형으로 변환

NSScanner 클래스를 이용해서 NSString을 float, double, hex,int 등의 다른 형으로 변환이 가능하다.

아래 예제는 헥사값을 읽어와서 integer값으로 변환하는 예이다.

NSString *hexaString = @"0x24DA1";
NSScanner* pScanner = [NSScanner scannerWithString: hexaString];
unsigned int iValue;
[pScanner scanHexInt: &iValue];
NSLog(@"iValue=%d",iValue);

결과 값:
iValue = 150945

이와 비슷하게 여러가지 형으로 상호 변환이 가능하다.

NSString이 숫자인지 아닌지 체크

아래 예제는 testString이 숫자만 포함하는지 아니면 숫자가 아닌 문자를 포함하고 있는지를 체크한다.

(BOOL)isDigit:(NSString)testString
{
NSCharacterSet *nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
NSRange nond = [testString rangeOfCharacterFromSet:nonDigits];
if (NSNotFound == nond.location) {
return YES;
} else {
return NO;
}
}

testString = @"12345" 이면 true 이고,
testString = @"12345ABY"이면 false 이다.

NSArray의 모든 Object들에서 같은 메세지를 보내는 방법.

NSArray의 모든 Object들에게 한번에 같은 메세지를 보낼 수 있는데 makeObjectsPerformSelector를 이용하면 된다.
이 함수는 잘 만 이용하면 아주 유용하게 사용할 수 있다.
예를 들어서 ScrollView의 subview들을 한번에 모두 제거한다든가 하는 작업이 가능하다.
단, 조건이 있는데 selector에 들어갈 메세지는 argument가 없는 함수만 가능하다. (명심할 것)

예제1)
UIScrollView의 subview들을 한번에 제거
[[myScrollView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

예제2)
IB에서 collection으로 묶인 UIButton들 한방에 unselect
xx.h

@property (retain, nonatomic) IBOutletCollection(UIButton) NSArray *allButtons;

xx.m

[_allButtons makeObjectsPerformSelector:@selector(setSelected:) withObject:NO];


iOS에서 broadcasting 하는 방법.

iOS의 어느곳에서든지 broadcast 메세지를 보낼 수 있다. 메세지를 보낼때는 이름(유일하게 구분이 되어야 함)을 정의하게되고, 그 broadcast message를 받고 싶은 곳에서는 notification센터에 같은 이름으로 observer 등록하면 받을 수 있다.

아래 예는 sender클래스가 로그아웃 메세지를 broadcasting하고, receiver클래스에서 그 broadcast message를 받아서 처리하는 간단한 예제이다.
broadcasting의 장점은 거미줄 같은 객체간의 상호 의존성을 줄일 수 있다는 것이다. 그렇지만 broadcasting을 남발하게 되면 오히려 프로그램의 복잡성을 키울 수 있다.
따라서, 적절한 곳에 적절히 사용해야 한다.



//sender.m
- (IBAction)touchedLogoutButton:(id)sender {
[[NSNotificationCenter defaultCenter] postNotificationName:UserNotificationHttpRequestLogout object:self];
}





//receiver.m
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doLogout:) name:@"notification_logout" object:nil];
}

- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"notification_logout" object:nil];
[super dealloc];
}

- (void)doLogout:(NSNotification *)notification
{
//로그아웃 처리
}

알아두면 좋은 것들

 CGPointEqualToPoint(CGPoint point1, CGPoint point2)
 : 포인트 point1와 point2가 같으면 TRUE, 다르면 FALSE 값 리턴.


//간단히 Mutable Array 생성하는 방법
NSMutableArray myarr = [@[] mutableCopy];


//간편 설정
CGRect CGRectOne = (CGRect){.origin.x = 1.0f, .origin.y = 1.0f, .size.width = 1.0f, .size.height = 1.0f};
CGRect CGRectOne = { { 0.0f, 0.0f }, { 1.0f, 1.0f } };
CGRect CGRectOne = {
        .origin = { .x = 0.0f, .y = 0.0f },
        .size   = { .width = 1.0f, .height = 1.0f }

    };

// center position
CGPoint centerPosition = (CGPoint){CGRectGetMidX(imageContainerLayer.bounds), CGRectGetMidY(imageContainerLayer.bounds)}



sqlite3 *gTheDb // db

NSInteger lastRowId = sqlite3_last_insert_rowid(gTheDb);
:마지막에 추가된 레코드의 rowid값 리턴



CGRect를 string으로 변환 하는 함수.
NSString rectString = NSStringFromCGRect(buttonRect);
output : rectString = {{75, -1}, {25, 21}}

반대로 string을 CGRect로 변환


CGRect rect = CGRectFromString(rectString);

이외에

NSStringFromCGSize, NSStringFromUIOffset 등의 많은 함수들이 있다. 

UIKit Function Reference를 살펴보면 알 수 있을 것임.

NSDictionary *dict = @{ kNamekey : @"jacobs kim" };   //딕셔너리에 직접 값 입력.


label의 matrix 와 text 정렬


iOS 7 이상에서는  boundingRectWithSize:options:attributes:context:
를 사용할 수 있음.
예제)
CGSize maximumLabelSize = CGSizeMake(_lyricsLabel.frame.size.width, CGFLOAT_MAX);
    
    CGRect expectSize = [_lyricsLabel.text boundingRectWithSize:maximumLabelSize
                                               options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                            attributes:@{NSFontAttributeName:_lyricsLabel.font}
                                               context:nil];
    _lyricsLabel.frame = CGRectMake(_lyricsLabel.frame.origin.x,
                                             _lyricsLabel.frame.origin.y,
                                             _lyricsLabel.frame.size.width,

                                             expectSize.size.height);



NSString의 sizeWithFont:constrainedToSize:lineBreakMode: 메써드를 통해서 text가 그려질 layout metrics를 받아올수 있다.

아래는 그 사용 예제이다:
- (void)alignSingleLineLabels
{
    [_label1 setText:@"첫번째 레이블."];
    [_label2 setText:@"두번째 레이블 입니다.!"];
   
    CGSize _label1_Size = [_label1.text sizeWithFont:_label1.font
                                              constrainedToSize:CGSizeMake(320, 640)
                                                  lineBreakMode:UILineBreakModeWordWrap];
    CGSize _label2_Size = [_label2.text sizeWithFont:_label2.font
                                   constrainedToSize:CGSizeMake(320, 640)
                                       lineBreakMode:UILineBreakModeWordWrap];
   
    [_label1 setFrame:CGRectMake(_label1.frame.origin.x, _label1.frame.origin.y, _label1_Size.width, _label1_Size.height)];
    float _label2_posX = _label1.frame.origin.x + _label1_Size.width;
    [_label2 setFrame:CGRectMake(_label2_posX, _label2.frame.origin.y, _label2_Size.width, _label2_Size.height)];
}

- (void)alignMultipleLineLabels
{
    [_label3 setText:@"첫번째 레이블.\n다은줄입니다."];
    [_label4 setText:@"두번째 레이블.\n다음줄 입니다.\n다은줄 입니다."];
    [_label5 setText:@"세번째 레이블.세번째 레이블.\n다음줄 입니다."];
   
    CGSize _label3_Size = [_label3.text sizeWithFont:_label3.font
                                   constrainedToSize:CGSizeMake(320, 640)
                                       lineBreakMode:UILineBreakModeWordWrap];
    CGSize _label4_Size = [_label4.text sizeWithFont:_label4.font
                                   constrainedToSize:CGSizeMake(320, 640)
                                       lineBreakMode:UILineBreakModeWordWrap];
    CGSize _label5_Size = [_label5.text sizeWithFont:_label5.font
                                   constrainedToSize:CGSizeMake(320, 640)
                                       lineBreakMode:UILineBreakModeWordWrap];
   
    [_label3 setFrame:CGRectMake(_label3.frame.origin.x, _label3.frame.origin.y, _label3_Size.width, _label3_Size.height)];
    float _label4_posX = _label3.frame.origin.x + _label3_Size.width;
    [_label4 setFrame:CGRectMake(_label4_posX, _label4.frame.origin.y, _label4_Size.width, _label4_Size.height)];
   
    float label5_posY = _label3_Size.height > _label4_Size.height?(_label3.frame.origin.y+_label3_Size.height):(_label4.frame.origin.y+_label4_Size.height);
    [_label5 setFrame:CGRectMake(_label5.frame.origin.x, label5_posY, _label5_Size.width, _label5_Size.height)];
}


레이블의 line 갯수를 가져와서 text가 그려질 line의 갯수와 비교하여 뉴라인문자(\n)을 리에블의 text에 append해줌으로써 text를 label의 맨 상단에 그려질 수 있도록 할 수있다.

- (void)alignTopLeft {
    CGSize labelSize = [_label6.text sizeWithFont:_label6.font
                                              constrainedToSize:CGSizeMake(_label6.frame.size.width, _label6.frame.size.height)
                                                  lineBreakMode:_label6.lineBreakMode];
    int lineCount = labelSize.height/_label6.font.lineHeight;
    int maxLineCount = _label6.numberOfLines;
    for (int i=lineCount; i < maxLineCount; i++) {
        _label6.text = [_label6.text stringByAppendingString:@"\n "];
    }
   
}


아래는단말에서 실행된 화면이다.

숫자를 통화로 변경

NSNumberFormatter를 이요하면, 숫자를 통화로 변경할 수 있습니다.

NSString *number = @"숫자";
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSNumber *numberFromString = [NSNumber numberWithInt:[number intValue]];
NSString *balance = [formatter stringFromNumber:numberFromString];
[formatter release];

지역포멧이 대한민국인 경우 변환 결과:
232220    ==> ₩232,220
-10263522   ==>  -₩10,263,522

지역포멧이 미국인 경우 변환 결과:
232220   ==>  $232,220.00
-10263522  ==>  ($10,263,522.00)      *()표기는 음수를 나타냄.

만약 "xxxx원" 이런식으로 보여지기를 원한다면 약간의 추가 작업이 필요합니다.
아래 함수는 그 처리를 하는 함수 입니다:
+ (NSString *)convertFromNumberToCurrency:(NSString *)number
{
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
    NSNumber *numberFromString = [NSNumber numberWithInt:[number intValue]];
    NSString *balance = [formatter stringFromNumber:numberFromString];
    [formatter release];
   
    balance = [balance stringByReplacingOccurrencesOfString:@"(" withString:@"-"];
    balance = [balance stringByReplacingOccurrencesOfString:@")" withString:@""];
   
    NSRange range = [balance rangeOfCharacterFromSet:[NSCharacterSet symbolCharacterSet]];
    while (range.location != NSNotFound) {
        balance = [balance stringByReplacingCharactersInRange:range withString:@""];
        range = [balance rangeOfCharacterFromSet:[NSCharacterSet symbolCharacterSet]];
    }
    balance = [balance stringByAppendingString:@"원"];
    return balance;
}

결과는 지역포멧에 상관없이 다음과 같음:
232220    ==> 232,220원
-10263522   ==>  -10,263,522원

다른 어플 실행 방법

UIApplication:openURL: 함수를 이용해서 어플을 실행할 수 있다.
- (BOOL)openURL:(NSURL *)url
url은 http:, https:, tel:, mailto: ,schemes 등이 가능하다.

<예제>
BOOL r = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlScheme]];
    if (r) {
//어플 실행
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlScheme]];
    } else {
//어플 다운로드
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:downloadURL]];
    }

align Justified( left and rignt ) with UILabel

NSString *text1 = @"Sample text : A his is my weblog in English, German and Korean. If you want to know more about a pizza stone once it’s cooled down.";

NSMutableParagraphStyle *style =  [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setAlignment: kCTJustifiedTextAlignment];

NSAttributedString * subText1 = [[NSAttributedString alloc] initWithString:text1 attributes:@{
                                                NSParagraphStyleAttributeName : style
                                     }];

_myUiTextView.attributedText = subText1;



참조사이트 : http://stackoverflow.com/questions/1301519/justified-alignment-in-uitextview-iphone

day of year 계산


NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"D"];
NSUInteger dayOfYear = [[formatter stringFromDate:[NSDate date]] intValue];
[formatter release];
NSLog(@"오늘은 일년중 %d일 입니다.",dayOfYear);


결과
today = 오늘은 일년중 71일 입니다.

UINavigationController 기반의 어플리케이션 만들기

View base application 프로젝트 생성한후에 application delegate에 다음과 같은 코드만 추가해 줌으로써 간단히 navigationcontroller 기반 어플리케이션으로 변환 된다.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
    UINavigationController* naviController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
    [naviController setNavigationBarHidden:YES];   //sub viewcontroller에서 이부분을 NO로 설정해 주면 뒤로가기가 가능하도록 navigation bar가 보임.
    self.window.rootViewController = naviController;
    [self.window makeKeyAndVisible];
    [self.viewController release];
    return YES;
}