윈플

자신이 만들 앱이 인터넷을 사용한다면, 인터넷이 연결되었는지를 확인하여 사용자에게 알려야합니다. 
그리고 Web Application을 생각 중이시라면, 중간 중간 Loading 부분을 인디게이터로 표현해주어야 하며,
에러에 관련된 처리는 당연한 부분입니다.

그래서 이번엔 인터넷 상태를 확인하고, 인디게이터는 언제 애니메이션을 키고 꺼야 되는지, 그리고 에러 처리는 어떻게 해야하는지 정리해봤습니다.


1. 인터넷 연결 상태 확인하기.

***Reachability

The Reachability sample application demonstrates how to use the SystemConfiguration framework to monitor the network state of an iOS device. In particular, it demonstrates how to know when IP can be routed and when traffic will be routed through a Wireless Wide Area Network (WWAN) interface such as EDGE or 3G.

: 쉽게 말해 'SystemConfiguration' framework 사용하여 인터넷 상태를 알려주는 샘플코드 되시겠습니다.


먼저 이 샘플코드를 활용하여 간단히 네트워크 상태를 체크하는 함수를 만들어봤습니다.

 
#pragma mark Check Network

- (BOOL) connectedToNetwork
{
    /*
     www.apple.com URL을 통해 인터넷 연결 상태를 확인합니다.
     ReachableViaWiFi && ReachableViaWWAN 
     : Wi-fi와 3G 둘다 안된다면 인터넷이 연결되지 않은 상태입니다.
     */
    
	Reachability *r = [Reachability reachabilityWithHostName:@"www.apple.com"];
	NetworkStatus internetStatus = [r currentReachabilityStatus];
	BOOL internet;
    
	if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN)) {
		internet = NO;
	} else {
		internet = YES;
	}
	return internet;
}


+ 물론 위 소스를 사용하기 위해서는
* SystemConfiguration.framework 를 추가하셔야 합니다.
* Reachability.h 와 
Reachability.m 소스가 프로젝트 안에 있어야 합니다.
Reachability.h 를 import 하셔야 합니다.

위 소스를 간단히 살펴보면, 'www.apple.com' 라는 url을 통하여 3G와 Wifi를 구분하지 않고 단순히 인터넷 사용 가능 유무를 검사합니다.
( 사용가능 YES, 사용불가 NO )


3G 와 Wifi 를 구분하려면?
: 당연히 &&로 묶여있는 if문을 나누어 주면 됩니다. ^_^;


2. UIWebView.

: <UIWebViewDelegate> 를 통해 아래 4개의 함수를 사용하여 에러처리 및 UIActivityIndicatorView를 처리할 예정입니다.


- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
: Delegate가 연결된 WebView안에서 요청이 있는 경우, 이 함수를 통해 어떤 url로 링크를 타는지 알 수 있습니다.
+ 예를들어 웹뷰를 통해 무언가를 검색했을 때, 검색어를 가져온다던지 기타 등등

UIWebViewNavigationType{
    UIWebViewNavigationTypeLinkClicked,            // 링크 클릭 : 0
    UIWebViewNavigationTypeFormSubmitted,      // 양식 제출 : 1
    UIWebViewNavigationTypeBackForward,         // 뒤로, 앞으로 : 2
    UIWebViewNavigationTypeReload,                  // 새로고침 :3
    UIWebViewNavigationTypeFormResubmitted,   // 양식 다시 제출 :4
    UIWebViewNavigationTypeOther                     //  기타 :5
};

- (void)webViewDidStartLoad:(UIWebView *)webView;
- (void)webViewDidFinishLoad:(UIWebView
*)webView;
: 위 두함수는 웹뷰가 시작되고, 끝났을 때 호출됩니다. 이 함수를 이용해서 
UIActivityIndicatorView 애니메이션을 언제 시작하 끝낼지 생각할 필요가 없게됬습니다.


- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
: 딱 봐도 이 함수가 error가 발생할 때 호출되는 함수입니다. 
- error.description : error 코드 포함하여 error에 대한 설명이 포함되어있습니다.
- error.code : error 코드를 알 수 있습니다. ( 아래 더보기를 통해 종류를 보시기 바랍니다. )

+ error code = -1009 인터넷이 연결안되어 있을 때 나는 코드입니다.


"Timeout" 처리하기

: 인터넷은 연결되어 있는 상태지만, 신호가 약하거나 잘못된 Wi-Fi를 물고 있는 경우 생길 수 있는 Timeout 처리에 관한 부분입니다.

( 1 ) WebView가 시작하는  webViewDidStartLoad에서 NSTimer를 지정한 시간에 함수를 호출하도록 설정합니다.
( 2 ) 
webViewDidFinishLoad에서는 NSTimer를 invalidate를 시켜줍니다. ( 정상적으로 종료되었다는 의미이므로 )


- (void)timeoutWebview
{
    NSLog(@"Timeout 20sec");
    UIAlertView *timeAlertView = [[UIAlertView alloc]initWithTitle:@"Timeout" message:@"20sec" delegate:nil cancelButtonTitle:@"cancel" otherButtonTitles:nil, nil];
    [timeAlertView show];
    // Timeout Check 20초 이상 걸린다면, 화면에 뿌려주기
}

- (void)webViewDidStartLoad:(UIWebView *)webView
{
    NSLog(@"StartLoad");
    
    // Timer시작
    timer = [NSTimer scheduledTimerWithTimeInterval:20.0 target:self selector:@selector(timeoutWebview) userInfo:nil repeats:NO];
    
    
    // Start Loading
    loadingIndicator.hidden = NO;
    [loadingIndicator startAnimating];
}



- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSLog(@"FinishLoad");
    
    // 정상적으로 웹이 됬다면 Timer 종료
    [timer invalidate];
    
    // Stop Loading
    [loadingIndicator stopAnimating];
    loadingIndicator.hidden = YES;
}




3. NSURLRequest

NSURL *_url = [NSURL URLWithString:URL];
NSURLRequest *request = [NSURLRequest requestWithURL:_url];

기본적으로 위와 같이 사용하지만, 

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URL]                                                                                                                      cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                                                       timeoutInterval:60.0];

이와 같이 NSMutableURLRequest를 사용해서 timeout 을 설정하는 방식을 더 많이 사용합니다.

마찬가지로 <NSURLConnectionDelegate> 를 사용해서

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
: 연결 오류가 났을 때 호출 되며 이곳에서 에러 처리를 해주시면 됩니다.
+ UIWebView에서의 Error와 코드는 같습니다.

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
: 연결 성공했을 때
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
: 연결 한 후에 데이터를 받을 때
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
: 데이터를 다 받았을 때 

- 인디게이터 부분은 연결에 성공하여서 데이터를 다 받을때까지로 할지, 아니면 연결 이후에 데이터를 받기 시작한 후 다 받을때 까지로 할지 정하시면 됩니다.


+ 추가적으로 response를 통해 Status Code를 통해 확인하는 방법입니다.
단순하게 200(Success) , 400(Bad Request)로 구분할 수 있습니다.

 
NSURLResponse *response;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
NSLog(@"return statecode : %d",[(NSHTTPURLResponse *)response statusCode]);




지금까지 앱에서 인터넷을 사용할 때, 기본적으로 처리해야 하는 부분을 봤습니다.만 아래 링크를 통해서
좀 더 알아보시기 바랍니다.


내가 만든 앱 문제는 없을까?
웹(Web) .vs 앱(APP) 어떤 것을 선택할 것인가?
- 모바일 앱 기획시 고려사항
- 애플의 하이브리드앱 제재는 정당한가?



'제2외국어 > iOS' 카테고리의 다른 글

[iOS] Network check and error handling  (0) 2013.08.21
[iOS]custom Cell - Edit 사용 시 밀리지 않는 문제  (0) 2013.06.20
[iOS]통화하기  (0) 2013.05.29
[iOS]Font 관련하여..  (0) 2013.04.26
[iOS] Multitasking : Location  (0) 2013.01.29
[iOS] Multitasking : Audio  (0) 2013.01.24

Comment +0

상황 : ViewController 위에 TableView를 올리고, 거기에 Custom Cell 을 사용할 때!!


- 기본 UITableViewCell 을 사용하는 경우, Edit 모드시 자동으로 정렬을 해줍니다. 
  하지만, Custom Cell을 사용하는 경우에 Edit 모드시 아래 이미지같이 자동으로 맞춰 주지 않습니다.


< 문제 >



1. 처음엔 edit 버튼을 눌렀을 때 tableview를 옆으로 이동 시켜주면 되겠구나 하고 TableView를 옮겼더니,
전체가 옯겨졌습니다;;
FAILED


       [UIView animateWithDuration:0.5 animations:^{

                [TableView setFrame:CGRectMake(0, 88, 320, 367)];
        }];
        [TableView setEditing:NO animated:YES];

       

 




2. 검색결과 AutoresizingMask 또는 clipSubview 로 해결하라고해서 해봤는데.. 이 부분은 잘 모르겠습니다.
FAILED


 customCell.m에서 initWithStyle ~ 부분에서

 // AutoresizingMask , contentView에 올리기
titleLabel.autoresizingMask  UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:titleLabel];





3. 또 다른 검색결과 awakeFromNib 를 통해 구현
SUCCESS

: custom Cell 의 .m 부분에서 awakeFromNib를 집어 넣습니다. 그리고 아래 소스를 집어넣고 끝.


- (void)awakeFromNib

{
       [super awakeFromNib];
       for(NSLayoutConstraint *cellConstraint in self.constraints){
       [self removeConstraint:cellConstraint];
       id firstItem = cellConstraint.firstItem == self ? self.contentView : cellConstraint.firstItem;
       id seccondItem = cellConstraint.secondItem == self ? self.contentView : cellConstraint.secondItem;

       NSLayoutConstraint* contentViewConstraint =
       [NSLayoutConstraint constraintWithItem:firstItem
                                                           attribute:cellConstraint.firstAttribute
                                                         relatedBy:cellConstraint.relation
                                                               toItem:seccondItem
                                                            attribute:cellConstraint.secondAttribute                                                                              
                                                           multiplier:cellConstraint.multiplier
                                                            constant:cellConstraint.constant];

        [self.contentView addConstraint:contentViewConstraint];

    }

}



< 성공 >





'제2외국어 > iOS' 카테고리의 다른 글

[iOS] Network check and error handling  (0) 2013.08.21
[iOS]custom Cell - Edit 사용 시 밀리지 않는 문제  (0) 2013.06.20
[iOS]통화하기  (0) 2013.05.29
[iOS]Font 관련하여..  (0) 2013.04.26
[iOS] Multitasking : Location  (0) 2013.01.29
[iOS] Multitasking : Audio  (0) 2013.01.24

Comment +0

*코드로 통화하기

1. 기본 통화하기
: 자동으로 기본 통화 어플을 통해 통화를 시작합니다.

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel:010-xxxx-xxxx"]];


2. 통화 후 앱으로 다시 돌아오기.
: 다만 팝업창으로 통화를 걸지 안걸지 한번 물어봅니다.

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"telprompt:010-xxxx-xxxx"]];


                   

                            < 1번의 경우 바로 통화 시작 >                    < 2번의 경우 팝업창으로 통해 한번 물어보고 통화 >                              


Tip.
: 전화번호는 010-1234-1234 || 01012341234 구분하지 않고 사용이 가능합니다.




'제2외국어 > iOS' 카테고리의 다른 글

[iOS] Network check and error handling  (0) 2013.08.21
[iOS]custom Cell - Edit 사용 시 밀리지 않는 문제  (0) 2013.06.20
[iOS]통화하기  (0) 2013.05.29
[iOS]Font 관련하여..  (0) 2013.04.26
[iOS] Multitasking : Location  (0) 2013.01.29
[iOS] Multitasking : Audio  (0) 2013.01.24

Comment +0

기본적으로 iOS에서는 자체 폰트를 사용합니다.
( 이걸 System Font라고 부릅니다. )

그리고 추가적으로 기본적으로 제공하는 Custom Font 도 있습니다.
( Arial, Helvetica 등 )


Interface builder 에서 기본으로 제공하는 Font 이외의 Font 를 적용하려면 약간의 추가 작업이 필요합니다.

-- 이 부분은 인터넷에서 " iOS font " 라고 검색하시면 쉽게 찾으실 수 있습니다. 


1.  plist에Fonts provided by application 추가 한 후 item에 Font 이름 적기

( Font 이름은 .ttf, .otf 확장자까지 다 적어주셔야 합니다 )


2.  Project , Resources 에다가 Font 파일 ( .otf, .ttf ) 놓기


3. 코드로 적용

Textfield.font = [UIFont fontWithName:@"NanumGothicExtraBold" size:45];

( Font 확장자를 제외한 이름만 적어주기, 현재 나눔고딕입니다. )



otf 보단 ttf 를 사용하는게 메모리에 도움이 된다고 합니다. 이유는 모름



<실제 적용된 화면>


기본 폰트에서는 저렇게 *# 이 중간에 있지 않습니다.
(즉, 나눔 고딕 폰트가 적용되었다는걸 알 수 있습니다. )


(Arial) TEST : 1234*#


PS . 사실 font 적용하는 과정에서 문제점이 생겨서 그 문제점을 해결하는 차원에서 포스팅을 하였는데, 그 문제점이 제 실수에서 비롯된 작은 문제여서, 그냥 흔한 포스팅으로 마무리 됩니다. (__)






'제2외국어 > iOS' 카테고리의 다른 글

[iOS]custom Cell - Edit 사용 시 밀리지 않는 문제  (0) 2013.06.20
[iOS]통화하기  (0) 2013.05.29
[iOS]Font 관련하여..  (0) 2013.04.26
[iOS] Multitasking : Location  (0) 2013.01.29
[iOS] Multitasking : Audio  (0) 2013.01.24
About : iOS Multitasking  (0) 2013.01.21

Comment +0

다음은 iOS Multitasking 중에서 Location입니다.


-- 프로젝트 설정

먼저 CoreLocation.framework 추가하기



그리고 Audio와 마찬가지로 .plist 설정




자 이제 소스부분입니다.

백그라운드에서 동작하게 하기 위해 AppDelegate.h / .m 에서 작업을 시작합니다.


1. import, 변수 선언

 #import <CoreLocation/CoreLocation.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate>

@property (nonatomic, strong) CLLocationManager *locationManager;



2. init & 설정

혹시나 AppDelegate에 있는 함수들이 정확히 무슨 기능을 하시는지 모르시는 분은 더보기를 통해 확인하시기 바랍니다.


먼저 앱시작하면 제일 먼저 들어오는 함수에서 locationManager를 초기화 및 정확도를 설정합니다.
그리고 startUpdating 을 시작합니다.
( Location은 위치이며, Heading은 방향을 알수있습니다. )


- (BOOL)application:(UIApplication *)application
   didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

   /* 
    locationManager 생성
    delegate 연결
    정확도에 대한 설정 
   */

     locationManager = [[CLLocationManager alloc]init];
    [locationManager setDelegate:self];
    [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];

    // AutoPause API 비활성화
    // 기본적으로 활성화(YES) 되어있음
    [locationManager setPausesLocationUpdatesAutomatically:NO]; 
     

    // LocationManager update
    [
locationManager startUpdatingLocation];
    [locationManager startUpdatingHeading];

     return YES;

}

** AutoPause API ??

- AutoPause API 활성화
- 움직이지 않을 때는 업데이트를 하지 않음
- CLLocationManager 는 기본적으로 AutoPause API가 활성화 상태
- AutoPause API를 사용하지 않으려면 pausesLocationUpdatesAutomatically 를 통해 설정
( YES : 활서 | NO : 비활성 )
 <단점>
- AutoPause API를 비활성화를 한다면 확실히 Requset가 많이 발생하고 그만큼 베터리 소모량이 큽니다


다음으로 Background 진입 시에 위치가 변하는 것을 모니터링 하는 함수를 호출합니다.

 

- (void)applicationDidEnterBackground:(UIApplication *)application
{

    // 앱이 Background 진입 호출
    NSLog(@"Background");    

    // locationManager 위치가 변하는 것을 모니터링 시작하는 함수
    [locationManager startMonitoringSignificantLocationChanges];   

}

마지막으로 앱이 종료되면, 그리고 실행 중일 때는 locationManager를 멈추는 작업을 해줍시다.

 
- (void)applicationDidBecomeActive:(UIApplication *)application
{

    // Active 상태로   호출
    NSLog(@"Become");

    [locationManager stopMonitoringSignificantLocationChanges];
}


- (void)applicationWillTerminate:(UIApplication *)application
{

    // 앱이 종료될 호출
    // locationManager 멈춤
    NSLog(@"terminate");
    [locationManager stopMonitoringSignificantLocationChanges];

}
 




3. (중요) Location Delegate 부분입니다. 

didUpdateLocations Delegate 함수를 통해, 현재 상태가 백그라운드 상태에 있을 경우에만 업데이트 되고 Log를 찍게
했습니다.
( 백그라운드 상태가 아니라면 실행안됩니다. )

#pragma mark Locationmanager delegate

- (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{

    BOOL isInBackground = NO;    

    if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
   {
        isInBackground = YES; 
        NSLog(@"update location : %f, %f",manager.location.coordinate.latitude,
                                                             manager.location.coordinate.longitude);

    }    

} 



4. 실행결과

이 앱에게 위치정보를 허락하는 부분, 당연히 OK

앱 실행시킨 화면입니다.
당연히 암것도 없고, 아무것도 안 찍힙니다.


여기서 홈버튼을 누르게 되면, Become 상태에서 Background상태로 변하면서 Log가 찍히는걸 알 수 있습니다.
다시 앱으로 들어온다면 다시 Become상태로 되면서 업데이트 종료  :)




PS.

시뮬레이터에서는 끊임없이 작동이 되지만, 실제로 디바이스에서는 이상하게 2~3번 정도 로그가 찍히다가 멈춥니다. 
( 실제로는 멈춘게 아닙니다. )
iOS에서는 기본적으로 사용자가 활동하지 않을때! 즉 움직이지 않을때는 위치 업데이트를 중지합니다. 


** 간단하게 웹디비에 연결해서 실제 밥먹으로 돌아다니면서 테스트 결과, 주기적으로 업데이트를 합니다. 

( 위치가 거의 변하지 않더라도, 적어도 30분에 한번씩은 업데이트를 꼭 합니다! )


< 참고 문서 >
CLLocationManager Class Reference

'제2외국어 > iOS' 카테고리의 다른 글

[iOS]통화하기  (0) 2013.05.29
[iOS]Font 관련하여..  (0) 2013.04.26
[iOS] Multitasking : Location  (0) 2013.01.29
[iOS] Multitasking : Audio  (0) 2013.01.24
About : iOS Multitasking  (0) 2013.01.21
[ios] 서버에 이미지만 보낼 때와 이미지 + 정보를 보낼 때  (0) 2013.01.04

Comment +0

 iOS Multitasking 중에서도 기본이라 할 수 있는 Audio 입니다.


[프로젝트 만들기 과정은 ..... 생략]



-- 프로젝트 설정

먼저 Audio를 사용하기 위한 Framework 추가하기



 iOS Multitasking 중 Audio 모드를 설정.
: plist ▶ Required background modes ▶ App plays audio
( 보시면 아시다시피 전 포스팅에서 소개한 7가지의 모드라는걸 아실 수 있습니다. :D )





이 밑에는 AVAudioPlayer 를 이용해 소리를 키는 부분입니다.
( 아시는 분은 필요없는 부분입니다. )


1.  import시키기 , 변수 선언

#import <AVFoundation/AVFoundation.h>

@property (nonatomic, strong) AVAudioPlayer *audioPlayer;


2. init & url 설정

// 먼저 test.mp3 라는 파일의 URL 설정
// 
AVAudioPlayer init

NSURL *audioFileLocationURL = [[NSBundle mainBundle]URLForResource:@"test" withExtension:@"mp3"];
audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:audioFileLocationURL error:nil];

// option  무한 반복 : -1
[audioPlayer setNumberOfLoops:-1];

//  Category property 설정
[[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance]setActive:YES error:nil];



  Values for the category property 


 -  AVAudioSessionCategoryAmbient : 동시 재생 가능, 배경음악 같은 경우

 -  AVAudioSessionCategorySoloAmbient : 동시 재생 불가

 -  AVAudioSessionCategoryPlayback : 일반적인 노래같은 경우

 -  AVAudioSessionCategoryRecord : 녹음만 하는 경우

 -  AVAudioSessionCategoryPlayAndRecord : 동시에 원할 때 ( 노래를 켜고, 녹음도 하고 )

 -  AVAudioSessionCategoryAudioProcessing : 코덱 및 신호 처리를 하는 동안은 재생 및 오디오를 사용하지 않을 때


 원문은 xCode에서 command 버튼을 누른상태에서 카테고리를 설정하면 보실 수 있습니다.


- OPTION
: 소리 크기 조절
ex) [audioPlayer setVolume:[sender value]];   // 값은 0.0 ~ 1.0 입니다.


3. 음악 켜기/끄기

[audioPlayer play];
[audioPlater pause];



실행 및 테스트 해본 화면입니다.

Interface 추가 및 연결하는 부분도 생략합니다.




** 참고로 시뮬레이터로 테스트할 경우 백그라운드로 잘 돌아가는지 확인이 안 되더군요.
    꼭 Device를 통해서 해보시기 바랍니다. 



Comment +0

iOS쪽을 하다보면 생각보다 제약사항이 많습니다.

1. 내부 DB를 건들 수 없다.
2. 다른 앱은 건들 수 없다.
3. Multitasking이 제한적이다.
etc..

내부DB와 다른 앱은 아마 탈옥을 하지 않는 이상 건들 수 없고, 갑작스럽게 가능하는 방향으로 바뀌지는 않을 것 같습니다.
그래서 먼저 Multitasking 쪽을 한번 살펴보기로 하겠습니다.

App State Changes

: 먼저 App State에 대해서 알아야 됩니다. 상태의 종류와 그 종류에 해당하는 부분을 확인하려면 꼭 필요합니다.

 State

 Description 

 Not running

 
 앱이 실행되지 않았거나, 시스템에 의해 종료된 상태입니다.

 Inactive


 앱이 foreground에서
 실행되었지만, 이벤트는 수신하지 않는 상태입니다. 
 이 상태에서도 어느 정도의 코드는 실행이 가능하지만 일정 시간이 되면 실행되지 않습니다.
 ( iOS 앱이 상태 변환을 할 때 머무는 단계입니다. )

 Active


 앱이 실행되고 있는 상태입니다. 가장 일반적인 상태입니다.

 Background


 앱 실행 중에 홈 버튼을 눌렀을 때로 Active에서 Suspended를 변하기 전에 머무는 상태입니다.

 이 잠깐(10분인가??)은 사용자에 의한 이벤트는 받지 못 하지만 소스코드는 수행이 가능합니다. 
 물론 추가적인 수행이 필요한 경우 시간을 늘어날 수 있습니다.
 ( Background가  Multitasking 을 위해 건드려야 할 부분입니다.  )

 Suspended


 앱이 중단된 상태입니다. 메모리는 있지만 코드는 수행되지 않는 상태입니다.

 메모리 부족이 발생할 때 시스템은 이 상태의 앱을 죽일 수 있습니다.


:  App State의 변화를 확인할 수 있는 곳은 AppDelegate( .h, .m) 입니다. 

Monitoring App State Changes




가장 중요한 부분입니다. Multitasking, 즉 Background에서 사용할 수 있도록 Apple에서 허용한 부분입니다.

1. Audio
: 가장 잘 알고있는 기능입니다. 기본 기능이기도 하죠. 오디오나 비디오 플레이어(소리에 한해) Background 에서도 돌아갑니다.

2. Location
: 언제부터 가능했는지 몰라도, 최근에 추가된 옵션인것 같습니다. 저희나라에는 아직 없지만 TomTom 이라는 업체에서 해외 중요 도시의 네비게이션을 팔고 있습니다.



어플리케이션

3. Voip
: 대표적인 어플로 Skype가 있습니다. Skype를 사용하신분들은 아실겁니다. 통화중에 홈버튼을 통해 나가더라도 아래 이미지와 같이 기본 어플과는 색깔(빨강)만 다른 상태로 표시되는 걸 확인하실 수 있습니다.


4. Newsstand-content
: 신문이나 가판대 앱을 정기적으로 다운받습니다.



5. External-accessory
External Accessory framework를 통해 External-accessory(외부 악세사리)와 정기적으로 작동합니다

6. Bluetooth-central
Core Bluetooth framework 를 통해 Bluetooth Accessory에 정기적인 일정에 따라 작동합니다. 

7. Bluetooth-peripheral
Core Bluetooth framework 를 통해 주변 모드에서 Bluetooth Accessory와 통신합니다.



PS.

1번의 경우 너무 흔해서 이미지도 구하지 않았고, 5,6,7 번 항목은 Apple를 통해서 iPhone 관련 물품을 판매하는 경우 모두 포함됩니다. Bluetooth 이어폰, 측정기 등이 있습니다.


솔직히 모든 항목을 다루어 보고 싶지만 1,2번을 제외한 나머지 부분은 원하는 분야도 아니거니와 솔직히 하기도 어렵습니다. 



참고 사이트

Misconceptions About iOS Multitasking
App States and Multitasking

파헤치기 #5. iOS App Programming Guide (5) App States and Multitasking <1> 

Comment +0

iPhone 에서 사진을 찍은 후, 이미지를 어디론가로 보낼 때.
사진 그 자체로만 보낸다면 그리 어렵지 않습니다.


* 서버에 이미지만 보낼 때

예를들어 

1. 찍은 이미지 정보 
: 밑에는 AVCaptureStillImageOutput 를 활용해 사진을 찍은게 아니라 현재 보이는 화면을 캡쳐한 이미지입니다.
( 차이점은 사진 찍은 것보다 데이터가 적다고 생각하시면 됩니다. 찍은게 아니라 캡쳐니깐요!! )

NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];

2. body 에 저장

[body appendData: imageData];

3. 보내기

[request setHTTPBody : body];

끝입니다. 이미 데이터 형식이니 body 에다가 붙여서 body 를 보내기만 하면 됩니다.
물론 받는 쪽에서도 처리해야할 게 있습니다.

---- 참고 ( NSData 를 UIImage 로 Convert ) ---
: UIImage *image = [[UIImage alloc] initWithData : imageData];
==> imageData 라는 NSData 형식의 자료를 UIImage 형식으로 바꾸어서 image 에 저장.



* 서버에 정보 + 이미지 보낼 때

단!! 단순히 이미지만 보내는게 아니라 이미지에 관한 정보를 더해서
[ 이미지에 관한 or 그냥 정보 + 이미지 데이터 ] 를 보낸다면 방식을 다르게 해주어야 합니다.

지금부터 하는 방식은 가장 단순하고 무식한, 손쉬운 방법입니다.

목표 : '이미지 이름 + 캡쳐한 날짜 + 이미지' 를 보낸다.
방법 : 이미지, 즉 NSData를 NSString 형식으로 변환해서 통짜 NSString 으로 보낸다.

중요!!
- 이미지, 즉 NSData 를 NSString 로 변환할 때 base64로 encoding 을 해주셔야 합니다.
- 헌데, 예전에 사용했던 [NSData encodeBase64ForData]; 가 언제부터인지 사라졌습니다. ㅠ
- 그래서 base64 encoding 함수를 직접 구하셔야 됩니다. (아래는 base64 함수입니다. ) 




원본 사이트 

- (NSString*)base64forData:(NSData*)theData {

    const uint8_t* input = (const uint8_t*)[theData bytes];
    NSInteger length = [theData length];
    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    uint8_t* output = (uint8_t*)data.mutableBytes;
    NSInteger i;

    for (i=0; i < length; i += 3) {

        NSInteger value = 0;

        NSInteger j;

        for (j = i; j < (i + 3); j++) {
            value <<= 8;
            if (j < length) {
              value |= (0xFF & input[j]);
            }

        }
        NSInteger theIndex = (i / 3) * 4;

        output[theIndex + 0] =                    table[(value >> 18) & 0x3F];
        output[theIndex + 1] =                    table[(value >> 12) & 0x3F];
        output[theIndex + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        output[theIndex + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';

    }
    
    return
 [[NSString allocinitWithData:data encoding:NSASCIIStringEncoding];






ex) 방식은 xml, json 형식이 있지만 현재 사용한 방법은 xml 형식입니다.

위의 base64 함수를 사용해서 
NSString *imgString = [self base64forData:imageData]; 

NSString *postStr = [[NSString alloc]init];                                                                     // 어딘가에 보낼 문자열 생성
postStr = [postStr stringByAppendingFormat:@"<Test>"];
postStr = [postStr stringByAppendingFormat:@"<imgName>%@</imgName >",subject];    // 이미지 이름
postStr = [postStr stringByAppendingFormat:@"<imgData>%@</imgData >"imgString];      // 이미지 데이터
postStr = [postStr stringByAppendingFormat:@"</Test>"];


이렇게 만든 xml 형식의 문자를 body 에 그냥 넣으시면 안되고요!! 문자니 NSUTF8StringEncoding 로 encoding 하신후에~

[body appendData:[[NSString stringWithString : postStr]dataUsingEncoding:NSUTF8StringEncoding]];

body 를 셋팅 후 보내시면 됩니다.





ps. base64 함수는 많아도 너~무 많으니 더 좋은 소스를 찾아보시거나, 직접 라이브러리와 하셔서 사용하셔도 무관합니다.

아래는 마르스 블로그에서 가져온 소스형식의 파일입니다. 

NSDataAdditions.h

NSDataAdditions.m



Comment +0


가끔씩 현재 위치 및 시간을 알아야 할 때가 있습니다.
그럴때를 위해서 가장 간단한 것만 찾아서 간단하게 적어보았습니다.


** 현재 위치 알아내기

1. CoreLocation Framework 추가하기


CLLocationManager 를 사용하기 위해서 "CoreLocationFramework 를 추가해주어야 합니다.


2. 헤더파일 설정 .h

#import <CoreLocation/CoreLocation.h>
@interface PhotoViewController : UIViewController
<CLLocationManagerDelegate
{
    CLLocationManager *locationManager;
}
@property (nonatomic, strong) CLLocationManager *locationManager;



3. 소스파일 설정 .m

locationManager = [[CLLocationManager alloc]init];                 // 초기화
locationManager.delegate = self;                                            // delegate 연결
locationManager.desiredAccuracy = kCLLocationAccuracyBest;  // 정확도 최고로 설정

[locationManager startUpdatingLocation];                                // 현재 위치 업데이
NSLog(@"%f",locationManager.location.coordinate.latitude);      // latitude     NSLog(@"%f",locationManager.location.coordinate.longitude);    // longitude 


< 주의사항 >
위치 정보를 가져오기 위해서는 해당 앱을 처음 실행시켰을 때 이 앱이 위치 정보를 가져가는걸 허락할지 물어봅니다.
그렇기 때문에 허락하지 않거나, viewDidLoad 에 위 소스를 그대로 적으시면 허락하기도 전에 로그를 찍기 때문에 제대로 된 
값을 가져오지 못 합니다.
아 그리고 시뮬레이터로 할 경우에는 애플 본사의 위치만 찍힙니다. 참고하세요.



** 현재 시간 알아내기

인터넷을 찾아보시면 NSDate 와 NSCalendar 를 활용해서 찾는 방법 등 여러가지 방법이 있습니다. 
그 중 가장 간단하게 알 수 있는 방법을 소개해드리겠습니다.

-- 참고한 사이트입니다.  :훨씬 다양한 방법들이 소개되어있습니다.

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy"];
int year = [[dateFormatter stringFromDate:[NSDate date]] intValue];    
[dateFormatter setDateFormat:@"MM"];
int month = [[dateFormatter stringFromDate:[NSDate date]] intValue];
[dateFormatter setDateFormat:@"dd"];
int day = [[dateFormatter stringFromDate:[NSDate date]] intValue];
[dateFormatter setDateFormat:@"HH"];
int hour = [[dateFormatter stringFromDate:[NSDate date]] intValue];
[dateFormatter setDateFormat:@"mm"];
int minute = [[dateFormatter stringFromDate:[NSDate date]] intValue];
[dateFormatter setDateFormat:@"ss"];
int second = [[dateFormatter stringFromDate:[NSDate date]] intValue];

NSLog
(@"%d-%d-%d-%d-%d-%d",year,month,day,hour,minute,second);

<초간단!!!>
: 위 형식처럼 자를수도 있고, 아니면 아래와 같이 한번에 표현도 가능합니다.

[dateFormatter setDateFormat:@"yyyy-MM-dd-HH-mm-ss"];
NSString *nowDate = [dateFormatter stringFromDate:[NSDate date]];
NSLog(@"%@",nowDate);


: 끝입니다. 주석도 달 필요없이 NSDateFormatter 를 이용해 DateFormat 를 이용해 분류해주는 작업이 다 입니다.


**Result


nowDate 라는 어플에 위치 정보를 허락하는지 물어보는 화면입니다.



실제 로그 입니다. 현재시간과 (시뮬레이터이기 때문에)애플의 위치가 찍혔습니다.





Comment +0

Apple Push Notification service 맛보기.

< 필수 >
: 애플 개발자 (개인 or 기업) 계정 보유.

< 맛보기 환경 및 툴>
: Mac OS X 10.7.5 ( iMac 27 ) , xCode4.5, 터미널

<순서>
1. iOS Provisioning Portal 에서 App IDs 생성



2. App IDs 에서 Configure App ID 를 통해 APNs 인증서 만들기 -> 다운
: 상업용이 아니라 개발용(테스트 목적이기에) 으로 Configure
( 이 때 .csr 파일을 만들어야 되는데... 누구나 알꺼라고 생각하고 생략하겠습니다. )



3. Provisioning 생성 ( 방금 만든 App IDs와 연결 ) -> 다운


4. xCode를 통해 프로젝트 생성 ( App IDs 에서 적었던 Bundle Identifier 와 똑같이 입력 )


5. 생성한 프로젝트의 AppDelegate.m 에 구현
    5-1. APNs 서비스 허용하게 만들기
    : 가끔씩 순서대로 따라해도, 푸쉬를 허락하겠습니까? 라는 메시지가 안 뜰때가 있습니다.
      이 때에는 다시 Provisioning 을 지운후 다시 차근히 해보시는 법이 답입니다.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // Override point for customization after application launch.
        // Let the device know we want to receive push notifications
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];    

            return YES;
        }

: 허락할 경우 설정 -> 알림 에 보시면 이렇게 방금 만든 Test 앱이 있습니다.


    5-2. Device Token 받기
    : Device Token 은 서버에서 해당 Device 로 메시지를 보낼 때 반드시 필요하다.
    ( 실제 구현시에는 이 Token을 서버로 꼭! 보내주어야 한다. )
    <성공 시>
        - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:                  (NSData*)deviceToken
        {
            NSLog(@"My token is: %@", deviceToken);
          }

    <실패 시>
    
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
    {
        NSLog(@"Failed to get token, error: %@", error);    
    }

    5-3. Push 메시지 받았을 때의 기능 구현
     : 밑에 함수는 간단히 메시지를 받았을 때 알림창으로 받은 메시지를 보여주는 함수입니다.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    NSString *string = [NSString stringWithFormat:@"%@", userInfo];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
                                                    message:string delegate:nil
                                          cancelButtonTitle:@"OK"   otherButtonTitles:nil];
    [alert show]; 
}


6. TEST 해보기
: 이 부분은 맥이라면 아주 쉽게 스윽지나갈 수 있습니다. ( 아래 참고 사이트에 있는 내용이지만 보기쉽게만 적었습니다. )




[Pem 파일 만들기]
    1. APNs 서비스를 위해 만들었던 CSR 파일
    2. (개발용) APNs 인증서를 클릭하여 키체인에 등록한 후 개인키와 함깨 내보내기를 통해 .p12파일 생성(비밀번호도 같이)
    ( 편하게 key.p12 로 명칭 )
    3. Provisioning 파일 , aps_developer.cer
    ( 편하게 cert.cer 로 명칭 )

[순서]
1. 3번의 aps_developer.cer 파일을 .pem으로 바꾸기

 openssl x590 -in cert.cer -inform der -out cert.pem 

2. 2번의 .p12 파일을 .pem으로 바꾸기

 openssl pkcs -out key.pem -in key.p12
 그리고 비밀번호 생성

3. 순서 1-2번의 .pem 파일들을 하나의 .pem으로 바꾸기

 cat cert.pem key.pem > ck.pem

simplepush.php

- php 파일입니다.

4. 그리고 첨부파일에 있는 .php 파일을 약간 수정, 위에 만들었던 ck.pem 파일과 한곳에 넣은 후!

// Put your device token here (without spaces):
$deviceToken = '0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78';
 
// Put your private key's passphrase here:
$passphrase = 'password';
 
// Put your alert message here: 
$message = 'My first push notification!'; 

개발서버는 gateway.sandbox.push.apple.com:2195

실제서버는 gateway.push.apple.com:2195


5. 두 파일이 있는 곳으로 cd 로 이동 후에 php 실행

 php push.php
 Connected to APNS
 Message successfully delivered
라고 떳다면 폰을 확인.


Push 메시지가 온걸 확인할 수 있습니다.





<참고 사이트>
: APNs 테스트 부터, 서버를 이용해 메시지 보내는 부분까지 자세히 나와있다. (Best)
Tutorial: iOS Push Notification Services For Beginners
Apple Push Notification Services Tutorial: Part 1/2
Apple Push Notification Services Tutorial: Part 2/2


ps. 그냥 참고 사이트에 있는 내용 그대로입니다.
특별한거 없습니다. 그냥 보기 편하게 정리한 정도입니다. 
더 자세한부분을 원하시면 튜토리얼 part 1/2부분을 정독하시면 됩니다.


Comment +2

제목은 거창하지만, 실제론 보기 좋은 소스를 위한 조금(?)은 귀찮은 코딩 방법이라고 명명한다.
( 내가 하는건 귀찮지만, 해놓으면 남이 내 소스를 볼 때 편하다. 물론 반대의 경우에도 같다 ) 


1. 주석

// 한줄

/*  단락    */



2. #pragma mark
: 이것(?)을 처음 사용해본 시기는 아무 생각 없이 책에 있는 예제를 따라하며 공부하던 시절, 당연히 써야하는 줄 알았는데...
  역시 알아보니 ( 쓰기 귀찮아서 꼭 써야되나하고 찾아봤다 : 동기 불순 ) 그냥 마크 기능이였다.  
++ 더 쉽게 책갈피 기능이라고 생각하면 편하다.

1. 저 화살표 부분을 클릭하면 



2. 아래 화면 처럼 나오는데, 또 화살표 표시로 구분한 게 제가 #pragma mark 를 사용한 부분입니다. 


보통 기본 View , IBAction 함수, delegate 등 보기 편하기 묶어놓고 
#pragma mark - ~  이런식으로 사용하면 됩니다.
( 참고로 mark 를 쓰지 않으면 표시되지 않습니다. 그리고 mark 만 할 경우 줄만 그어집니다. )

ex ) #pragma mark Test   : 한줄 그어지고 그 밑에 Test 라고 표시
       #pragma mark          : 글씨 없이 한줄만 표시
       #pragma Test           : 아무런 표시도 안됨



3. Snippet 
: 1. (작은) 정보 2. (대화, 음악 등의) 한 토막 :: 출처 - 네이버 영어사전 

그냥 쉽게 "자동 완성 기능" 이라고 명명합시다.

ex)


if ( i == 0 ) {
    // use    
} 


if ( i == 0 )
{
      // use
}

if ( i == 0 ) { // use } 

 if ( i == 0 ) {
  // use        }

가장 많이 쓰이는 if 문에도 여러 방법으로 쓰듯이 자신에 맞는 아니면 팀에 맞게 사용할 수 있게 일종의 스타일을 설정가능.


<< 사용법 >>


1. xCode 오른쪽 아래쪽을 보시면 다음과 같은 창이 보입니다.



2. Code Snippet Library -> User 로 가면 아무것도 없습니다. 
( 설정해 놓은게 있다면 있습니다. )

                                                         



3. 추가하시는 방법은... 일단은 아무 글씨나 쓴다음에 끌어다 놓으면 아래 창이 생깁니다.

Title : Snippet 이름
Summary : Snippet 설명
Completion Shortcut : 호출하기 위한 단축이름 같은 겁니다.
Completion Scopes : 여기에서 함수로 지정할 지, 문자로 지정할 지 선택하셔야 됩니다. 

< 처음은 기존의 if 문 Snippet 이고 두번째는 제가 만든 ifmy 라는 Snippet 입니다 >


  


만들다보니 그냥 적으면 저렇게 회색창으로 되지 않습니다.
비밀은 바로  <# 문장 #> , <# #>안에 문장을 넣으면 됩니다. 


아래는 결과입니다.
** ifmy 라는 제가 만든 Snippet가 생겼습니다.



< 참고사이트 >

Snippet 에 대한 참고 사이트 : 맥부기 카페의 글 




주석기본이고, #pragma mark 의 경우 습관이 생기면 편하다. Snippet 의 경우 자신이 많이 쓰이는 걸 하나씩 추가해 놓다보면 확실히 보기 좋다. 
하지만 Snippet 의 경우에는 자신만 편할 수도 있다. 


ps. 하지만 난 혼자하니깐 Snippet도 써야지 아무리 생각해도 자동으로 완성되는 if 문의 경우에는

if ( 조건 )
{
    // value 
}

이게 아니면 안된다. 내 눈에 전자파가 흘러넘치기 전까진 안되!


Comment +0

** xCode 4.5 for iOS 6.0 달라진 점을 쓰고 보니 스토리보드에 대해 다 적지 않은 것 같아 추가해봅니다.


1. Collection View

: C# 및 ASP.NET, Java 등을 해보신 분이라면 한마디로 표현해서 "Grid View"라고 표현하겠습니다.
  위에 속하지 않으신 분들을 위해서는( 물론 Objective-C는 기본입니다. ) "Table View" 와 비교하여 설명하겠습니다.

Table View 가 Cell들을 리스트 형식으로 가지고 있다면, Collection View는 Cell을 바둑판 형식으로 가지고 있다고 표현하겠습니다.
( ex :  Android 에서는 앱을 보여주는 형식 - 리스트 방식 / 바둑판 방식
iOS 에서는 이번에 App Store에서  업데이트 항목 : Table View / 추천 항목 : Collection View )

Essential function
: 아래 함수는 Collection View를 사용하기 위한 꼭 써야되는 함수인데, 잘 보시면 Table View를 사용할 때 쓰이는 함수와 비슷합니다.

1. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
// collection view의 cell의 갯수를 지정하는 함수
2. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
// 각 cell이 만들어 질때 실행되는 함수



 



    • Collection View Controller
    • Collection View
    • Collection View Cell
    • Collection Reusable View
      : (?) 내용을 살펴보면, Collection View에서 스크룰시에 cell들이 삭제되는 대신 재사용성을 위하여 사용(성능up) 한다고 하는데
        그냥 Table View의  header / footer 같이 사용되는 것 같습니다. 

 - ps : 이 부분에 대하여는 좀 더 공부가 필요합니다.


Reference ]
- Doc 및 참고 : https://developer.apple.com [링크]
- 강좌
        *  (기초) 연금술사 님이 작성하신 : http://cafe.naver.com/mcbugi/236330 
        *  (Custom) TSDev 님이 작성하신 : http://cafe.naver.com/mcbugi/237546  
        *  
Beginning UICollectionView In iOS 6: Part 1/2
        *  
Beginning UICollectionView In iOS 6: Part 2/2






2. Container View 



2-1. Prediction


< in Story Board >


                     

< in Simulator >

View Controller가 아닌 Container View Controller 소스에서 Hidden 이라는 버튼을 눌렀을 때 self.view 를 Hidden 시킨 화면
예상과 다르게 View Controller 자체에서 Container 부분이 아예 사라졌다.
( 단순히 Modal View 개념처럼 사용될 줄 알았었다.... )


2-1. Real

: Container View 는 일종의 Child View개념으로 뷰 컨트롤러 위에 또 다른 컨트롤러를 올릴 수 있게 해주는 개념.
  응용가능 한 범위는 더욱 많아 졌고, 최근에 고민했었던 View Controller 위에 static Table View를 사용하는 문제도
  Container View 를 사용하면 쉽게 해결이 가능하다.
 ( 문제점은 아직까진 모르겠다. 속도라던지, 속도라던지... )


간단히 적용시켠 본 Ex)


< in Story Board >


***  단순히 Container에 View Controller 만 연결시키는게 아니라, Table View Controller 도 물론 연결할 수 있다.



< in Simulator >






3. Summary summary

  • 이제 Grid View 방식을 구현 or API 를 가져와서 사용할 필요가 없다.
  • Collection View 내에서 Custom 이 아니라 Flow 방식을 사용하면 일일이 정렬을 할 필욘 없다. 
  • Container View 는 View Controller 의 자식 Controller 라고 생각하자.
  • View Controller 위에 또 다른 자식 Controller 를 여러개 올릴 수 있다.
  • Container 는 단순위 View 위에 올려져 있는게 아니라, 그 부분을 대체하고 있다.

 


'제2외국어 > iOS' 카테고리의 다른 글

APNs 맛 보기.  (2) 2012.11.15
강남스타일? 코딩스타일!  (0) 2012.11.06
xCode 4.5 for iOS 6.0 달라진 점(2)  (0) 2012.10.04
xCode 4.5 for iOS 6.0 달라진 점(1)  (6) 2012.09.24
[iOS]UINavigationController에서 데이터 넘길 때  (0) 2012.09.14
Naming is important!!!  (1) 2012.09.11

Comment +0

ah... 중간에 작성한 자료가 사라지는 바람에 다시 적게되는 ㅜ


 iOS 6.0이 정식으로 출시되고, 그에 따라 xCode도 4.5로 업데이트!!
기존의 경고도 없던 임시 프로젝트에서 경고들이 속속히 발생하게 되었다...

그래서 써보는 xCode 4.5에서 바뀌거나 추가된 것들






1. Deprecated :  더 이상 지원하지 않는 것들...

- modalViewController: Deprecated in iOS 6.0

automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers: Deprecated in iOS 6.0

dismissModalViewControllerAnimated: Deprecated in iOS 6.0

-  presentModalViewController:animated: Deprecated in iOS 6.0

shouldAutorotateToInterfaceOrientation: Deprecated in iOS 6.0

viewDidUnload: Deprecated in iOS 6.0

viewWillUnload: Deprecated in iOS 6.0


viewDidUnload, viewWillUnload 를 보면, 이제 개발자에게 메모리 관련된 것을 신경쓰지말라고 하는 것 처럼 보이며
modalView관련해서도 3가지 함수가 사라졌다. ( 편해진건지는 아직 모르겠다. )

내 프로젝트 중에서는 modal에 관련된 것 중 [self dismissModalViewControllerAnimated:YES]; 함수가 제일 많았는데
( 경고가 0->11로 11번이나 이 부분에서 경고가 떻다;; )


( 화살표 부분의 함수로 대체하면 된다. )

[self dismissModalViewControllerAnimated:YES] 를 [self dismissViewControllerAnimated:YES completion:nil] 로
대체하여 사용하면 해결된다.
- 단!! dismissViewControllerAnimated 이 경우 iOS 5.0이상부터 지원하니 그 이하 버전을 지원하는 경우 다른 방법을...




2. Changes in StoryBoard : 스토리보드에서 바뀐 점

: 가장 눈에 띄는건 이제는 단 2개 뿐이지만 iOS 에서도 파편화(?)가 생겼는데, 3.5-inch 와 4-inch  입니다.
( 물론 3.5를 그대로 써도 4-inch 화면에서 자동으로 젤 위와 아래에 검정화면이 생기면서 화면이 늘어나진 않습니다. )


( Retina (4-inch) 이 부분이 추가된 걸 알 수 있다. )


                -

( 화살표를 누르면 3.5 -> 4.0 인치 화면으로 바뀐다. iPhone5에 맞는 화면 )



    


Exit

스토리보드에서 처음 보이는게 또 보이는데 Exit 라는 겁니다.
기본 segue에 의한 순차적 화면전환을 벗어나게 해준다는 거라는데....
아직 확실치가 않습니다;;

ex) 기존 segue( modal 및 push/pop )에 의한 화면전환의 경우
순차적으로 1->2->3->4 이렇게 진행되었다면,

1->3, 2->4 이렇게 각각의 컨트롤러가 자신의 출구(혹은 입구)를 
가지게되어 어디든지 갈 수 있다는 것 같습니다.




dismissModalViewControllerAnimated , presentModalViewController:animated
이 두개의 함수가 사라진 이유가 있는 것 같습니다!








3. Map : Google -> Apple

: MKMapView, 즉 기본 mapView가 더 이상 구글 맵을 사용하지 않습니다. Apple Map을 사용합니다. 
  Google의 맵 서비스를 따라잡기 위한 노력이 많이 보이는건 사실이지만, 그 만큼 부족한 점도 수도없이 많습니다.

장점
- 위치 정보 검색 속도  > Google 운전 경로
- UI 디자인
- 3D (신기함 정도?)

단점
- 미국을 제외한 다른 나라의 경우 정보 미흡 
( 단적으로 우리 나라에서 지하철 표시도 되어 있지 않다!!! )
- 3D 가 아주 호러물 수준이다. 
( 구글에서 Apple Map을 치면 이상한 3D 맵 사진을 볼 수 있다 ㅡㅡ )

단점이 너무 나도 많기 때문에... 더 이상 기존의 맵뷰를 그대로 사용하면 욕을 엄청 먹을 가능성이 큽니다, 아니 확실합니다.

즉, 구글 API, 네이버 API 등을 사용.... 귀찮아지게 됬습니다.

Google Map API 사용하기
: 어떻게 보면 편법일지도 모르지만, Webview에 Google Map에 연결하여 Javascript를 통해 사용하는 방법입니다.
( iOS에서 Google Maps Javascript V3 API 실행하기 )





이렇게 개발자를 많이! 귀찮게 하는 업데이트는 오랜만에 보는 것 같습니다.
( 물론 업데이트는 무조건 개발자를 귀찮게 합니다. 공부 + 적용 )

이 밖에도 아래 문서를 통해 더욱 자세한 또는 제가 적지 않은 부분을 보실 수 있으실 겁니다.
잘못된 부분은 댓글로.. 더 좋은 정보가 있으시면 물론 댓글로 추가해주시면 감사합니다.


[참고 문서]
1. Xcode Release Notes
2. What's New in iOS
3. Xcode Organizer - Documentation

Comment +6

  • 오랜만에 왔네요~_~
    좋은 글 고맙습니다 ㅎㅎ

  • yagom 2012.10.10 18:28

    ㅎㅎㅎ 진짜 덧글 어디다 달아야 하는지 한참 찾았어요~ㅎㅎ
    건강히 잘 다녀왔습니다!ㅎㅎ

  • 안녕하세요, 글에 잠깐 언급하신 "iOS에서 Google Maps Javascript V3 API 실행하기" (http://blog.sphinfo.com/?p=208)를 작성한 team SPH입니다 :) 좋은 글에 저희 글 소개해주셔서 정말 감사합니다. iOS기반 개발에 참고할 자료가 많은 좋은 블로그를 운영하구 계시네요. 앞으로도 Google Maps API 기반 개발 이야기를 꾸준히 올릴 예정입니다. 종종 들러주세요 :D

  • 송건 2013.01.28 18:16

    구글느님을 통해 들어왔는데 덕분에 좋은 정보 잘 배워갑니다. 감사합니다.


1. 네비게이션바 뒤로가기 버튼에...
: 네비게이션컨트롤러를 이용할 때 뒤로가기 버튼이 자동으로 구성되는데, 이 경우에는 뒤로가기 버튼을 눌렀을 때 
    (1) 원하는 메소드 호출
    (2) 커스텀 이미지
이 두가지를 하기가 어렵다.
(1)의 임시방편으로 viewDidDisappear 함수를 이용해서 확인할 수도 있지만, 이 방법은 뒤로가기 뿐만 아니라 다른 페이지로
넘어가는 경우에도 발생하기에 정확하게 문제를 해결할 수 있다고 볼 수 없다.


해결책

: 커스텀으로 버튼을 만들어준다음 액션을 연결해 주거나, 이미지를 설정한다.

해당 viewDidLoad에서 
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"뒤로" style:UIBarButtonItemStyleBordered target:self action:@selector(goToBeforePage)];

self.navigationItem.leftBarButtonItem = backButtonItem;


하지만 위 방법으로는 UIBarButtonItem 형식이라, 만약에 네비게이션아이템의 형식을 원한다면..

[self.navigationItem.leftBarButtonItem setAction:@selector(goToBeforePage)];
이렇게 생성된 버튼에 @selector 만 연결시켜주면 된다.


이미지를 덮어 쒸우려면

[self.navigationItem.leftBarButtonItem setImage:[UIImage imageNamed:@"test.png"]];

이런식으로!




2. 네비게이션바가 연결된 뷰에 데이터를 넘길 때...


( - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 사용할 때 )

보통 뷰에서 뷰 이동간 데이터를 전달할 때, - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 를 사용
그러나 네비게이션컨트롤러가 연결된 뷰의 경우 문제가 되는데...


 

문제 없음

문제 발생


[원인]

문제 발생하는 이유는 destinationViewController가 다음 뷰로 인식은 되는데 실제로는 NavigationController에서 검사를 하기 때문에 생기는 오류이다.

빌드할 떄는 문제가 되진 않지만 실제 실행시 : ~unrecognized selector sent to instance 라는 메시지를 볼 수 있을 것이다.

해결책

: 네비게이션컨트롤러를 destinationViewController에 연결시킨 다음, 다음 뷰컨트롤러를 네비게이션컨트롤러의 
topViewController로 지정, 그리고 데이터를 넘기면 된다.


UINavigationController *nc = segue.destinationViewController;
nextViewController *vc = (nextViewController *)[nc topViewController];

[vc setTitle : @"test"];




Comment +0


부제 : UI 만 수정했는데 프로그램이 죽진 않지만 검정 화면만 나오는 경우....


나의 경우 예제 소스를 보고 코딩 스타일을 배우는 경우가 많아서, IBOutlet 을 사용하는 경우

1. 헤더에 @property 로 생성

@property (nonatomic, strong) IBOutlet UILabel *iLabel;

2. .m 에서 synyhesize 로 구성을 맞추준 다음

@synyhesize iLabel; 

3. 마지막으로 인터페이스 빌드 or 스토리 보드 에서 직접 연결을 해주는 방법을 주로 사용했습니다.


헌데 부제와 마찬가지로... 단순히 UI 에 뷰만 추가했을 뿐인데 갑자기 검정 화면만 나오면서 멘붕....


아..

프로그램이 죽지는 않지만.. 위와 같이 검정 화면이 나오는 것!!

모든 기능을 다 구현한 뒤에.. 단순히 로딩 화면만 추가하기 위해 뷰하나 생성했을 뿐인데 이렇게 되었다.


@property (nonatomic, strong) IBOutlet UIView *loadView;

문제점은 로딩화면이라고 표현하기 위해 loadView 라는 변수명을 사용했기 때문에 생기는 문제였다.

loadView 는 로딩 되었을 때 사용되는 뷰로 이미 만들어져 있었기 때문에...
( 실제로 위처럼 loadView 라고 선언하지 않더라도 self.loadView 가 존재한다. )



"사소한 것 같지만 중요한 네이밍."
너무 흔할것 같은, 어쩌면 당연한 변수명은 피하는게 상책이다.




'제2외국어 > iOS' 카테고리의 다른 글

xCode 4.5 for iOS 6.0 달라진 점(1)  (6) 2012.09.24
[iOS]UINavigationController에서 데이터 넘길 때  (0) 2012.09.14
Naming is important!!!  (1) 2012.09.11
[iOS]탈옥 여부 확인하기...  (0) 2012.08.08
WWDC2012에 대한 기대  (0) 2012.06.08
[Customize] 4. UIAlertView  (0) 2012.04.24

Comment +1






탈옥하게 되면 깔리게되는 내부 파일을 검사하는 방법과 포트를 검사하는 방법 2가지 방법이 있다고 합니다.



1. 디렉토리/파일 존재 여부 검사

    /Applications/Cydia.app

    /Applications/RockApp.app

    /Applications/Icy.app

    /usr/sbin/sshd

    /usr/bin/sshd

    /usr/libexec/sftp-server

    /Applications/WinterBoard.app

    /Applications/SBSettings.app

    /Applications/MxTube.app

    /Applications/IntelliScreen.app

    /Library/MobileSubstrate/DynamicLibraries/Veency.plist

    /Applications/FakeCarrier.app

    /Library/MobileSubstrate/DynamicLibraries/LiveClock.plist

    /private/var/lib/apt

    /Applications/blackra1n.app

    /private/var/stash

    /private/var/mobile/Library/SBSettings/Themes

    /System/Library/LaunchDaemons/com.ikey.bbot.plist

    /System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist

    /private/var/tmp/cydia.log

    /private/var/lib/cydia

 

샘플 Code        '/Applications/Cydia.app'




// 탈옥 체크
UIAlertView *alter_ok = [[UIAlertView alloc]initWithTitle:@"Confirm" message:@"This is not Jailbreak phone"                                                    delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];

UIAlertView *alter_error = [[UIAlertView alloc]initWithTitle:@"Confirm" message:@"This is Jailbreak phone"                                                        delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];

    NSString *filePath = @"/Applications/Cydia.app";

    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){

        // 탈옥했음!
        NSLog(@"Cydia Existed. JailBroken #2");
        [alter_error show];

    }else{
        NSLog(@"Normal");
        [alter_ok show];
    }




2. 포트검사 : 21번, 22번, 23번


소켓 프로그래밍 써야될듯? 더 간단한 방법을 찾아봐야겠다.

'제2외국어 > iOS' 카테고리의 다른 글

[iOS]UINavigationController에서 데이터 넘길 때  (0) 2012.09.14
Naming is important!!!  (1) 2012.09.11
[iOS]탈옥 여부 확인하기...  (0) 2012.08.08
WWDC2012에 대한 기대  (0) 2012.06.08
[Customize] 4. UIAlertView  (0) 2012.04.24
[Customize] 3. Tabbar  (2) 2012.04.13

Comment +0



2008년 2달

2009년 1달

2010년 8일

2011년 10시간

그리고 2012년 2시 이 시간은 각 행사 입장권을 판매하기 시작하고 매진된 시간입니다.

이대로라면... 2013년은 1시간안에 판매될지도 모르겠는데요?

하지만 이렇게 매년 관심을 모으는 것도 내년에는 어떻게 될지 아무도 모릅니다.


사람은 어떤 부분에 감동을 받게되면, 그 부분에 대해 좀 더 오래 기억한다고 합니다.
( 그리고 기대치도 높아집니다. )

iPod부터 시작되어 iPhone, iPad 그리고 iTV 까지 감동을 이어나가고 있지만.. ( iTV 는 약간 애매함 )

잡스가 없는 Apple이 사람들의 기대치를 어떻게 만족시킬지 궁금합니다.
( 또는 잡스가 없기에 어떻게 달라질지.. )





이번 WWDC2012이 바로 내일이면 열리는데요..

관심사였던 iOS 6.0, iPhone5, iTV 중에서 iOS 6.0은 확실히 발표되는걸로 나왔지만 나머지는 소문은 무성한데
확실치는 않습니다.


이번에 공개될 iOS 6





1. 3D Map ( vs Google )

: Google 과의 Map 전쟁을 선포하였는데요
 ( 그 이유는 지금까지는 iOS에서도 사용자들이 google map 을 사용하엿고, Apple에서는 그에 대해 사용료를 지급하였습니다. 
이 사용료 부분이 꽤 컸었고, Apple 입장에서는 핵심기능 중 하나인데 경쟁업체(?) 소프트웨어를 사용하기 싫은 부분도 있을 꺼라
생각됩니다. )

   하지만 지금까지 사용해왔던 google map과 경쟁하는건 마찬가지기에 3D 기능을 추가한 것 같습니다. 
   선택해서 사용하는건 결국 사용자의 몫이지만, 잘 만들어야지 선택을 받겠지요.





2. with Facebook?

: 이번 iOS는 Facebook을 내장한다는 소문이 있습니다. 
  지금까지는 어플로써 사용해왔는데 이 부분에서 동기화 부분이나 여러가지 문제점이 많았다고 합니다.
  Facebook을 내장하면서 좀 더 다양한 서비스를 iOS가 제공할 수 있을거라 생각됩니다.



3. Siri

: Apple의 핵심기능 중 하나인 Siri는 공개된 이후 생각보다 라인업이 없습니다.
 ( iPhone4s 외에는 적용되지 않았고, 그 이유로는 여러 언어에 대한 대책과 아직 문제점이 많다는 설이 많습니다. )
 New iPad 에서도 Dictionary 부분에서 잠깐 Siri의 일부분을 사용하긴 하지만 이번 iOS6을 업데이트 하면서
 적용될지 관심사입니다.





+@ 

: 이 외에 Mac OS 인 Mountain lion 과 연동, 최적화 및 안정화가 진행될 것 같지만 이런 것은 당연시되는 부분이라
 크게 관심을 끌진 못 할것 같습니다.



iPhone5 에 대해서는 말이 많지만..  확실한건 내일 보면 안다는 것입니다.
사람들이 보내는 관심만큼 Apple에서 어떠한 감동을 안겨줄지 기대됩니다.



'제2외국어 > iOS' 카테고리의 다른 글

Naming is important!!!  (1) 2012.09.11
[iOS]탈옥 여부 확인하기...  (0) 2012.08.08
WWDC2012에 대한 기대  (0) 2012.06.08
[Customize] 4. UIAlertView  (0) 2012.04.24
[Customize] 3. Tabbar  (2) 2012.04.13
[Customize] 2. Navigation Item  (1) 2012.04.12

Comment +0

흔히 경고창으로 사용되는 UIAlertView는 자주는 안 쓰이지만, 사용할 때를 대비해서 커스텀해보도록 하겠습니다.



먼저, UIAlertView 사용법부터 보겠습니다.

UIAlertView *nomalAlert = [[UIAlertView alloc]initWithTitle:@"공지사항" message:@"기본 경고창입니다." delegate:self cancelButtonTitle:@"확인" otherButtonTitles:@"취소", nil];

[nomalAlert show];


initWithTitle : (문자열) 타이틀이 들어갑니다

message : (문자열) 안에 들어가는 내용을 쓰시면 됩니다.

delegate : 기본적으로 self로 연결해줍니다. ( Textfield 등 다른 delegate도 연결가능합니다. )

cancelButtonTitle : 눌렀을 때, 자동으로 AlertView가 없어집니다. 보통 "확인" 버튼으로 사용됩니다.

otherButtonTitles : "확인"버튼 이외의 버튼을 추가적으로 넣을 수 있습니다.

아, 그리고 반드시 show함수를 호출해야 화면에 표시됩니다.


+@ 각 버튼에 대한 이벤트는 <UIAlterDelegate>를 통해 
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 를 통해 제어할 수 있습니다.

ex) if( buttonIndex == 0) // 첫번째 버튼 이벤트
       else if( buttonIndex == 1) // 두번째 버튼 이벤트

[결과화면]


자 그럼 UIAlterView를 커스텀하기 위해서 xCode에서 Command+n으로 소스를 하나 만듭시다.
이름은 원하시는 대로, 전 customAlert라고 만들었습니다.

기본적으로 NSObject Class를 상속받고 있지만 이걸 UIAlertView로 바꾸어 줍시다.

// UIAlertView 상속

@interface CustomAlertView : UIAlertView


UIAlertView를 하나의 모양으로 정해놓는 방법
- 첫번째 방법의 경우 실질적으로 화면에 표시되는 UIAlertView의 show함수만 재정의 하는 방법으로 가능하며

// Custom하는데 필요한 함수들 Overriding
-(void)show
{

    [super show];

    for (UIView* view in self.subviews) {

        if ([view isKindOfClass:[UIImageView class]]) {  // SubView UIImageView이면 -> 바탕

            UIImage *bg = [UIImage imageNamed:@"bg.png"];

            ((UIImageView*)view).image = [bg resizableImageWithCapInsets:UIEdgeInsetsMake(50,10,10,10)];

        }

        else if ([view isKindOfClass:[UIButton class]]) { // Button type 이면 

            [(UIButton*)view setBackgroundImage:[UIImage imageNamed:@"buttonBG.png"] forState:UIControlStateNormal];

        }

        else if ([view isKindOfClass:[UILabel class]]) {  // UILabel이면.

            ((UILabel*)view).shadowColor = [UIColor blackColor];

        }

    }


}


이 경우에는 우리가 만든 customAlert를 통해 선언 후에 기본 AlertView와 똑같이 사용해도 바뀜.


-- 결과 --

CustomAlertView *alert = [[CustomAlertView alloc]initWithTitle:@"공지사항" message:@"\n커스텀 경고창입니다." delegate:self cancelButtonTitle:@"확인" otherButtonTitles:@"취소", nil];

[alert show];





[참고]

배경으로 쓰인 이미지 입니다.


버튼 배경으로 쓰인 이미지 입니다.





'제2외국어 > iOS' 카테고리의 다른 글

[iOS]탈옥 여부 확인하기...  (0) 2012.08.08
WWDC2012에 대한 기대  (0) 2012.06.08
[Customize] 4. UIAlertView  (0) 2012.04.24
[Customize] 3. Tabbar  (2) 2012.04.13
[Customize] 2. Navigation Item  (1) 2012.04.12
[Customize] 1. Navigation Bar  (0) 2012.04.10

Comment +0

이번에는 Tabbar를 커스텀해보도록 하겠습니다.

Tabbar 의 경우에는 디자이너와 상의를 잘 했을 경우(즉 이미지 규격에 맞는 경우!!) 
아주 쉽게 커스텀이 가능하지만,
항상 예외는 있고, 이미지는 너무 다양하기 마련입니다.

- 결국은 코드로 고쳐할 부분이 분명 존재합니다.



먼저 Tabbed Application 으로 프로젝트 생성

: CustomTabbar 라는 이름으로 만들었습니다.



- 처음 실행 시킨 화면입니다. -

이미지를 살펴보시면 first.png 와 first@2x.png 파일이 있는데 그냥 first라고 이름만 쓰시면 
에뮬레이터가 알아서 사이즈에 맞게 변환해줍니다.



예제소스를 살펴보시면 이미지 이름만 바꾸어주면 되는거 아니야? 라고 생각하실 수 있는데
맞습니다. 바로 이경우가 이미지의 규격(사이즈)를 잘 맞춘 경우입니다.

그렇다면 다른 케이스(이미지 크기가 다 다른 경우) 보시다시피 사이즈가 다른 두 개의 앵그리버드 이미지를 탭바에 넣어보시면  (스토리보드에서 그냥 집어넣어버렸습니다.)





 









 < ---- 이미지를 보시면
첫번째는 아예 나오지를 않았고

두번째도 정확한 모양이 아닙니다.




- 이미지 규격에 맞지 않은 경우 스토리보드 상에서 Image Inset을 통해 값을 변경해도 이미지의 전체모습을 나타낼 수가 없습니다.


Tab Bar Controller 의 첫번째 뷰의 .m파일에서 viewDidLoad함수에 소스를 추가합니다.

// 각 이미지 설정

UIImage *selectedImage0 = [UIImage imageNamed:@"anger.png"];

UIImage *selectedImage1 = [UIImage imageNamed:@"anger2.png"];

    

// tabBar에 현재 연결되어 있는 tabBar 연결

UITabBar *tabBar = self.tabBarController.tabBar;

// tabBar 아이템으로 각 각 연결 ( 아이템이 없는데 추가된다면 에러 )

UITabBarItem *item0 = [tabBar.items objectAtIndex:0];

UITabBarItem *item1 = [tabBar.items objectAtIndex:1];


// 각 아이템에 이미지 연결

[item0 setFinishedSelectedImage:selectedImage0 withFinishedUnselectedImage:selectedImage0];

[item1 setFinishedSelectedImage:selectedImage1 withFinishedUnselectedImage:selectedImage1];













 <----- 결과 화면

이미지가 제대로 나왔지만 크기를
벗어나 버렸습니다....
자 다시 ImageInsets를 고쳐봅시다!!!





[item0 setImageInsets:(UIEdgeInsetsMake(40, 40, 40, 40))];

[item1 setImageInsets:(UIEdgeInsetsMake(15, 15, 15, 15))];


아이템에 이미지 연결하기 전에 위 두줄의 코드만 추가해보시면!!


짜잔! 원하는 모양이 비슷하게 나왔습니다.




여기에 배경을 넣고 싶다면, tabBar의 배경만 설정해주시면 됩니다.
이렇게.. [tabBar setBackgroundImage:[UIImage imageNamed:@"NaviBG.png"]];



 


이런 배경도 크기가 넘어버려서
뭔가 꺼림직합니다...


tabBar의 Bounds를 조절해봅시다.
[tabBar setBounds:CGRectMake(0032060)];

-- 원래 Tabbar의 사이즈는 320,49 입니다. --





탭바의 Bounds를 조절해서 크기를 맞추어봤지만 

탭바의 크기가 위 아래로 넓혀지면서 글씨가 약간 짤렸네요



음...

음...

음...




안되겠네요 사람불러야겠습니다. 




결론 : 이미지 규격은 중요합니다.




'제2외국어 > iOS' 카테고리의 다른 글

WWDC2012에 대한 기대  (0) 2012.06.08
[Customize] 4. UIAlertView  (0) 2012.04.24
[Customize] 3. Tabbar  (2) 2012.04.13
[Customize] 2. Navigation Item  (1) 2012.04.12
[Customize] 1. Navigation Bar  (0) 2012.04.10
[UIView] 애니메이션효과 주기  (5) 2012.04.05

Comment +2

  • ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ아엌ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
    결론에서 빵터져버렸네요 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
    이런 커스터마이징 포스팅 정말 유용한 것 같습니다 ㅎㅎㅎ
    기초도 중요하지만, 응용도 중요하니...!!
    좋은 포스팅 고맙습니다 ㅎㅎ

Navigation Bar에 이어서 Navigation Item 을 커스텀 해보도록 하겠습니다.

더 쉽습니다.

Navigation Item 역시 3개의 스타일과 기본적으로 제공하는 버튼 모양이 있고,
색깔도 지정가능합니다.

Style : 1. Plain    2. Bordered    3. Done
그리고 기본적으로 제공하는 버튼아이콘 ( 직접 살펴보세요 )이 있습니다.

기본적으로 네비게이션 바에는 Bar Button Item 을 집어넣습니다.

- 기본 모양 -


- 이미지를 올려놓았을 때 모양 -

이미지는 들어갔지만 원하는 모양은 아닙니다.
1. Bar Button Item 에 Round Rect Button을 올립니다.
2, Bar Button Item 를 삭제 후 Round Rect Button를 넣습니다
둘 다 같습니다.


     보시다시피 Bar Button Item 안에 Button이
     들어가게 됩니다.

     즉. 저희가 평소에 버튼에 이미지를 입히는
     방식으로 가능하다는 예기입니다.



- Item이 아닌 Button을 입힌 모양 -

- Button에 이미지 넣은 모양 -


그리고 이미지 사이즈를 조절하고 싶다면 Item이 아닌 그 안에 있는 Button의 View에 있는 
Origin을 수정하시면 됩니다.



- 사이즈 조절 후 모양 -



네비게이션 바와는 다르게 소스를 고칠 필요가 없었습니다.
Item안에  Button을 넣어서 Button 로 처리하는 방식을 그대로 사용하면 되기 때문입니다.


끝... 이 아닙니다!

고려할 사항이 있습니다. 네비게이션 컨트롤러 사용 시 Push할 때 생기는 버튼이 있습니다.


[ 이미지를 입힌 버튼을 다른 뷰 컨트롤러에 Push로 Modal을 설정해줍니다. ]


그러면 보시다시피 Push되면서 자동(아무 설정은 안해주었을 때)으로 Navigation Item의 Title을 적힌 뒤로가기 버튼을 만들어 줍니다. 


- Back Button 에 원하는 문구를 설정 가능합니다. -
( Prompt 는 제목같은 효과입니다. 직접 해보시는게 이해하기 빠릅니다 )

그렇다면 이미지는??
해당 뷰컨트롤러(Push로 들어간 페이지)에서 처리할려고 해도 미리 만들어버리기 때문이 올바른 접근 방법이 아닙니다.

Push로 들어갈 때! 버튼을 셋팅해주어야 합니다. 이때 필요한 함수가 prepareForSegue 라는 함수입니다.

prepareForSegue함수는 Segue(=modal)될 때, Segue를 위해 준비하는 함수로 Push나 Modal로 다른 페이지로 넘어가기전에 호출되는 함수입니다.


이 전에 Push의 Identifier 설정해 주어야 합니다.
( ex: showDetail 이라고 저는 주었습니다.




.... 이럴수가 위에 방법과 똑같이 Item에 Button을 넣어서 입히면 될 줄 알았지만 착각이였습니다.

첫번째 시도, Item 에 Button을 넣는방법  ----- Fail (아무런 변화 없음)

두번째 시도, Item의 image를 넣는 방법  ----- Fail (모양이...)

세번째 시도, Item의 배경에 집어넣는 방법 ----- Fail (모양+문자 그대로)


- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

{

    if ([[segue identifier] isEqualToString:@"showDetail"]) {

       


UIBarButtonItem *backBarButton = [[UIBarButtonItem alloc]init];    

        

        

[backBarButton setBackButtonBackgroundImage:[UIImage imageNamed:@"BG1.png"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

[self.navigationItem.backBarButtonItem setImage:[UIImage imageNamed:@"anger2.png"]];

       


    }

}

그렇다면!! 2번째와 3번째 방법을 합쳐서! 배경을 네비게이션바 배경으로 준 다음 했다

..... 이게 아닌데 우리가 원하는 모양은 아니지만 임시방편으로 구현,



괜히 카톡도 색깔만 바꾼게 아니었어..
혹시나 네비게이션바 아이템을 커스텀한 어플이 있다면 신고바랍니다.


'제2외국어 > iOS' 카테고리의 다른 글

[Customize] 4. UIAlertView  (0) 2012.04.24
[Customize] 3. Tabbar  (2) 2012.04.13
[Customize] 2. Navigation Item  (1) 2012.04.12
[Customize] 1. Navigation Bar  (0) 2012.04.10
[UIView] 애니메이션효과 주기  (5) 2012.04.05
[iOS]UIColor, RGB값 간단히 Macro로 사용하기  (1) 2012.03.20

Comment +1