프로그래밍/Objective-C2010. 7. 29. 09:46
* Quartz 라이브러리

  - 아이폰 OS에서 그래픽 기능을 구현하기 위한 C 라이브러리

  - 그림을 그리기 위해서는 그림을 그릴 대상인 CGContextRef가 필요하다. 그림을 그리기 위한 모든 정보를 저장하는 컨텍스트임. 그래픽카드를 추상화한 개념이라고 생각하면 된다

view : drawRect( ) -> CGContextRef에서 상속받음

  - Quartz API를 이용해 객체를 생성, 뷰가 아닌 다른 곳에 그림을 그릴 수 있다

  - 뷰에 그림을 그리기 위해서는 drawRect 메소드를 이용해서

CGContextRef 변수명 = UIGraphicsGetCurrentContext();

    와 같이 해주면 변수명이 CGContextRef 객체가 된다. 

  - touchesBegan 등에서도 그릴 수는 있다. 다만 CGContextRef가 없기 때문에 drawRect()를 빌려서 사용해야 한다


* drawRect

  - 다음과 같은 경우에 자동으로 호출된다
뷰 위를 부분적으로 덮고 있던 또 다른 뷰가 이동하거나 사라질때
숨겨져 있던 뷰의 hidden 속성을 NO로 설정해서 다시 나타나도록 했을 때
뷰를 스크린 밖으로 스크롤했다가 돌아올때
setNeedsDisplay나 setNeedsDisplayInRect를 호출했을 때

  - 패러미터
CGContextSetRGBStrokeColor(그래픽컨텍스트,R,G,B,A):선의 색상
CGContextSetLineWidth(그래픽컨텍스트, 두께)
CGContextStrokePath(그래픽 컨텍스트)
CGContextSetRGBFillColor(그래픽컨텍스트,R,G,B,A): 면색


* 작도 함수

  - 선 그리기
CGContextMoveToPoint(그래픽컨텍스트객체, x, y)
CGContextAddLineToPoint(그래픽컨텍스트객체, x, y) : 계속해서 이어서 그린다
CGContextSetLineDash(그래픽컨텍스트객체, 시작위치, 실수배열, 개수);

  - 사각형 그리기
CGContextFillRect(그래픽컨텍스트객체, CGRect 타입 변수)

  - 원 그리기
CGContextAddEllipseInRect(그래픽컨텍스트객체, CGRect 타입 변수)

  - 다각형은 선을 연속해서 그리면 됨


* 선 그리는 예제 코드(TestView.m)

#import "TestView.h"

@implementation TestView

- (id)initWithFrame:(CGRect)frame 
{
    if ((self = [super initWithFrame:frame])) 
{
        // Initialization code
    }
    return self;
}

-(IBAction)Line
{
mode = 1;
[self setNeedsDisplay];
}

-(IBAction)Rect
{
mode = 2;
[self setNeedsDisplay];
}

-(IBAction)Polygon
{
mode = 3;
[self setNeedsDisplay];
}

-(void) drawLine:(CGContextRef)context 
{
// 선 색상 설정
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

// 선 두께
CGContextSetLineWidth(context, 1.0);
// 선 그리기
CGContextMoveToPoint(context, 10.0, 30.0);
CGContextAddLineToPoint(context, 310.0, 30.0);
CGContextStrokePath(context);
CGContextSetLineWidth(context, 1.0);
// 두번째 선
CGContextSetLineWidth(context, 4.0);
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextMoveToPoint(context, 10.0, 50.0);
CGContextAddLineToPoint(context, 310.0, 50.0);
CGContextStrokePath(context);
// 점선
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
CGFloat dash[] = {5.0, 10.0, 15.0, 20.0};
CGContextSetLineDash(context, 0.0, dash, 4);
CGContextMoveToPoint(context, 10.0, 70.0);
CGContextAddLineToPoint(context, 310.0, 70.0);
CGContextStrokePath(context);
CGContextSetLineDash(context, 0.0, NULL, 0); // 점선을 그리게 해주는 방법
// 배열 이용하기
CGPoint lines[] =
{
CGPointMake(10.0, 90.0),
CGPointMake(60.0, 140.0),
CGPointMake(110.0, 130.0),
CGPointMake(160.0, 190.0),
CGPointMake(210.0, 200.0),
CGPointMake(260.0, 90.0),
CGPointMake(310.0, 200.0),
};
CGContextSetLineWidth(context, 5.0);
CGContextAddLines(context, lines, sizeof(lines)/sizeof(lines[0])); // 배열의 갯수 구하는 방법이지만 
                                                                                                      // 포인터 배열에서는 사용하지 말 것.
CGContextStrokePath(context);
}

-(void) drawRectangle:(CGContextRef)context 
{
// 선 색상
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

// 채우기 색
CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 1.0);
// 선 두께
CGContextSetLineWidth(context, 2.0);
// 경로에 사각형 추가
CGContextAddRect(context, CGRectMake(30.0, 30.0, 60.0, 60.0));
CGContextStrokePath(context);
// 사각형 채우기
CGContextFillRect(context, CGRectMake(130.0, 30.0, 60.0, 60.0));
CGContextStrokeRectWithWidth(context, CGRectMake(230.0, 30.0, 60.0, 60.0), 4.0);
}

-(void) drawPolygon:(CGContextRef)context 
{
CGPoint center;
// 선 색상
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

// 채우기 색
CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
// 선 두께
CGContextSetLineWidth(context, 1.0);
// 별 그리기
center = CGPointMake(80.0, 100.0);
CGContextMoveToPoint(context, center.x, center.y + 30.0);
for(int i = 1; i < 5; ++i)
{
CGFloat x = 30.0 * sinf(i * 4.0 * M_PI / 5.0); // M_PI -> Objective-C에서 매크로로 정의해둔 
        // 원주율 값
CGFloat y = 30.0 * cosf(i * 4.0 * M_PI / 5.0);
CGContextAddLineToPoint(context, center.x + x, center.y + y);
}
CGContextClosePath(context);
CGContextFillPath(context);
// 별 + 원 그리기
center = CGPointMake(160.0, 100.0);
CGContextMoveToPoint(context, center.x, center.y + 30.0);
for(int i = 1; i < 5; ++i)
{
CGFloat x = 30.0 * sinf(i * 4.0 * M_PI / 5.0);
CGFloat y = 30.0 * cosf(i * 4.0 * M_PI / 5.0);
CGContextAddLineToPoint(context, center.x + x, center.y + y);
}
CGContextAddEllipseInRect(context,CGRectMake(130, 70, 60,60));
CGContextClosePath(context);
CGContextEOFillPath(context);
// 5각형 그리기
center = CGPointMake(240.0, 100.0);
CGContextMoveToPoint(context, center.x, center.y + 30.0);
for(int i = 1; i < 6; ++i)
{
CGFloat x = 30.0 * sinf(i * 2.0 * M_PI / 6.0);
CGFloat y = 30.0 * cosf(i * 2.0 * M_PI / 6.0);
CGContextAddLineToPoint(context, center.x + x, center.y + y);
}
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
}

- (void)drawRect:(CGRect)rect 
{
CGContextRef context = UIGraphicsGetCurrentContext();
if(mode==1)
[self drawLine:context];
else if(mode==2)
[self drawRectangle:context];
else
[self drawPolygon:context];
    // Drawing code
}


* 베지어 곡선

  - CGContextAddCurveToPoint 를 이용해서 그린다

  - 3개의 좌표를 대입하게 되는데 이 좌표는 첫번째 제어점, 두번째 제어점, 종료점이다

1. 앞의 예제에 툴바 버튼을 1개 추가

2. IBAction 메소드 추가하고 앞에 만든 툴바 버튼과 연결
-(IBAction)Bazier;

3. 메소드 구현

-(IBAction)Bazier
{
mode = 4;
[self setNeedsDisplay];
}

-(void) drawBezier:(CGContextRef)context 
{
// 색상 설정
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
// 선 두께
CGContextSetLineWidth(context, 2.0);
// 원 그리기 (하단)
CGContextAddEllipseInRect(context,CGRectMake(60, 20, 200,200));
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextDrawPath(context, kCGPathFillStroke);
CGContextStrokePath(context);
// 베지어 곡선 그리기
CGPoint s = CGPointMake(60.0, 120.0);
CGPoint cp1 = CGPointMake(130.0, 230.0);
CGPoint cp2 = CGPointMake(190.0, 10.0);
CGPoint e = CGPointMake(260.0, 120.0);
CGContextMoveToPoint(context, s.x, s.y);
CGContextAddCurveToPoint(context, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y);
CGContextSaveGState(context);
// 반원 그리기 (상단)
CGContextAddArc(context,160,120,100,0,M_PI,true);
CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextDrawPath(context, kCGPathFillStroke);
CGContextStrokePath(context);
}

- (void)drawRect:(CGRect)rect 
{
CGContextRef context = UIGraphicsGetCurrentContext();
if(mode==1)
[self drawLine:context];
else if(mode==2)
[self drawRectangle:context];
else if(mode ==3)
[self drawPolygon:context];
else
[self drawBezier:context];
    // Drawing code
}


* Core Animation

  - 간단 예제
#import <QuartzCore/CAAnimation.h>
#import <QuartzCore/CAMediaTimingFunction.h>

#import "AniTest.h"


@implementation AniTest

-(IBAction)ani1 // 투명도 보
{
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"opacity"];
float from = 0.1;
float to = 1.0;
ani.fromValue = [NSNumber numberWithFloat:from];
ani.toValue = [NSNumber numberWithFloat:to];
ani.duration = 1.0;
ani.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
ani.delegate = self;
ani.autoreverses = YES;
[imgView.layer addAnimation:ani forKey:nil];
imgView.layer.opacity = 1.0;
}

-(IBAction)ani2 // 위치 보
{
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"position"];
CGPoint from = CGPointMake(50,50); 
CGPoint to = CGPointMake(250,250); 
ani.fromValue = [NSValue valueWithCGPoint:from];
ani.toValue = [NSValue valueWithCGPoint:to];
ani.duration = 1.0;
ani.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
ani.delegate = self;
ani.autoreverses = YES;
[imgView.layer addAnimation:ani forKey:nil];
imgView.layer.position = to;
}

-(IBAction)ani3 // 크기 보간
{
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"bounds"];
CGRect from = imgView.layer.bounds;
CGRect to = CGRectMake(20,20,120,120);
ani.fromValue = [NSValue valueWithCGRect:from];
ani.toValue = [NSValue valueWithCGRect:to];
ani.duration = 1.0;
ani.delegate = self;
ani.autoreverses = YES;
[imgView.layer addAnimation:ani forKey:nil];
}

-(IBAction)ani4 // 키프레임 커브 좌표 보간이동
{
CAKeyframeAnimation *ani = [CAKeyframeAnimation animationWithKeyPath:@"position"];
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath,NULL, 50,200);
CGPathAddCurveToPoint(thePath,NULL,
 100.0,50.0,
 220.0,350.0,
 270.0,200.0);
ani.path = thePath;
ani.calculationMode = kCAAnimationPaced;
ani.duration = 3.0;
ani.delegate = self;
[imgView.layer addAnimation:ani forKey:nil];
CFRelease(thePath);
}

- (id)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
        // Initialization code
    }
    return self;
}


Posted by windship
프로그래밍/Objective-C2010. 7. 28. 10:58
* 예외처리

  - Objective-C의 예외처리를 위한 예약어
@try: Exceptions이 던져질 수 있는 block을 정의한다
@throw: Exception object를 던진다
@catch(): @try bolck안에서 던져진 exception을 catch한
@finally: @try block에서 Exceptions가 던져지던 아니던 수행되어질 block code를 정의한다

  - 모두 NSException.h에 정의되어 있다


* NSAssert

  - 특정 조건을 만족하지 않는 경우 NSInternalInconsistencyException예외를 발생시켜 프로그램을 강제로 중단시키는 매크로함수
  - 사용방법 : NSAssert(만족해야 하는 조건, 출력할 문장);


* 에러 처리

  - 에러가 발생하면 메서드나 함수의 리턴 값 형태로 에러의 발생을 리턴한다. 파일 처리에는 이러한 에러 처리를 위한 객체를 대입하도록 되어 있다. 이 경우 에러 처리에 관련된 오브젝트를 대입하면 에러가 발생해도 프로그램이 중단되지 않고 적절한 메시지를 출력하도록 할 수 있다

  - NSError : NSError.h 파일에 정의되어 있는 클래스로 에러에 대한 정보를 저장할 수 있는 클래스
* 생성자
+(id)errorWithDomain:(NSString *)domain code:(NSInteger)code userInfo:(NSDictionary *)dic

* 멤버 프로퍼티
(NSString *)domain: 에러와 관련된 기술 요소 (Cocoa, Unix…)
(NSInteger)code: 에러에 관련된 정수 값
(NSDictionary *)userInfo: 에러에 관련된 정보를 저장할 사전

* 멤버 메서드
(NSString *)localizedDescription: 에러를 설명하는 문자열로 domain과 code 출력
(NSString *)localizedFailureReason: 에러의 발생 원인
(NSString *)localizedRecoverySuggestion: 에러의 대처 방법


* XCode 화면 설정

  - [X-Code] – [Preference] 메뉴를 이용
  - [All – In – One]:  빌드, 디버깅, 검색 등이 모두 하나의 창에서 실행
  - [Condensed]: 파일 창, 편집 창, 디버깅 창 등이 모두 분리되어서 실행
  - [Default]: 그룹 및 파일 창, 편집 창 등은 통합되어 있고 디버깅 창,  GDB 콘솔 등의 일부 창은 분리된 상태에서 실행


* Break Point

  - Break Point 설정 : 원하는 지점을 선택하고 마우스 오른쪽을 클릭해서 Add BreakPoint

  - Break Point 삭제 : Break Point를 선택하고 마우스 오른쪽을 클릭해서 remove BreakPoint

  - Break Point 까지 실행 후 옵션
Continue: 코드를 계속 실행
 Step Over: 코드 다음 행으로 이동
 Step Into - 코드가 다른 메서드를 호출하는 경우 메서드 안으로 진입
 Step out - 현재 메서드를 빠져 나가서 호출하는 메서드로 이동

  - Break Point에 소리 설정하기 : 마우스 오른쪽을 클릭한 후 [Built-In BreakPoints] – [Sound out and auto-continue]

  - Break Point에 동작 지정하기
Break Point에서 오른쪽의 + 버튼을 눌러서 동작 지정 가능
[Log]: 콘솔에 로그를 남기
[Sound]: 시스템에 내장된 소리를 재생
[Shell Command]: 셀 명령 실행
[Debugger Command]: GDB 명령을 남김


* Watch Point

  - 변수의 값이 변경되는 경우를 감시하고자 하는 경우에 사용하는 기능. 이 포인트를 설정해두면 변수의 값이 변경되면 실행이 자동적으로 멈추게 된다
 
  - 디버거 창의 Variable 항목에서 선택할 수 있으며, 변수를 선택하고 마우스 오른쪽 메뉴를 눌러서 Watch Variable를 선택


* Instruments

  - 실행 중인 프로그램의 동작 상태를 감시하고 분석하는 데 사용되는 프로그램

  - 작업의 종류
1. Leaks: 메모리 누수 감지
2. Object Allocations - 객체의 생성과 해제를 감시
3. CPU Sampler – CPU 사용량 확인
4. Activity Monitor:  시스템 자원을 사용하는 상황을 감시 - 모든 프로그램 검사
5. Core Animation/OpenGL ES: 그래픽 성능 검사
6. System Usage: 프로그램의 I/O 작업을 감시


* 지역화(Localization)

  - 각 나라별로 서로 다르게 보이는 애플리케이션을 구현하고자 하는 경우 사용하는 것. 일반적으로 문자열의 변환이나 이미지의 변환 및 아이콘의 변화 등을 의미한다

  - 지역화 가능 요소: Nib 파일, 문자열, 아이콘 및 그래픽 요소, 소리 파일, Info.pList의 내용

  - 지역화 파일을 생성하는 방법 : GetInfo 메뉴에서 General – Make File Localizable 


* 문자열 지역화
 
  - 문자열을 지역화하기 위해서는 Localizable.strings 파일을 생성해서 이 파일을 먼저 지역화해준다

  - 각각의 지역화되어 있는 파일에서 “키값” = “ 실제데이터”; 로 지역화를 해주면 된다

  - 매칭되는 키 값이 없다면 있는 그대로 출력될 것이며 이를 사용할 때는 NSLocalizedString(@”키값”, @”보충설명”)형태로 사용해야 한다

  - 지역화 예제
1. Resource 디렉토리에  strings 파일을 생성(Localizable.strings) =>Mac OS X 의 Resource에 있다
2. Localizable.strings 파일을 선택하고 Info 버튼을 누르고 Make File Localizable을 누르고  Add Localization을 선택하고 Korean을 입력
3. Localizable.strings 아래의 English 파일에 입력
"Language" = "English";
"Greeting" = "Hello"; 
4. Localizable.strings 아래의 English 파일에 입력
"Language" = "한국어";
"Greeting" = "안녕하세요";


* xib 파일의 지역화

  - View-Based Application 프로젝트 생성

  - Resource 디렉토리에 그림 파일을 2개 생성

  -  ViewController.xib 파일을 선택하고 Info 아이콘을 클릭해서 General 탭에서 AddLocalization을 클릭, Korean을 추가

  - xib 아래에 2개의 언어가 보일 것이고 언어별로 다르게 디자인하면 된다


* 리소스 지역화(다른 리소스 사용)

  - Localizable.strings에 아래 문장 추가
"Image" = "Acrobat.png";
"Image" = "아크로뱃.png";

  - ViewController.h 파일에 변수 선언 및 프로퍼티 선언
@interface StringLocalizeViewController : UIViewController 
{
UILabel *label1;
UILabel *label2;
UIImageView * imgView;

}
@property(nonatomic, retain)IBOutlet UILabel *label1;
@property(nonatomic, retain)IBOutlet UILabel *label2;
@property(nonatomic, retain)IBOutlet UIImageView * imgView;
@end


* 오디오

  - 소리를 재생하는 방법은 2가지로 하나는 System Sound API를 이용하는 방법이 있고 AVAudioPlayer를 이용하는 방법이 있다

  - System Sound API를 이용하는 방법은 AIFF, WAV, CAF 파일만 재생이 가능

  - System Sound API를 이용해서 소리를 재생하기 위해서는 먼저 사운드를 시스템 소리 객체(SystemSoundID)로 만들어야 한다

  - 소리 객체 만들기: OSStatus AudioServicesCreateSystemSoundID(CFURLRef inFileURL, SystemSoundID *outSytemSoundID) 함수룰 호출해서 생성

  - 소리 재생: AudioServicesPlaySystemSound(SystemSoundID inSystemSoundID)를 호출하면 된다. 이 때 매개 변수로 kSystemSoundID_Vibrate를 대입하면 진동이 생긴다

  - 소리 객체 파기:OSStatus AudioServicesDisposeSystemSoundID(SystemSoundID *inSytemSoundID)를 호출하면 된다.
AudioToolbox.framework의 AudioToolbox.h에 메소드들이 정의되어 있음

  - 파일경로를 URL 형태로만 받기 때문에 NSString을 사용해서 선언해야 함. 멀티미디어 기능은 거의 대부분이 URL 형태로 사용하므로 반드시 알아 두어야 함

  - 아주 단순한 효과음만을 재생하는 기능이므로 단점과 제약이 많음
반복 불가능
음량 조절 불가능
재생 중에 중지 불가능
동시에 여러개 재생 불가능
확장자 제약이 심함



* AVAudioPlayer

  - 긴 소리 재생에 주로 이용하는 방법으로 아래와 SystemSoundAPI 에 비해서 아래와 같은 장점을 가지고 있습니다.
반복기능 제공
음량 조절 가능
중간에 재생을 중지 할 수 있음
동시에 여러 개의 음악을 재생할 수 있음
음악 파일의 확장자 제한이 일반적으로 없음

  -AVFoundation.framework에 존재하며 AVAudionPlayer.h 파일에 정의

  - 메소드
initWithContentsOfURL:(NSURL *)url error:(NSError **)error: 초기화
(BOOL)play : 재생
(void)pause: 중지
(void)stop: 재생 종료
BOOL Playing: 재생여부를 리턴하는 프로퍼티
NSURL *url: 소리 파일의 URL(readonly)
float volume: 소리 크기(0.0 - 1.0)
NSInteger numberOfLoops: 반복 재생 횟수
NSTimeInterval currentTime: 초기 재생 시간


Posted by windship
프로그래밍/Objective-C2010. 7. 22. 09:45
* 파일 처리

  - 아이폰에서 참조하게 되는 폴더들 : Application – Documents, Library, tmp, Caches, Preferences, Application.app

  - 위의 폴더들이 존재하지만 그 중 Documents 폴더만 우리가 사용할 수 있다

  - app는 번들 디렉토리이다. 실행 중에는 이 폴더의 내용을 변경할 수 없다

  - Library 폴더 안에는 다시 Caches와 Preference 폴더가 존재하며 Preference 폴더 안에 NSUserDefaults가 생성하는 .plist 파일이 존재한다

  - Preference는 ITunes에 의해 백업된다

  - Caches는 애플리케이션에 의존적이어야 하는 파일을 저장

  - tmp는 지속적으로 저장되지 않아도 되는 파일을 저장


* 특별한 용도의 파일

  - Default.png 파일은 애플리케이션이 로드될 때 자동으로 호출되는 그림 파일이다

  - 최상위 폴더에 넣어두면 자동으로 호출되어 출력된다 (주로 로딩시에 로고를 보여주는 용도로 사용됨)

  - 이 파일은 320x480 사이즈를 권장한다

  - ~~~info.plist 파일 역시 번들 정보를 저장하고 있는 특별 용도의 파일이다

  - 이 2개의 파일은 위치와 이름이 반드시 정해진 대로 되어 있어야 하며 바꿀 수 없다


* 파일에 읽기/쓰기

  - Documents 폴더의 경로 얻기
NSArray * 배열명 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *경로명 = [배열명 objectAtIndex:0];

  - 현재 프로젝트의 번들 경로 얻기
[[NSBundle mainBundle]bundlePath];

  - NSString, NSDictionary, NSData, NSArray, NSDate의 파일로부터 읽기와 쓰기
파일로부터 읽기
-(id)initWithContentsOfFile:(NSString *)path;
URL로 부터 읽기
-(id)initWithContentsOfURL:(NSURL*)url;
파일에 쓰기
-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag;
URL에 쓰기
-(BOOL)writeToFile:(NSURL *)url atomically:(BOOL)flag;


* 아카이브

  - 프로그램에서 사용되는 Object를 속성 값이나 관계를 포함에서 파일에 바이트 배열로 저장해 두는 것을 archive라고 한다

  - Object를 바이트 배열로 저장하는 것을 archive라고 하고 반대되는 작업을 unarchive라고 한 다

  - 객체를 archive하기 위해서는 NSCoding이라는 프로토콜을 따라야 한다 . 이 규칙을 따르게 되면 archive가 가능하고 NSString이나 NSDictionary 등은 이 프로토콜을 이미 적용해 두고 있다

  - NSArray나 NSDictionary 또는 NSData 등의 자료구조들은 description 메서드를 호출하면 데이터들을 propertyList로 만들어서 출력해준다. 이 때 문자열은 “”로 묶어주며 영문자와 숫자로만 구성된 경우 “”를 생략해도 된다

  - 데이터는 < >로 16진수로 묶어서 표현하게 된다

  - 저장되는 구조는 description을 확인하면 되고 파일에 저장되어 있는 경우에 읽어 올 수도 있다. 이 때 이 파일들은 XML 구조로 저장되며 수정이 불가능한 객체로 리턴되므로 주의해야 한 다


* 일반 클래스 아카이브

  - 일반 오브젝트를 아카이브 할 때는 NSCoding 프로토콜에 정의되어 있는 encodeWithCoder:와 initWithCoder: 메서드를 정의하면 된다

  - 메서드의 원형
-(void)encodeWithCoder:(NSCoder *)encoder
이 메서드의 안에서 encoder가 아카이브 할 실제 멤버들을 직접 인코딩하면 된다
-(id) initWithCoder:(NSCoder *)decoder
이 메서드의 안에서 decoder가 언아카이브 할 실제 멤버들을 직접 디코딩하면 된다

  - 기본 데이터 타입에 대한 인코드와 디코드 메서드
encodeBool:forKey   decodeBool:forKey
encodeInt:forKey  decodeInt:forKey
encodeInt32:forKey decodeInt32:forKey
encodeInt64:forKey decodeInt64:forKey
encodeFloat:forKey decodeFloat:forKey
encodeDouble:forKey decodeDouble:forKey


Posted by windship
프로그래밍/Objective-C2010. 7. 21. 11:15
* CustomCell을 사용한 테이블뷰의 셀 꾸미기 예제

  - Navigation-Based Application 프로젝트 생성

  - UITableViewCell로 부터 상속받는 클래스 생성(CustomCell). Objective-C Class로 해야한다.

  - CustomCell 클래스의 헤더 파일에 변수 및 프로퍼티 선언
#import <UIKit/UIKit.h>

@interface CustomCell : UITableViewCell 
{
// 레이블 2개, 이미지 뷰 1개를 가지는 셀을 만듬.
UILabel *lblName;
UILabel *lblInfo;
UIImageView *imageView;
}

// .을 이용하기 위한 프로퍼티 선언(외부와 연결할 것이므로 IBOutlet도 지정)
@property(nonatomic,retain)IBOutlet UILabel *lblName;
@property(nonatomic,retain)IBOutlet UILabel *lblInfo;
@property(nonatomic,retain)IBOutlet UIImageView *imageView;

@end

  - CustomCell 클래스의 구현 파일(.m 파일)에 synthesize 지정
@synthesize lblName;
@synthesize lblInfo;
@synthesize imageView;

  - CustomCell의 xib 파일 추가. Resources 우클릭 > Add File > User Interface > UIView

  - 추가된 CustomCell.xib 파일을 편집(인터페이스빌더). 기본으로 붙어있는 view를 제거하고 TableViewCell을 추가

  - TableViewCell의 인스펙터 창에 있는 속성 중 ClassIdentify 부분을 위에서 만든 CustomCell 클래스로 바꿔줌
 
  - CustomCell의 화면을 디자인(이미지 뷰와 레이블 등등...). 변수연결 작업(IBOutlet)

  - RootViewController.h 파일에 데이터 변수 선언
#import <UIKit/UIKit.h>

@class CustomCellAppDelegate;

@interface RootViewController : UITableViewController 
{
NSMutableArray * ar; // 테이블 뷰에 출력될 데이터 배열
CustomCellAppDelegate * app;
}

@property(nonatomic, retain) NSMutableArray * ar;

@end

  - RootViewController.m 파일에 헤더 파일 import 시키고 synthesize 지정
#import "RootViewController.h"
#import "CustomCell.h"; // 만들어진 Custom 클래스를 사용하기 위해서 import함
#import "CustomCellAppDelegate.h";

@implementation RootViewController

@synthesize ar;

  - RootViewController.m 파일의 viewDidLoad 에서 데이터 생성
-(void)viewDidLoad
{
[super viewDidLoad];
app = (CustomCellAppDelegate *) [[UIApplication sharedApplication]delegate];

// 딕셔너리는 항상 데이터(object)와 키가 함께 저장된다. 
        //아래 Name, imageName, Description 부분이 키이다. 
// 딕셔너리 내부의 데이터에 바로 접근할 수는 없고, 항상 그 딕셔너리의 키를 통해서 접근해야만 한다.
// -(id)ObjectForKey : (id)Key -> Key에 해당하는 Object 리턴
// -(NSArray *)allKeys -> 모든 key값을 리턴

NSDictionary *dic1 = [[NSDictionary alloc] initWithObjectsAndKeys:
@"아크로뱃", @"Name", @"Acrobat.png", @"imageName", @"문서 작성", @"Description", nil];
NSDictionary *dic2 = [[NSDictionary alloc] initWithObjectsAndKeys:
@"AIM", @"Name", @"AIM.png", @"imageName", @"기본", @"Description", nil];
NSDictionary *dic3 = [[NSDictionary alloc] initWithObjectsAndKeys:
@"앱스토어", @"Name", @"AppStore.png", @"imageName", @"앱스토어", @"Description", nil];
NSDictionary *dic4 = [[NSDictionary alloc] initWithObjectsAndKeys:
@"계산기", @"Name", @"Calculator.png", @"imageName", @"계산기", @"Description", nil];

app.ar = [[NSMutableArray alloc] initWithObjects:dic1, dic2, dic3, dic4, nil];

[dic1 release];
[dic2 release];
[dic3 release];
[dic4 release];
}

  - RootViewController.m 파일에 데이터 출력
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [app.ar count];
}

// 셀을 만들어주는 메소드. indexPath는 row와 section을 멤버로 가져서 그것으로 그룹과 행을 구분한다.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *CellIdentifier = @"Cell"; // 셀을 구분하기 위한 문자열을 생성
    
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
 // CustomCell의 xib파일에 있는 내용을 객체로 만들어달라고 요청하는 부분
cell = (CustomCell *)[nib objectAtIndex:0]; // 배열의 첫번째 객체를 CustomCell * 으로 
                                                               // 변경해서 cell에 대입
}
NSDictionary *Dic = [app.ar objectAtIndex:indexPath.row]; // ar 배열로부터 행번호에 해당하는 
                                                                          // 딕셔너리를 Dic에 대입
cell.lblName.text = [Dic objectForKey:@"Name"];
cell.lblInfo.text = [Dic objectForKey:@"Description"];
cell.imageView.image = [UIImage imageNamed:[Dic objectForKey:@"imageName"]];
return cell;
}

// 행의 높이를 만들어주는 메소드
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}


* 인덱스 테이블 예제

1. Navigation Based Application 프로젝트 생성

2. UITableViewController로 부터 상속받는 SubViewController 추가

3. RootViewController.h  파일에 변수 선언 및 프로퍼티 선언
#import <UIKit/UIKit.h>

@class SubViewController;

@interface RootViewController : UITableViewController 
{
NSMutableArray * data; // 실제 데이터를 저장하고 있을 배열
SubViewController * subView; // 서브 데이터를 출력해 줄 서브 뷰 컨트롤러
}

@property(nonatomic, retain) NSMutableArray * data;
@property(nonatomic, retain)SubViewController * subView;

@end

4. RootViewController.m  파일에 synthesize이용과 loadview에서 데이터 생성
#import "RootViewController.h"
#import "SubViewController.h"

@implementation RootViewController

@synthesize data;
@synthesize subView;

- (void)loadView 
{
[super loadView];
NSArray *KIA;
NSArray *SK;
NSArray *HD;
NSArray *LG;
KIA = [NSArray arrayWithObjects:@"윤석민", @"이용규", @"이종범", @"김연아", @"이동국", @"박지성", @"차범근", @"허정무", nil];
SK = [NSArray arrayWithObjects:@"김광현", @"김재현", @"고효준", @"정근우", @"나주환", nil];
HD = [NSArray arrayWithObjects:@"김시진", nil];
LG = [NSArray arrayWithObjects:@"이택근", @"이병규", @"봉중근", nil];
NSDictionary *Dic1, *Dic2, *Dic3, *Dic4;
Dic1 = [[NSDictionary alloc] initWithObjectsAndKeys:@"KIA", @"Team", KIA, @"data", nil];
Dic2 = [[NSDictionary alloc] initWithObjectsAndKeys:@"SK", @"Team", SK, @"data", nil];
Dic3 = [[NSDictionary alloc] initWithObjectsAndKeys:@"HD", @"Team", HD, @"data", nil];
Dic4 = [[NSDictionary alloc] initWithObjectsAndKeys:@"LG", @"Team", LG, @"data", nil];

self.data = [[NSArray alloc] initWithObjects:Dic1, Dic2, Dic3, Dic4, nil];

[Dic1 release];
[Dic2 release];
[Dic3 release];
[Dic4 release];
self.title = @"프로야구";
}

5. RootViewController.m  파일에 데이터를 출력하고 처리하는 메소드 작성
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{
    return [self.data count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    NSDictionary *Dic = [data objectAtIndex:indexPath.row];
cell.textLabel.text = [Dic objectForKey:@"Team"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    if (subView == nil) 
{
SubViewController *temp= [[SubViewController alloc] initWithStyle:UITableViewStylePlain];
self.subView = temp;
[temp release];
}
self.subView.subData = [self.data objectAtIndex:indexPath.row];
[[self navigationController] pushViewController:subView animated:YES];
}

6. SubViewController.h  파일에 변수 생성과 프로퍼티 설정
#import <UIKit/UIKit.h>

@interface SubViewController : UITableViewController 
{
//루트로부터 데이터를 받을 변수
NSDictionary *subData;
//각 섹션에 해당하는 데이터
NSMutableArray *sectionData;
//인덱스 항목을 가지고 있을 변수
NSArray *index;
}

@property(nonatomic, retain)NSDictionary *subData;
@property(nonatomic, retain)NSMutableArray *sectionData;
@property(nonatomic, retain)NSArray *index;

//이름을 넘겨주면 자음을 리턴해주는 메서드
-(NSString *)subtract:(NSString *)data;
@end

7. SubViewController. m  파일에 synthesize지정과 loadView메서드 정의 
#import "SubViewController.h"

@implementation SubViewController

@synthesize subData;
@synthesize sectionData;
@synthesize index;

- (void)loadView {
[super loadView];
self.sectionData = [[NSMutableArray alloc] init];
self.index = [[NSArray alloc] initWithObjects:@"ㄱ", @"ㄴ", @"ㄷ", @"ㄹ", @"ㅁ", @"ㅂ", @"ㅅ", @"ㅇ", @"ㅈ", @"ㅊ", @"ㅋ", @"ㅌ", @"ㅍ", @"ㅎ", nil];
}

8. SubViewController. m  파일에 subtract메서드  정의
- (NSString *)subtract:(NSString*)data 
{
NSComparisonResult result = [data compare:@"나"];
if(result == NSOrderedAscending) 
return @"ㄱ";
result = [data compare:@"다"];
if(result == NSOrderedAscending) 
return @"ㄴ";
result = [data compare:@"라"];
if(result == NSOrderedAscending) 
return @"ㄷ";
result = [data compare:@"마"];
if(result == NSOrderedAscending) 
return @"ㄹ";
result = [data compare:@"바"];
if(result == NSOrderedAscending) 
return @"ㅁ";
result = [data compare:@"사"];
if(result == NSOrderedAscending) 
return @"ㅂ";
result = [data compare:@"아"];
if(result == NSOrderedAscending) 
return @"ㅅ";
result = [data compare:@"자"];
if(result == NSOrderedAscending) 
return @"ㅇ";
result = [data compare:@"차"];
if(result == NSOrderedAscending) 
return @"ㅈ";
result = [data compare:@"카"];
if(result == NSOrderedAscending) 
return @"ㅊ";
result = [data compare:@"타"];
if(result == NSOrderedAscending) 
return @"ㅋ";
result = [data compare:@"파"];
if(result == NSOrderedAscending) 
return @"ㅌ";
result = [data compare:@"하"];
if(result == NSOrderedAscending) 
return @"ㅍ";
return @"ㅎ";
}

9. SubViewController. m  파일에 viewWillAppear 메서드 재정의
- (void)viewWillAppear:(BOOL)animated 
{
[self.sectionData removeAllObjects];
NSMutableArray *temp[[self.index count]];
for(int i = 0; i < [self.index count]; i++)
{
temp[i] = [NSMutableArray arrayWithCapacity:100];
}
NSArray *name = [subData objectForKey:@"data"];
for(int i = 0; i < [self.index count]; i++)
{
NSString *pre = [self.index objectAtIndex:i];
for(int j = 0; j < [name count]; j++)
{
NSString *str = [name objectAtIndex:j];
if([pre isEqualToString:[self subtract:str]])
{
[temp[i] addObject:str];
}
}
}
for(int i = 0; i < [self.index count]; i++)
{
if([temp[i] count] != 0){
NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:[self.index objectAtIndex:i], @"section_name", temp[i], @"data", nil];
[self.sectionData addObject:data];
}
}
[self.tableView reloadData];
    self.title = [self.subData objectForKey:@"Team"];
[super viewWillAppear:animated];
}

10. SubViewController. m  파일에  섹션을 만드는 메서드 재정의
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
return [self.sectionData count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSDictionary *Dic = [self.sectionData objectAtIndex:section];
NSString *sectionName = [Dic objectForKey:@"section_name"];
return sectionName;
}

11. SubViewController. m  파일에  셀을 만드는 메서드 재정의
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    NSDictionary *Dic = [self.sectionData objectAtIndex:section];
NSMutableArray *ar = [Dic objectForKey:@"data"];
return [ar count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    
    NSDictionary *Dic = [self.sectionData objectAtIndex:indexPath.section];
NSMutableArray *ar = [Dic objectForKey:@"data"];
cell.textLabel.text = [ar objectAtIndex:indexPath.row];
   
    return cell;
}

12. SubViewController. m  파일에  인덱스를 만드는 메서드 재정의
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.index;
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
for(int i = 0; i < [self.sectionData count]; i++)
{
NSDictionary *Dic = [self.sectionData objectAtIndex:i];
NSString *sectionName = [Dic objectForKey:@"section_name"];
if([sectionName isEqualToString:title])
{
return i;
}
}
return -1;
}






Posted by windship
프로그래밍/Objective-C2010. 7. 20. 10:56

KT앱 대회 준비하면서 모은 자료들을 정리해서 올립니다.
거의 맥부기 카페 자료들이 대부분인데 한곳에 모아서 찾아보기 쉬우라고 올려봅니다.

-푸쉬  서버  개발  관련 자료-
이지 APNS 오픈 소스 라이브러리
http://www.easyapns.com/
구글 코드 APNS 오픈 소스
http://code.google.com/p/apns-php/
서버 튜토리얼
http://blog.boxedice.com/2009/07/10/how-to-build-an-apple-push-notification-provider-server-tutorial/


-label이나 textView에 현재 시간을 표시하고 싶습니다-
NSDate *t = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
NSString *timeStr = [formatter setDateFormat:@"HH:mm:ss"];
myLabel.text = timeStr;
...
[textView scrollRangeToVisible:NSMakeRange([textView.text length]-1, 1)];


-시뮬레이터 포토 라이브러리 자신의 이미지 추가 방법-
UIImage * sShot = [UIImage imageNamed:@"imageName.jpg"];
UIImageWriteToSavedPhotosAlbum(sShot, nil, nil, nil);


-네이게이션바 스타일 바꾸기-
http://cafe.naver.com/mcbugi/1241


-이미지 자르기 함수를 소개합니다. (UIImage)-

- (UIImage*)imageByCropping:(UIImage *)imageToCrop toRect:(CGRect)rect
{
CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], rect);
UIImage *cropped = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return cropped;
}
http://www.hive05.com/2008/11/crop-an-image-using-the-iphone-sdk/


-HTTP 라이브러리-
http://allseeing-i.com/ASIHTTPRequest/How-to-use


-json 관련-
라이브러리 http://code.google.com/p/json-framework/
json 투토리얼 http://iphonedevelopertips.com/networking/iphone-json-flickr-tutorial-part-1.html


-알럿 템플렛-
self.myAlertView = [ [UIAlertViewalloc]
initWithTitle:@"알림"
message:@"이메일을입력해주세요"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:@"확인", nil];
self.myAlertView.delegate = self;
[self.myAlertViewshow];


-푸쉬서버 구현을 위한 서버 인증서 pem 만들기-
애플 개발자 센터 apps ID 추가 (이때 와일드카드(*)는 사용하면 안됨)
키체인에서 개인 인증서 하나 만들어 애플 개발 센터에 등록
애플 개발센터에서 cert파일을 다운받아서 키체인으로 추가

키체인에서 내보내기로 p12파일로 저장

커맨드에서  p12파일을 pem파일로 변환
openssl pkcs12 -in quizers_dev_cert.p12 -out quizers_dev_cert.pem -nodes -clcerts


-전역변수를 사용해 보자...-
http://cafe.naver.com/mcbugi/55643


-JSON 2중 뎁스 이상 키 접근하기-
NSDictionary*feed =[self downloadPublicJaikuFeed];
// get the array of "stream" from the feed and cast to NSArrayNSArray*streams =(NSArray*)[feed valueForKey:@"stream"];
// loop over all the stream objects and print their titlesint ndx;
NSDictionary*stream;
for(ndx =0; ndx &lt; stream.count; ndx++){
        NSDictionary*stream =(NSDictionary*)[streams objectAtIndex:ndx];
        NSLog(@"This is the title of a stream: %@", [stream valueForKey:@"title"]); 
}


-배열 NSArray-
초기 데이터로 생성
NSArray *array = [[NSArray alloc] initWithobjects:추가할 객체들.. , nil];
 스트링으로 생성
NSArray *joins =(NSArray*)[result objectForKey:@"joins"];
길이 구하기
NSLog(@"Array size : %d " , sizeof(BUILDING_DATA) / sizeof(BUILDING_DATA[0]));


-NSString 클래스를 이용하여 문자을 넣자니 유니코드를 받아 초기화-
-(NSUInteger) UnicharLength:(const unichar*)str
{
unichar* pStr = (unichar*)str;
for( ; pStr[0] != nil ; pStr++ );
return (NSUInteger)(pStr - str);
}
[[NSString alloc] initWithCharacters:(원본문자열) length:[self UnicharLength:(원본문자열)]];


-랜덤 출력-
srandom(time(NULL));
value = random() % 100;
위처럼 하시면 0~99사이의 한수를 리턴합니다.
srandom(time(NULL)); 는 첨에 한번만 해주시면 됩니다.


-Code Sign error: Provisioning profile이 맞지 않을 때 변경 방법-
여러 장비에서 작업을 하거나 여러 프로젝트를 진행 중에 변경된 Provisioning profile이 적용되지 않아 Debug를 할 때 ”Code Sign error: Provisioning profile ‘3E6AA725-6534-46F8-B9CE-D19AC9FD854B’ can’t be found” 이런 오류가 발생하는 경우가 있는데요. 이럴 때 현재 사용중인 Provisioning Profiles로 프로젝트 세팅을 변경해주는 방법을 소개한 글(원문)이 있어서 공유합니다.

1. 실행중인 Xcode Project를 닫습니다.
2. Finder에서 프로젝트 폴더로 이동합니다.
3. 프로젝트 .xcodeproj 파일 선택하고 마우스 오르쪽 키를 눌러 '패키지 내용 보기'를 선택합니다.
4. 패키지 내용 보기를 통해 패키지 안에 있는 project.pbxproj 파일을 Xcode로 불러옵니다.
5. 검색을 통해 PROVISIONING_PROFILE 부분을 찾아 변경된 Provisioning profile 로 변경해줍니다.
6. 현재 Provisioning profile을 확인하려면 Organizer 창을 열어보면 알 수 있습니다.
7. Window > Organizer로 Organizer 창을 열고 왼쪽에 IPHONE DEVELOPMENT > Provisioning Profiles로 이동합니다.
8. 오른쪽에 있는 Profile Identifier를 복사해서 변경해주면됩니다.
9. 변경이 끝나면 project.pbxproj 저장하고 프로젝트를 열어 테스트합니다.


-아이폰 웹개발에서 디바이스 아이디 가져올수있나요?-
[[UIDevice currentDevice] uniqueIdentifier];



-Accessing Objects in a NSArray-
To access an object in an NSArray, you use the -objectAtIndex: method, as in the following example:NSArray *numbers;
NSString *string;

numbers = [NSArray arrayWithObjects: @"One", @"Two", @"Three", 
                                     nil];
string = [numbers objectAtIndex: 2];   // @"Three"

Of course, you have to be careful not to ask for an object at an index which is negative or bigger than the size of the array; if you do, an NSRangeException is raised (we'll learn more about exceptions in another tutorial).
To get the length of an array, you use the method -count, as in:
NSArray *numbers;
int i;

numbers = [NSArray arrayWithObjects: @"One", @"Two", @"Three", 
                                     nil];
i = [numbers count];   // 3


-상태바 제어-
안 보이게
[UIApplication sharedApplication].statusBarHidden = NO;

스타일
UIApplication *myApp = [UIApplication sharedApplication];
[myApp setStatusBarStyle:UIStatusBarStyleBlackOpaque];


-메모리 오버되어서 어플이 죽는 경우에 호출되는 이벤트??-

뷰컨트롤러 베이스로 작업을 한다면

- (void)didReceiveMemoryWarning

함수로 메모리가 위험할시에 위 함수를 핸들링하니 내부에 관련 대응할 처리를 구현해주면 됩니다.



-D-Day 구하기-
NSDate* date  = [NSDatedateWithNaturalLanguageString:@"2010-06-30"];
NSDate* d_day = [NSDatedateWithNaturalLanguageString:@"2010-12-31"];

NSDateComponents *dcom = [[NSCalendar currentCalendar]components: NSDayCalendarUnit
fromDate:date  
  toDate:d_day  
  options:0];

NSLog(@"day=%d",   [dcom day]);   // 184


-라디오 버튼이나 체크박스등을 찾지를 못하고  있는데-
Interface Builder 에서 library를 보시면 segmented control, switch가 보일겁니다.
말씀하시는 라디오버튼이나 체크박스는 없지만  
라디오버튼은 segmented control로 대체, 체크박스는 switch 로 대체하셔서 사용하시면 될듯합니다.


-책장 넘기기 효과-
UIView 를 하나 만들고 그 안에 UIImageView 를 만들었습니다.
이제 이미지뷰어의 내용을 채울때 책장을 넘기듯이 넘기는 방법입니다.

[UIView baginAnimations:@"stalker" context:nil]; <- stalker 는 UIView 의 이름입니다
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:stalker cache:YES];
[UIView setAnimationDuration:1.0];
imageView.image = [UIImage imageNAmed:이미지파일명];
[UIView commitAnimations];

이 걸 터치 이벤트나 이런곳에 삽입하면
책장을 넘기듯이 이미지의 전환이 일어납니다. 


-image를 fade out 효과-
[UIView beginAnimations:nil context:NULL];
[imageView setAlpha:0.0];
[UIView commitAnimations]; 


-UIView Animation 중복방지-
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveLinear]; 
....
[UIView setAnimationDelegate:self]; 
[UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];
        [UIView commitAnimations];

이런 식으로 에니메이션을 만들었는데 간단하게 UIImageView를 한점에서 다른 한점으로 이동시킵니다.
근데 그래서 에니매이션이 끝나면 다시 또다른 다른 두 좌표로 해서 위의 코드가 실행되서 계속해서 UIImageView를 움직이게 하고 있습니다.

근데 질문은 1. setAnimationDidStopSelector 에서 에니매이션이 끝난것을 알기전에 강제로 에니메이션을 멈출수 있나요?
2. 제 경우에는 어떤 경우에 위 코드가 setAnimationDidStopSelector 가 호출되었을때 만 실행되는 것이 아니라 다른 부분에서도 호출하기도 합니다.  근데 문제는 동시에 위 코드가 중복되어서 호출되면 이상하게 작동해요.  그래서 꼭 위 코드를 실행(에니매이션을 commit 하기전에는 반드시 에니메이션을 강제로 멈추던지 아니면 다른 체크를 해야 할것 같은데.....  

혹시 방법이 있으면 부탁드립니다.

꾸벅~

답글 : 
[UIView setAnimationsEnabled:NO];
// 에니메이션을 종료 합니다. 


-일정시간 딜레이 후 함수 호출-
[self performSelector:@selector(playerStop) withObject:nil afterDelay :1.0f];

-(void) playerStop 
{
}


-개발 완료, 베타 테스팅용 Ad Hoc 배포-
http://cafe.naver.com/mcbugi/9042


-테이블뷰에 원격이미지를 넣을경우 스크롤이 느려지는 현상-
LazyTableImages 샘플http://developer.apple.com/iphone/library/samplecode/LazyTableImages/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009394
AsyncImageView 클래스 http://www.markj.net/iphone-asynchronous-table-image/


-테이블 뷰 섹션별로 이름 주기-
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if( section == 0 ) {
return@"발행한퀴즈";
} elseif( section == 1 ) {
return@"참여한퀴즈";
} else {
return@"진행중인퀴즈";
}
}


-정사각형으로 사진을 CROP 하고, 썸네일 크기에 맞게 리사이즈-
먼저, 출처는 다음 기사입니다.
http://tharindufit.wordpress.com/2010/04/19/how-to-create-iphone-photos-like-thumbs-in-an-iphone-app/ 
 
iPhone 사진앨범의 특징은 가로나 세로가 긴 이미지라 할지라도,
정사각형으로 사진을 CROP 하고, 썸네일 크기에 맞게 리사이즈 시킵니다.
 
위의 기사의 내용을 나름대로 보기 편하게(?) 수정을 했습니다.
 
함수명 - makeThumbnailImage
파라미터 - 원본 이미지, 리사이즈없이 CROP만 할지 여부, 리사이즈할 정사각형 한변의 길이
리턴값 - CROP 및 리사이즈된 이미지
 
- (UIImage*) makeThumbnailImage:(UIImage*)image onlyCrop:(BOOL)bOnlyCrop Size:(float)size
{
 CGRect rcCrop;
 if (image.size.width == image.size.height)
 {
  rcCrop = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
 }
 else if (image.size.width > image.size.height)
 {
  int xGap = (image.size.width - image.size.height)/2;
  rcCrop = CGRectMake(xGap, 0.0, image.size.height, image.size.height);
 }
 else
 {
  int yGap = (image.size.height - image.size.width)/2;
  rcCrop = CGRectMake(0.0, yGap, image.size.width, image.size.width);
 }
 
 CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], rcCrop);
 UIImage* cropImage = [UIImage imageWithCGImage:imageRef];
 CGImageRelease(imageRef);
 if (bOnlyCrop) return cropImage;
 
 NSData* dataCrop = UIImagePNGRepresentation(cropImage);
 UIImage* imgResize = [[UIImage alloc] initWithData:dataCrop];
 
 UIGraphicsBeginImageContext(CGSizeMake(size,size));
 [imgResize drawInRect:CGRectMake(0.0f, 0.0f, size, size)];
 UIImage* imgThumb = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();
 [imgResize release];
 return imgThumb;
}

위 소스를 참고하시면, 이미지를 CROP 하는 방법이나, 이미지를 RESIZE 하는 방법을 참고하실수 있을겁니다.
 
사족을 붙이자면, 왜 Resize 할지 여부를 따로 분리 시킨 이유는 실제로 사용을 해보면 Resize 루틴에서
많은 CPU 부하가 걸립니다. 그래서 UIImageView 에  contentMode를 UIViewContentModeScaleAspectFit 로 설정해서
자체적으로 리사이즈를 하게 하는 방법이 비동기적으로 괜찮습니다. (물론.. 실제 Resize된 이미지가 아니므로 메모리적인 소비는 있습니다.)
 
많은 도움 되셨으면 좋겠네요 ^^


-사진찍을때  아래에서  올라오는  메뉴 UIActionSheet-
http://ykyuen.wordpress.com/2010/04/14/iphone-uiactionsheet-example/


-uibutton disable-
http://www.iphonedevsdk.com/forum/iphone-sdk-development/2499-uibutton-disable.html


-이미지  슬라이드  샘플-
http://lievendekeyser.net/index.php?module=messagebox&action=message&msg_id=1351


-커버플로우  라이브러리-
http://apparentlogic.com/openflow/


-Xcode3.2.3과 SDK4로 업그레이드 후, 기존 앱 업그레이드 하는 법-
XCode3.2.3 과 SDK4로 버전업한 후, 기존 앱을 업그레이드 할 때 간단한 Tip 입니다.
1. XCode3.2.3과 SDK4로 업그레이드 한다. 별도로 기존 XCode 3.1 버전을 따로 보관할 필요가 없습니다.
2. 기존 앱을 새 XCode3.2.3에서 연다.
3.Group & Files를 right click -> Get Info 후
  3-1.General Tab 에서
Project Format 을 Xcode 3.2-compatible 로 바꾼다.
 3-2.Build Tab 에서
 Base SDK를 iPhone Device 4.0(배포시), 혹은 iPhone Simulator 4.0(테스트시) 로 바꾼다
 iPhone OS Deployment Target 을 iPhone OS 3.0 (즉 지원하고자 하는 하위버전으로) 로 바꾼다.
이렇게 하시면 됩니다.


-객체 타입 비교-
if ( [a isKindOfClass:b] )


-문자열 비교-
NSString *strText = idField.text;
if([srText isEqualToString:@"mihr01"])
....
else if([srText isEqualToString:@"mihr02"])
....
else
...
이렇게 하셔도 되고요 완전 같은 스트링이 아니라
 
포함된것을 찾으려면
if([strText rangeOfString:@"mihr01"].length) 


-탭뷰에 스타일시트를 붙일때-
UIActionSheet *popupQuery = [[UIActionSheetalloc]
initWithTitle:nildelegate:self
cancelButtonTitle:@"취소"
destructiveButtonTitle:nil
otherButtonTitles:@"사진찍기", @"기존의사진선택", nil];
popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque;
QuizersAppDelegate *appDelegate = (QuizersAppDelegate *)[[UIApplicationsharedApplication] delegate];
[popupQuery showInView:appDelegate.window];


-스크롤  밀어서  데이터  리플래쉬  하기-
소스코드
http://github.com/facebook/three20/tree/master/samples/TTTwitter/
설명
http://www.drobnik.com/touch/2009/12/how-to-make-a-pull-to-reload-tableview-just-like-tweetie-2/


-테이블뷰 위에 검색창 붙이는 방법-
테이블뷰 위에 검색창 넣으신 후에, viewDidLoad 메서드 부분에 [table setContentOffset:CGPointMake(0.0, 44.0) animated:NO];해주시면 처음 보여질 때는 검색창이 안 보이다가 밑으로 땡기면 나타나게 됩니다.


-네트워크  연결  됐는지  확인 Reachability-
http://www.raddonline.com/blogs/geek-journal/iphone-sdk-testing-network-reachability/
http://theeye.pe.kr/entry/how-to-check-network-connection-on-iphone-sdk



-아이폰 강제종료 버튼 이벤트-
아래 메소드가 어플이 종료될 때 수행되는 함수입니다.
종료될 때에 각종 리소스들을 Free시킬 경우에 사용됩니다.
참고하시면 될 듯 합니다~
 - (void)applicationWillTerminate:(UIApplication  *)application



-크랙 방지 클래스-
http://cafe.naver.com/mcbugi/11661



-어플을 강제 종료하는 API 는 아이폰에서 제공하지 않는다?-
http://cafe.naver.com/mcbugi/11803



-탭바 클릭시 바로 UISearchBar 클릭되도록 할려면 어떻게 해야 하나요?-
UISearchBar가 first responder가 되게 하면 됩니다.
[searchBarObj becomeFirstResponder];



-UITextField 입력값 체크하기 : 문자열 길이, 숫자여부 체크-

헤더(.h)에 UITextFieldDelegate 선언

@interface 클 래스명 : UIViewController <UITextFieldDelegate>



구현부(.m)에 다음 메쏘드를 구현하면 됨

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { 

//return NO하면 입력이 취소됨
//return YES하면 입력이 허락됨
//textField 이용해서 어느 텍스트필드인지 구분 가능

//최대길이

int maxLength = 128;

NSString *candidateString;

NSNumber *candidateNumber;


//입력 들어온 값을 담아둔다

candidateString = [textField.text stringByReplacingCharactersInRange:rangewithString:string];


if(textField == IDField) {
maxLength = 8;
} else if(textField == AgeField) {
//숫자여부 점검

//length가 0보다 클 경우만 체크
//0인 경우는 백스페이스의 경우이므로 체크하지 않아야 한다

if ([string length] > 0) {

//numberFormatter는 자주 사용할 예정이므로 아래 코드를 이용해서 생성해둬야함

//numberFormatter = [[NSNumberFormatter allocinit];

//[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];


//numberFormatter 를 이용해서 NSNumber로 변환

candidateNumber = [numberFormatter numberFromString:candidateString];


//nil이면 숫자가 아니므로 NO 리턴해서 입력취소

if(candidateNumber == nil) {

return NO;

}


//원 래 문자열과 숫자로 변환한 후의 값이 문자열 비교시 다르면

//숫자가 아닌 부분이 섞여있다는 의미임

if ([[candidateNumber stringValuecompare:candidateString] != NSOrderedSame) {

return NO;

}


maxLength = 2;

}

}

//길이 초과 점검

if ([candidateString length] > maxLength) {

return NO;

}


return YES;

}

http://cafe.naver.com/mcbugi/37651



-How to split string into substrings on iPhone?-
http://stackoverflow.com/questions/594076/how-to-split-string-into-substrings-on-iphone



-메모리 누수-
http://cafe.naver.com/mcbugi/64257


-디바이스 가로 세로 상태-
UIDeviceOrientationIsLandscape([UIDevicecurrentDevice].orientation) ?


-UITextField 에 자동 포커스 주기-
키보드 올리면서 커서를 넣을때는 아래방법을 이용하시면 됩니다.
[textField becomeFirstResponder]; 
참고로 이건 커서를 빼면서 키보드를 내리실때 사용하시면 되구요...
[textField resignFirstResponder]; 


-홈버튼이 눌렸을 때도 텍스트뷰 내용을 저장하려면 어떻게 해야할까요?-
- (void)applicationWillTerminate:(UIApplication *)application / Application Delegate 메서드 부분에 구현하시면 되지않을가요? 


-3.2 4.0  동영상  플레이-
http://iphonedevelopertips.com/video/getting-mpmovieplayercontroller-to-cooperate-with-ios4-3-2-ipad-and-earlier-versions-of-iphone-sdk.html


-한글완성형(EUC-KR)을 iPhone/Mac에서 사용할 수 있는 언어셋으로 변환하기-
http://blog.backpackholic.tv/160


-인터페이스 함수들을 편하게 가져오는 방법-
http://code.google.com/p/xcode-auto-assistant/


-#pragma mark로 코드 쉽게 구분하기-
http://cafe.naver.com/mcbugi/64408


-os4에서 applicationWillTerminate가 안먹어서 알게된것-
os4에서 applicationWillTerminate: 가 안먹어서 삽질하다가 알아낸 결과입니다.
뒷북 인지는 모르지만 혹시 모르시는 분을 위해서 적어봅니다.
os3.x 에서는 홈버튼을 한번만 누르면 applicationWillTerminate 가 아주 잘 호출됩니다.
하지만 os4 에서는 홈버튼을 한번만 누르면 
applicationDidEnterBackground 가 호출됩니다.
os4 에서 멀티태스킹을 위해서 좀 바뀌었습니다.
os4에서도 홈버튼 한번 누를때 applicationWillTerminate 가 호출되게 하려면
info.plist 에서 'Application does not run in background' 이 속성을 추가해주면 됩니다.
위 속성이 없으면 기본적으로 멀티태스킹이 되는걸로 간주합니다. (진짜 멀티태스킹은 아니지만)
위 속성이 없을때 호출되는 메소드를 실험해 봤습니다.
-----------------------------------------------------------------
처음 어플을 실행시키면
     didFinishLaunchingWithOptions, 
applicationDidBecomeActive 
이 호출되고
홈버 튼을 한번 만 누르면
applicationWillResignActive, 
applicationDidEnterBackground
호출되면서 어플이 종료되고
이상태에서 다시 어플을 실행시키면
applicationWillEnterForeground, 
applicationDidBecomeActive 
호출됩니다.
홈버튼을 두번 누르면
applicationWillResignActive
이 호출됩니다.
----------------------------------------------------------------
'Application does not run in background' 을 체크하면
홈버 튼을 한번만 누르면 applicationWillTerminate 를 호출합니다.
'근데 속성 체크 안했을때 applicationWillTerminate 는 호출이 안되는건지 궁금하네요.
아시는 분 좀 알려주세요.

답글 : 
Applicationwillterminate함수 대신에 applicationDidENterBAckground 사용하라고하네여 이곳에서 공유자원해제나 사용자데이타 저장,타이머 무효화,어플상태정보등 저장을 하라고 합니다. http://cafe.naver.com/mcbugi/65497


-COCOS2D 번개 효과-
http://www.cocos2d-iphone.org/forum/topic/370


-iPhone 4.0 호환 키보드에 버튼 or 뷰 붙이기-
기존꺼에 비해 약간 수정되 었을뿐입니다....
하지만 -_-이거 찾느라 ㅠㅠ;; 

3.1.x에서는 windows 서브뷰에 항상 키보드 뷰가 있었지만 ...
4.0 부터는 windows 에 항상 있는게 아니고, 키보드를 불렀을때 -_- 붙어서 오더라고요.. 그래서

Done 버튼 붙이는 예제 입니다. (Number 패드에)

아래 액션을 Text필드의 BeginTouched 에 연결 시킵니다.
 // 키보드가 나왔을때랑 사라질때의 이벤트를 잡아냅니다.
//3.1.X 에서는 UIKeyboardWillShowNotification 으로 잡지만
// 4.0 때문에 --; DidShow로 잡아줬습니다.
//그래야 윈도우에 키보드가 있더라고요 ;;;
-(IBAction)FieldTouched{
    
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillShow:) 
                                                 name:UIKeyboardDidShowNotification
                                               object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillHide:) 
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
    
    
}

// 키보드가 나왔을때 Done 버튼 붙여주기 
- (void)keyboardWillShow:(NSNotification *)note {  
    
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
    doneButton.frame = CGRectMake(0, 163, 106, 53);
    doneButton.adjustsImageWhenHighlighted = NO;
    [doneButton setImage:[UIImage imageNamed:@"DoneUp.png"] forState:UIControlStateNormal];
    [doneButton setImage:[UIImage imageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted];
    [doneButton addTarget:self action:@selector(backgroundTap:) forControlEvents:UIControlEventTouchUpInside];

    //3.1.x 와 4.0 호환 키보드 붙이기
    for( UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows] ){
        for( UIView *keyboard in [keyboardWindow subviews] ){
            NSString *desc = [keyboard description];
            if( [desc hasPrefix:@"<UIKeyboard"]==YES ||
               [desc hasPrefix:@"<UIPeripheralHostView"] == YES ||
               [desc hasPrefix:@"<UISnap"] == YES )
            {
                [keyboard addSubview:doneButton];
            }
        }
    }
    
}

// 키보드가 없어질때 Done 버튼을 삭제 합니다.
- (void)keyboardWillHide:(NSNotification *)note {  
    
    for( UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows] ){
        for( UIView *keyboard in [keyboardWindow subviews] ){
            NSString *desc = [keyboard description];
            if( [desc hasPrefix:@"<UIKeyboard"]==YES ||
               [desc hasPrefix:@"<UIPeripheralHostView"] == YES ||
               [desc hasPrefix:@"<UISnap"] == YES )
            {
                for(UIView *subview in [keyboard subviews])
                {
                    [subview removeFromSuperview];
                }
                
            }
        }
    }
}

도 움 되시길 바랍니다 ;)
http://cafe.naver.com/mcbugi/62349


-배열내 숫자 값 비교해서 정렬하기-
만약에 객체내의 인스턴스를 키로 정렬할 경우에는 NSSortDescriptor 를
쓰시면 됩니다.
아래는 name으로 정렬한 예입니다.

@interface Test :
NSObject {
NSString *name;
double distance;
}
@property
(nonatomic, retain) NSString *name;
@property double
distance;
@end

@implementation Test
@synthesize name, distance;
@end


아 래는 사용방법입니다.
       Test *t1 = [[Test alloc] init];
Test *t2 = [[Test alloc] init];
Test *t3 = [[Test alloc] init];
[t1 setName:@"마바사"];
[t2 setName:@"아자차"];
[t3 setName:@"가나다"];
[t1 setDistance:1.2];
[t2 setDistance:2.5];
[t3 setDistance:0.5];
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:t1];
[array addObject:t2];
[array addObject:t3];
[t1 release];
[t2 release];
[t3 release];
// 이름순으로 정렬
NSSortDescriptor *nameSort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(localizedCompare:)];
[array sortUsingDescriptors:[NSArray arrayWithObjects:nameSort, nil]];
[nameSort release];
for(Test *t in array) {
NSLog(@"%@ %f", [t name], [t distance]);
}
[array removeAllObjects];


------[결 과]------
2010-07-12 17:46:13.117 Sort[5070:20b] 가나다 0.500000
2010-07-12 17:46:13.125 Sort[5070:20b] 마바사 1.200000
2010-07-12 17:46:13.130 Sort[5070:20b] 아자차 2.500000


p.s. distance로 정렬하고자 한다면 
NSSortDescriptor *distanceSort = [[NSSortDescriptor alloc] initWithKey:@"distance" ascending:YES];
nameSort 대신 distanceSort를 넣으시면 됩니다.
http://cafe.naver.com/mcbugi/65873


-[TIP] 시뮬레이터 사진앨범에 사진넣기-
1) 시뮬레이터를 실행시킵니다.

2) 맥에서 포토라이브러리에 넣을 사진을 시뮬레이터로 Drag&Drop 합니다.

3) 그러면, 사파리가 열리면서 Drag한 이미지가 표시가 될겁니다.

4) 그 표시된 이미지를 마우스로 꾸~~~~~~욱 눌러줍니다.

5) 그러면, 메뉴가 뜨면서 이미지를 저장할건지 복사할건지를 묻습니다.

6) 이미지 저장을 누릅니다.

7) 이제 시뮬레이터의 사진앨범에 가 보시면 아까 저장한 사진이 들어가있을겁니다.


---


출처 : http://cafe.naver.com/mcbugi/67700

Posted by windship
프로그래밍/Objective-C2010. 7. 20. 10:53

코드가 길어질 수록 원하는 메소드를 찾아가기가 함든 경우가 많습니다.
이럴때 #pragma mark를 이용해서 코드를 쉽게 구분하고 찾아갈 수 있습니다.

 

예를 보겠습니다.

이 소스는 ADC에서 받은 Touches라는 프로젝트입니다.

 

젤 위에 세줄을 보시면  #pragma mark를 사용한걸 볼 수 있습니다.

 

Navigation Bar를 보시면 이것의 용도를 알 수 있습니다.

 

 

Navigation Bar에서 ===Animating subviews=== 라는 항목으로 구분되어서 두개의 메소드가 표시되는 걸 볼 수 있습니다.

즉 ...

#pragma mark - 는 구분용 실선

#pragma mark ===Animating subviews=== 는 항목명 출력

#pragma mark   는 그냥 빈 공간용 입니다.

 

 

좀 더 이해하기 쉽게 세줄을 주석처리 해보면

 

이렇게 몽땅 붙어서 나오게 되죠.

 

#pragma mark를 써서 코딩할때 관련된 메소드들을 잘 모아서 묶어둔다면 훨씬 보기 좋고 관리하기 좋을 것 같습니다.

전 아직 이렇게 긴 코드를 짤 수준까진 안되지만 지금부터 습관을 들여야 될 것 같네요 ^^

 

 

참고로 #pragma mark - 뒤에 공백을 넣으면 안됩니다.

 

 

공백이 들어가게 되면 위와 같이 됩니다.

그리고 Preferences... > Code Sense의 Sort list alphabetically  항목이 체크되어 있으면  Navitation Bar에서 알파벳 순으로

메소드들을 정렬해서 보여줍니다. 위의 기능을 사용하고 싶으시면 이 항목을 체크하지 마세요. 디폴트는 체크되어있지 않습니다.

 

#pragma mark가 무슨 용도인지 찾아보다가 알게되었네요.

도움이 되셨으면 합니다~ ^^


---


출처 : http://cafe.naver.com/mcbugi/64408

Posted by windship
프로그래밍/Objective-C2010. 7. 16. 11:52
* 애니메이션의 또 다른 방법

  - CATransition : 다른 프레임워크를 사용
  - UICalloutView : 유저들이 만들어버린 것. 헤더파일 형태로 제공. 주로 풍선 도움말 같은 것을 만들 때 쓴다. 유저들이 만들었기 때문에 공식적인 애플의 SDK가 아니고, 각각의 소스마다 형태가 약간씩 다를 수 있다. 사실상 UIView에서 상속받아 만들어지는 형태가 대부분임.

* CATransition

  - Core Animation Transition의 약자임.
  - 뷰가 아니라 뷰를 담는 레이어에서 동작함
  - Quartz 코어 프레임워크에서 제공되므로 QuartzCore.framework를 링크하고, QuartzCore/QuartzCore.h 파일을 import 해주어야 함

* CATransition 타입

  - kCATransitionFade : 서서히 사라지는 효과. subtype 없음
  - kCATransitionMoveIn : 레이어가 미끄러지듯이 나타남. subtype으로 kCATransitionFrom의 방향을 지정할 수 있음
  - kCATransition

* 뷰 컨트롤러

  - 뷰 관리 모델을 담당하는 가장 기본적인 클래스
  - UITabBarController나 NavigationController도 이러한 UIViewController로 부터 상속 받아서 만들어진다
  - 프로퍼티
UIView *view: 화면에 출력될 뷰
UINavigationController *navigationController
UITaBarController *tabBarController
UIViewController *modalViewController
NSString * title     <- NavigationController에서는 제목으로 화면에 출력되며 일반적으로는 뷰의 이름입니다.

* 인터페이스 빌더를 써서 xib 파일에 만들어진 뷰(IBOutlet을 사용하는 뷰)는 awakeFromNib를 통해서 로드된다.

* 그냥 코딩으로 구현된 뷰(IBOutlet이 없는 뷰)는 loadView 메소드를 통해서 로드된다.

* 뷰 화면과 관련된 메소드

  - viewDidLoad : 뷰가 로딩된 후 호출
  - viewWillAppear:(BOOL)animated : 뷰가 화면에 나타나기 직전에 호출
  - viewDidAppear:(BOOL)animated : 뷰가 화면에 나타나고 애니메이션이 종료된 후 호출
  - viewWillDisappear:(BOOL)animated : 뷰가 화면에서 사라지기 직전에 호출
  - viewDidDisappear:(BOOL)animated : 뷰가 화면에서 사라지고 난 후 호출

* 뷰의 방향 전환과 관련된 메소드

  - (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
  - 이 메서드의 return 값이 YES이면 방향 전환을 지원하고 NO이면 지원하지 않는다
  - UIInterfaceOrientation은 회전 방향 열거형이다
  - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration : 방향 전환이 이루어지기 직전에 호출되는 메소드
  - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation : 방향 전환이 끝난 후 호출되는 메소드

* Touch 이벤트

   - UIResponder로부터 상속받는 모든 객체에서 발생하는 이벤트. 메소드 재정의만 하면 사용 가능하다
   - UITouch: 터치에 관련된 정보를 저장하기 위한 클래스로 아래와 같은 멤버를 소유하고 있다
NSTimeInterval timestamp: 터치가 발생한 시간을 저장하는 프로퍼티(readonly)
UITouchPhase phase: 터치의 상태를 저장하는 프로퍼티(readonly)로 값은 UITouchPhaseBegan, UITouchPhaseMoved, UITouchPhaseStationary, UITouchPhaseBeganEnded, UITouchPhaseCancelied
NSUInteger tapCount: 터치 한 횟수
UIView *view: 터치가 최초로 발생한 뷰
UIWindow *window: 터치가 최초로 발생한 윈도우
(CGPoint)locationView:(UIView *)view     <– view좌표계에서 터치한 위치
(CGPoint)previousLocationView:(UIView *)view      <– view좌표계에서 터치한 이전 터치의 위치 정보

   - UIEvent: 하나 이상의 터치 정보를 가지고 있는 클래스로 UITouch 객체들을 NSSet 의 형태로 저장해서 반환하며 아래와 같은 프로퍼티와 메서드 소유
NSTimeInterval timestamp: 터치가 발생한 시간을 저장하는 프로퍼티(readonly)
-(NSSet *)allTouches: 모든 UITouch 객체
-(NSSet *)touchesForWindow:(UIWindow *)window: window에서 발생한 모든 터치 객체

  - UIResponder의 터치 이벤트 메서드
- (void)touchedBegan:(NSSet *) touches withEvent:(UIEvent *)event;  <- 터치가 시작할 때 발생
- (void)touchedMoved:(NSSet *) touches withEvent:(UIEvent *)event;  <- 터치해서 이동하는 중에 발생
- (void)touchedEnded:(NSSet *) touches withEvent:(UIEvent *)event;  <- 터치를 마치면 발생
- (void)touchedCancelled:(NSSet *) touches withEvent:(UIEvent *)event;  <-터치 중 시스템 이벤트가 발생한 경우 발생

  - 멀티 터치는 객체의 MultipleTouch 속성이 YES 일 때만 가능
 
  - 멀티 터치를 지원하기 위해서는 view의 User Interaction Enabled 속성이 YES, Multiple Touch 속성이 YES 여야 한다




Posted by windship
프로그래밍/Objective-C2010. 7. 15. 09:45
* 스크롤 뷰

  - 컨텐츠 사이즈가 뷰 사이즈보다 클 경우 스크롤 기능을 이용해서 보여줄 수 있는 뷰
  - 자체적으로 줌 기능을 가지고 있기 때문에 한번에 보여주는 크기인 Frame 사이즈와 전체의 컨텐츠 크기인 ContentsSize 2가지의 사이즈를 설정해야 한다
  - 인터페이스 빌더는 기본 뷰 이상의 크기를 편집할 수 없기 때문에 스크롤 뷰는 인터페이스 빌더로 설정하기 어렵다(코딩으로 만든다)
  - 항상 setScrollEnabled 속성을 Yes로 주어야만 스크롤이 가능해진다 <-- 주의!
  - 이미지의 사이즈는 직접 계산할 필요가 없다. Xcode의 Resources에만 등록해 두면 알아서 크기와 사용 용량을 알아서 구한다

  - 예제 1: 스크롤 없음
-(void)loadView 
{
 UIImage* image = [UIImage imageNamed:@"tri2.jpg"];  // 이미지 파일로 UIImage 객체를 생성
 UIImageView * imageView = [[UIImageView alloc]initWithImage:image];  // UIImage 객체를 기반으로
                                                                                     // UIImageView 객체를 생성
                                                                                     // (frame - (0,0,가로크기,세로크기)
 [imageView setUserInteractionEnabled:YES];  // ImageView가 사용자의 터치 이벤트를 받을 수 있도록 설정
                                                                   // (없으면 터치 이벤트 사용 못함)  <-- 중요!
 [image release];  // UIImage 객체를 release. viewController나 view는 다른 객체
 self.view = imageView;
 [imageView release];
}

  - 예제 2: 스크롤 가능
- (void)loadView 
 {
UIImage* image = [UIImage imageNamed:@"tri2.jpg"];
UIImageView * imageView = [[UIImageView alloc]initWithImage:image];
[imageView setUserInteractionEnabled:YES];
CGSize imageSize = [image size];
[image release];
CGRect rect;
rect.origin.x = 0;
rect.origin.y = 0;
rect.size.width = 320;
rect.size.height = 480;
UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:rect]; // ScrollView를 한번에 보여주고자 
                                                                                                         // 하는 크기만큼으로 설정
[scrollView setScrollEnabled:YES]; // 스크롤을 가능하도록 설정
[scrollView setContentSize:imageSize]; // 전체 컨텐츠 크기를 대상 이미지 크기만큼으로 설정
[scrollView addSubview:imageView]; // 스크롤뷰에 출력할 컨텐츠를 설정
[imageView release];
self.view = scrollView; // 현재 뷰는 스크롤 뷰로 설정
[scrollView release];
 }

  - 줌 기능을 사용하려면 줌의 최대, 최소 사이즈를 추가로 지정해 주어야 한다
  - delegate에 메소드를 가지고 있는 객체를 지정해 줘야 하며, UIScrollViewDelegate 프로토콜을 따른다
  - 뷰는 가만히 있지만 그 안에 보여지는 컨텐츠가 줌을 수행하는 것

  - 예제 3: 줌 기능 추가
~~~ViewController.h 파일

#import <UIKit/UIKit.h>

@interface _715_1ViewController : UIViewController <UIScrollViewDelegate> 
{
UIImageView * returnView;
}

@end

~~~ViewController.m 파일 #1

- (void)loadView 
 {
UIImage* image = [UIImage imageNamed:@"tri2.jpg"];
UIImageView * imageView = [[UIImageView alloc]initWithImage:image];
[imageView setUserInteractionEnabled:YES];
CGSize imageSize = [image size];
[image release];
CGRect rect;
rect.origin.x = 0;
rect.origin.y = 0;
rect.size.width = 320;
rect.size.height = 480;
 UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:rect]; // ScrollView를 한번에 보여주고자 
                                                                                                         // 하는 크기만큼으로 설정
[scrollView setScrollEnabled:YES]; // 스크롤을 가능하도록 설정
[scrollView setContentSize:imageSize]; // 전체 컨텐츠 크기를 대상 이미지 크기만큼으로 설정
[scrollView addSubview:imageView]; // 스크롤뷰에 출력할 컨텐츠를 설정
 
scrollView.maximumZoomScale = 2.0f;
scrollView.minimumZoomScale = 0.5f;
 
scrollView.delegate = self;
 
returnView = [imageView retain];
 
[imageView release];
 
self.view = scrollView; // 현재 뷰는 스크롤 뷰로 설정
 
[scrollView release];
 }

-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return returnView;
}

~~~ViewController.m 파일 #2

UIImage* image = [UIImage imageNamed:@"tri2.jpg"];
UIImageView * imageView = [[UIImageView alloc]initWithImage:image];
returnView = [imageView retain];
[imageView setUserInteractionEnabled:YES];
CGSize imageSize = [image size];
[image release];
CGRect rect;
rect.origin.x = 0;    rect.origin.x = 0;
rect.size.width = 320;  rect.size.height = 480;
UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:rect];
[scrollView setScrollEnabled:YES];
[scrollView setContentSize:imageSize];
[scrollView addSubview:imageView];
[scrollView setMaximumZoomScale:2.0];
[scrollView setMinimumZoomScale:0.5f];
[scrollView setDelegate:self];
[imageView release];
self.view = scrollView;
[scrollView release];

-(UIView*)viewForZoomingInScrollView:(UIScrollView*)scrollView
{
return returnView;
}


* UIView Animation

  - 위치변화, 크기변화, 투명도변화, 회전 등이 가능
  - +(void)beginAnimations:(NSString *)animationID context:(void *)context    <-- 시작 구문
  - +(void)commitAnimations   <-- 종료 구문
  - 위 2개 메소드 사이에 애니메이션의 효과를 지정하면 된다
Posted by windship
프로그래밍/Objective-C2010. 7. 14. 09:38
* View의 생성방법

  1. 코드로 생성하는 방법  
     - UIView * 객체명 = [[UIView alloc]initWithFrame : (CGRect)rect];
        rect 부분은 CGPoint Origin(CGFloat x, y), 또는 CGSize Size(width, height) 등으로도 가능
     - [window 객체 addSubview : 뷰 객체명];
     - 코드로 생성시, xib 파일을 사용하는 부분이라면 m 파일의 loadview 부분에서 생성하면 안되고 viewDidLoad 부분에서 해야 한다.

- (void)viewDidLoad 
{
UIButton * button = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 150, 30)];

[button setTitle:@"버튼" forState:UIControlStateNormal];   // 버튼의 초기 타이틀 설정. 

[self.view addSubview:button];   // 버튼을 현재 뷰 컨트롤러의 뷰의 서브뷰로 초기화함
[button release];    // SubView가 NSArray * 타입이라서 추가나 제거가 될 때 
                                    // retain과 release를 자동으로 수행하게 된다.
                            // 따라서 임시 변수를 이용해서 대입했다면 반드시 release를 해야 한다.
[button addTarget:self action:@selector(redView) forControlEvents:64];    // 버튼의 TouchUpInside  
                                                                                                                   // 이벤트에 redView 메소드를 
                                                                                            // 연결
    [super viewDidLoad];
}

-(void)redView
{
self.view.backgroundColor = [UIColor redColor];
}

  2. 인터페이스 빌더로 생성하는 방법
     - 인터페이스 빌더로 뷰를 생성하고 IBOutlet으로 멤버 변수와 연결한다
     - 만들기는 가장 쉬우나 사후 관리가 귀찮음

  3. UIView로부터 상속받는 클래스를 생성해서 사용자 정의 뷰를 만든 후 사용하는 것
     - 사람마다 필요로 하는 기능이 모두 조금씩 다를 수 있기 때문
     - 만들고자 하는 것이 기본적인 모양이 아닐 경우 이 방법을 사용해 만든다
     - 주로 테이블 뷰에 가장 많이 사용하게 된다(사람들마다 셀을 사용하는 형태가 다르기 때문)


* Objective-C의 콜렉션 : NSArray, NSDictionary, NSSet
  - 삽입이나 삭제시에 retain 과 release 이용


*  IBAction과 void는 기본적으로 같다. 인터페이스 빌더에서 인식하느냐 못하느냐의 차이일 뿐. 둘 다 리턴값이 없다.


* 인터페이스 빌더의 버튼 이벤트를 코딩으로 구현하려면 열거형으로 해서 값을 줘도 된다. (UIControlEvents 도움말에 잘나와있음)


* 앱 만들때 배경그림 까는 법
  - 인터페이스 빌더에서 Image View를 배경화면 크기로 깔아버리고 시작


* NSArray 오브젝트들의 배열

  1. 생성
    arrayWithObject : 객체
    arrayWithObjects : 객체 나열, nil
    arrayWithArray : 배열명

NSArray * ar = [NSArray arrayWithObjects : @"1", @"2", @"3", nil];
NSArray * ar1 = [NSArray arrayWithArray : ar];    <-- COPY이다.

ar1 = ar;
ar1 = [ar retain];      <-- 동작결과는 똑같지만 이게 더 좋은 방식. release에 있어서 더 자유롭다.

  2. 초기화
   array -> init
   공간은 있지만 데이터가 없는 경우임

  3. 추가 및 삭제
   -(NSArray *) arrayByAddingObject : 객체
   -(NSArray *) arrayByRemove : 객체

원래 3까지 있는 배열 ar을 만들고

[ar arrayByAddingObject : @"4"] <-- 이렇게 하면 가상본을 만들어서 4를 추가한다.
ar = [ar arrayByAddingObject : @"4"] 로 하여 다시 한번 ar에 집어넣어야 한다.

추가를 해서 처음에 정해진 배열크기보다 큰 부분에 데이터가 들어오면 자동적으로 원래 배열이 아니라 다른 곳에 큰 배열을 만들어서 추가해 버린다(위에서 말한 가상본). 실제 기기에서는 이런 부분이 메모리를 낭비하게 되어 아주 치명적인 누수를 일으킨다. 따라서 위의 방법은 사용하지 않는다.

NSArray * temp = [ar arrayByAddingObject : @"4"];
...
[ar release];

ar = [temp retain];
[temp release];

이것이 Objective-C에서 가장 일반적으로 배열을 만들고 추가/삭제를 하는 방법이다.

  4. 멤버 접근

   1) index 이용 :
      -(id)ObjectAtIndex:(id)index
      멤버 접근에 가장 쉽고 일반적인 방법

   2) Enumerator 이용:
      -(NSEnumerator *)ObjectEnumerator
      반복자. 어떤 형태의 멤버에든 접근하기 쉽게 하기 위해서 만들어진 것.
      배열은 규칙적으로 반복되기 때문에 읽기가 쉬우나, 실제 프로그램 작성시에는 그렇게 자료가 규칙적인 경우가 많지 않다.
      이 때문에 반드시 배워야 하는 개념이 Linked List. 이 경우에는 규칙적이지 않으므로 인덱스를 사용하지 못한다.
      무엇인가에 각각의 멤버의 주소만 전부 가지도록 하게 만들면 그 이후부터는 그것만으로 모든 멤버를 참조할 수 있다
      
NSEnumerator * 변수 = [ar ObjectEnumerator];

id sender;

while((sender = [변수 nextObject])!=nil)
{
...
}

   3) for ~ in 사용가능:

id sender;   // <-- 데이터 타입이 무엇이 들어있을지 모르기 때문에 대부분의 타입을 받을 수 있는 id 형을 사용

for(id sender in ar)

    자료들의 크기가 커지면 커질수록 속도면에서 유리해지는 방법이다.


  5. 배열의 요소 개수

    -(NSInterger) count



* 2차원 배열

  - Objective-C에서는 기본적으로 2차원 배열이 없다.
  - 때문에 2x2의 배열을 만든다고 할 경우는 이렇게 한다.

NSArray * ar1 = [NSArray arrayWithObjects: @"1", @"2", nil];
NSArray * ar2 = [NSArray arrayWithObjects: @"3", @"4", nil]; // 2개의 1차원배열을 만든 뒤

NSArray * ar = [NSArray arrayWithObjects: ar1, ar2, nil]; // 그 배열 2개를 모아 다른 배열을 선언

[ar1 release];
[ar2 release];

  - 주의

NSArray * copyAR = [NSArray arrayWithArray: ar];
ar = [ar arrayByAddingObject: ar3];
[[ar ObjectAtIndex: 0] arrayByAddingObject: @"10"];

  - 흔히 얕은 복사라고 함. 한번의 복사만을 해준다.
  - 이것을 방지하기 위해서는 메모리 상의 처리보다 파일처리 같은 외부 기억장소로 빼내서 처리하는 방법을 이용하는 것이 좋다


* ImageView

  - 이미지 한 장을 화면에 출력하기 위한 정적인 뷰. 이벤트 사용할 수 없다
  - Image 속성을 이용해 이미지 리소스를 연결한다
  - contentMode 속성으로 배치 모양을 결정한다
      UIViewContentModeScalToFill : 프레임의 긴 쪽에 맞춰서 확대/축소
      ScaleAspectFit : 작은 쪽에 맞춰줌 . 가로/세로 비율을 맞춰서 확대/축소

Posted by windship
프로그래밍/Objective-C2010. 7. 12. 09:29
* 컨트롤
  - UIKit가 제공하는 재사용 가능한 작은 부품
  - 일종의 뷰라고 할 수 있다
  - UIButton, UIDatePicker, UIPageControl, UISegmentControl, UITextField, UISlider, UISwitch...
  - 능동 컨트롤 : 사용자의 실제 이벤트를 연결하는 컨트롤. 일반적으로 버튼 등이 해당
  - 정적 컨트롤 : 
  - 수동 컨트롤 : 일반적으로 텍스트 필드 등이 해당

* UILabel
  - 정적 텍스트를 출력하기 위한 읽기 전용 뷰로 UIView로부터 상속. 컨트롤이 아님.
  - UIresponder로부터 상속받은 속성은 사용이 가능하지만 UIControl에 있는 이벤트는 사용 불가
  - 간단한 텍스트를 출력하기 위한 용도로 사용
  - lineBreakMode 프로퍼티가 중요. 출력 영역을 벗어났을 때의 처리.
  - numberOfLines : 몇줄까지 출력 가능한가라는 의미

* 타이머(NSTimer)
  - 일정 주기, 일정 시간에 대한 기능을 사용할 때 쓰는 클래스
  - NSTimer.h에 정의되어 있으나, Foundation에 포함되어 있으므로 기본적으로 인클루드는 안해도 된다.
  - +(id) scheduledTimerWithTimeInterval : 실행주기 Target : 수행할 메소드가 있는 객체 selector : @selector(수행할 메소드) userinfo : (id)부가 정보를 저장할 객체 repeats: (BOOL) 반복여부];
  - 수행할 메소드가 있는 객체 : 대개는 self
  - 수행할 메소드 : 시간이 되었을 때 수행할 명령. 매개변수도 없고 리턴값도 없어야 함
  - 반복여부 : yes / no
  - 타이머 종료시에는 invalidate 메소드를 호출해서 무효화시킴.

* 인터페이스 빌더로 만든 것은 dealloc으로 해제
* 프로퍼티를 만든 것은 synthersize로 해제

* UITextField
  - 사용자로부터 키보드 입력을 받기 위한 컨트롤
  - 문자가 아니라 숫자만 입력하면 될 경우는 Number Pad로 변경한다

* 키입력시 키보드가 화면을 가려버리는 문제의 해결
  1. 특정 키를 누를 때 키보드에 할당된 입력 이벤트를 강제로 회수해 버리면 된다
      - < UITextFieldDelegate>프로토콜을 따르도록 설정하고 (Bool)textFieldShouldReturn:(UITextField*)theTextField 메서드에서 매개변수가 resignFirstResponder 메서드를 호출
  2. Did End on Exit 이벤트를 이용
  3. 텍스트 필드에 이벤트가 발생할 때 버튼을 화면 위로 올리
  4. 뷰 클래스나 뷰 컨트롤러 클래스에서 터치 이벤트를 이용해서 텍스트 필드에서 FirstResponder를 해제


Posted by windship