출처 : 테스트주도개발 TDD 실천법과 도구

계약이란 개념은 로직의 선/후행 조건 같은 단순한 개념부터, 개발에 필요한 업무규칙, 고객의 요구사항에 이르기까지의 다양한 경우를 지칭한다. (null 크, 최소값 체크, 음수 체크)

방어 프로그래밍 - 발생 가능한 문제 상황에 대비해 점검하는 부분을 의심
계약에 의한 설계 - 신뢰에 의한 프로그램

즉 선언적인 형태로 프로그램의 상태를 구분하고, 이를 통해 작성된 로직의 간결성을 유지하면서도 작성자의 의도를 명확히 전달한다

방어 프로그래밍 테스트 케이스 예

public void testAccount(){
try {
wrongAccount = new Account(-10000);  // Account 클래스는 음수가 들어갈 경우 IlleagalArgumentException 발생)
assertTrue("계좌는 반드시 양수 이여야함", false);
} catch(IlleagalArgumentException e) {
assertTrue(true);
}
}
 
 위 경우  Account가 음수가 들어 갈 경우 예외 상황이 발생되어 catch가 되어 조건이 참이 되게 된다. (해당 예외가 발생이 안되면 false를 발생하게 됨) 즉 Account 객체의 음수가 아닌 음수에 따른 결과를 테스트하게 되는 것임.

계약에 의한 설계에 의한 테스트 케이스는 따로 테스트 케이스를 작성하기 보다는 실제로 값이 입력되는 부분에 assert라는 키워드를 통해 특정 상황(양수 값)의 상태를 확증하는데 사용된다.


'UML,OOP,Pattern, TDD' 카테고리의 다른 글

Strategy pattern VS Brigde Pattern  (0) 2011.10.09
TDD Tip  (0) 2011.04.19
객체지향 개발 관련 팁  (0) 2011.04.19
객체지향 개발 원칙  (0) 2011.04.19
UML Tip  (0) 2011.04.19
출처 : 테스트주도개발 TDD 실천법과 도구

TDD유의사항

테스트케이스는 이름이 중요하다.
더 이상 제대로 동작하지 않은 테스트 케이스는 제거한다.
TDD는 자동화된 테스트를 만드는 것이 최종 목표가 아니다.
모든 상황에 대한 테스트 케이스를 만들 필요는 없다
여러 개의 실패하는 테스트 케이스를 한 번에 만들지 않는다.
하나의 테스트 케이스는 하나만 테스트하도록 작성한다.
전통적인 테스트 기법을 배워둔다.
테스트 케이스는 최대한 고립시킨다.

TIP

1. 기능 테스트, 단위 테스트 구분

기능 테스트 - 사용자 관점의 테스트
단위 테스트 - 애플리케이션 관점의 테스트

기능 테스트는 외부 동작 위주로 진행되기 때문에 블랙박스 테스트로 볼수 있다. 하지만 일부 단위가 수정 되었을 때 오류가 발생되게 되면 해당 오류 단위를 추적하기 힘든 상황이 있다. 이럴 경우 단위 테스트가 잘 구성되어있다면 쉽게 오류난 부분을 찾는데 도움이 될 것이다.

2. 미리 예상할 수 없는 경우 TDD진행

임의의 값을 만들어 실패를 만들고 실패 때 나온 값을 결과값으로 현재 상태가 올바름을 알 수밖에 없다.  TDD는 사실 개발자가 특정 메소드를 호출했을 때 어떤 값이 리턴될지 알고 있다는 것을 사전조건으로 가정되어 있다.

3. 테스트 케이스 코드를 작성하기 어려울 때

코드가 불필요한 클래스와 의존관계가 있는지 확인한다. 의존성을 피할수 없는 경우 Mock객체를 사용하는 방법이 있지만 최솨한만 사용한다. 억지로 테스트를 작성하는 것은 잘못된 접근이다.

4. 테스트 케이스를 작성할 때 외부 모듈이 익숙지 않을 경우

위 경우 테스트 케이스 작성은 두가지로 나눌수 있다.

가. 라이브러리 학습을 위한 테스트 케이스 - 신뢰도 측정의 개념으로 테스트 케이스를 작성한다.
나. 업무 코드 작성을 위한 테스트 케이스 - 외부 모듈의 API를 배제하고 업무시나리오에 맞게 테스트 케이스를 작성한다. API는 재료로 사용하는 것이라는 생각으로 시나리오 베이스 테스트 케이스를 작성하면 수월하다

5. 수동 테스트 VS 자동화된 테스트

자동화는 지향해야하는 목표이다. 하지만 자동화하는데 많은 노력이 들어간다. 따라서 프로젝트 적당한 시기에 도입한다. 수동 테스트의 단점은 회귀 테스트가 부담이 될 것이다. 기능이 추가/변경 될 때마다 기능 테스트를 수행해야하는데 누락되거나 지나치게 단순화된 형태로 테스트를 진행하게 될 가능성이 커진다.

6. void 메소드를 테스트 할 경우

메소드를 아래와 같이 나눌 수 있다

리턴값이 있는 메소드 : 기능
void 메소드 : 절차

메소드의 리턴값이 없다는 의미는 로직의 절차를 기술했거나, 로직 트리의 맨 끝에 해당하는 기능 위임 작업을 목표로 하는 것을 의미한다. 이 경우 행위 기반 테스트를 해야한다. 가장 간단한 방법은 상태를 확인 할수 있는 다른 메소드로 결과를 테스트 하는 것이다. (isClicked, isReady 등)

'UML,OOP,Pattern, TDD' 카테고리의 다른 글

Strategy pattern VS Brigde Pattern  (0) 2011.10.09
TDD - 계약에 의한 설계(DbC, Design by Contract)  (0) 2011.04.19
객체지향 개발 관련 팁  (0) 2011.04.19
객체지향 개발 원칙  (0) 2011.04.19
UML Tip  (0) 2011.04.19

1. 요구사항에 대해 일반적으로 보이는 명사나 비슷한 대상을 가지고 대충 관계를 맺지 말아야한다.
-> 이런 행동은 허깨비 클래스, 상상뿐인 추상화, 하나님 클래스 등을 생성할 여지가 있고 실제 코드로 작성이 엉망으로 바뀔 가능성이 많다.

허깨비 클래스 : 실제 단순한 기능을 하는 부분을 어뎁터 생성하게 되어 기능을 사용할 때 필요 없는 클래스
상상뿐인 추상화 : 개념에 의해서 추상 클래스를 생성 한 후 다른 클래스에서 전혀 사용하지 않은 클래스
하나님 클래스 : 여러 객체로 기능을 분리하였지만 실제 중요한 동작은 한 클래스에 몰려있게 되는 클래스

2. 문제를 생각해야 한다.
-> 실제 요구사항들이 진행되는 과정을 이해하고 클래스로 구현해야 하는 문제가 무엇인지 파악해야 한다. 하지만 이때에도 주의해야 할 사항이 있다.

선을 넘어간 연결 : 각 과정을 나누고 난뒤 물리적인 순서로 연관을 맷을 경우 문제가 발생한다. 즉 논리적인 관점에서 과정의 연관을 생각해야한다.

3. 사용자 인터페이스를 생각한다.
-> 실제 사용자(호출하는 대상) 관점에서 객체와 상호작용할 수단을 만든다. 인터페이스 내에서 위 단계에서 도출된 클래스와 어떻게 연결될지 논리적인 관점에서 생각한다. 이런 연결을 협력 다이어그램으로 표현 한 후 추상 모델 클래스 다이어그램으로 정의할 수 있다.

4. 추상 모델을 실제 구현한다.
-> 생성 된 모델을 현재 환경에 의존하지 말도록 구체적으로 고민해야 한다. 즉 DIP를 사용하여 의존관계에 대해 생각해본다. 그리고 의존관계를 인터페이스로 분리하여 세부 사항 정의 할 때 고차원적인 정책과 한정 된 유도 클래스 내 행동(메소드)을 분리해야 한다.

'UML,OOP,Pattern, TDD' 카테고리의 다른 글

Strategy pattern VS Brigde Pattern  (0) 2011.10.09
TDD - 계약에 의한 설계(DbC, Design by Contract)  (0) 2011.04.19
TDD Tip  (0) 2011.04.19
객체지향 개발 원칙  (0) 2011.04.19
UML Tip  (0) 2011.04.19

의존 관계 정리
1. 인터페이스를 만들어 의존 관계를 끊거나 의존의 방향을 바꿀수 있다.
2. 다형성을 사용하면 어떤 함수를 포함한 모듈에 의존하지 않고 그 함수를 호출할 수 있다.

SRP : 단 하나의 책임 원칙

1. 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다. 한 클래스가 너무 많을 것을 안다면(다양한 기능의 메소드) 부서지기 쉬운 클래스가 된다. 즉 설계 결합도가 너무 높다. UML을 통해 확인하기 쉽다. 둘 이상의 주제 영역에 의존 관계인 클래스를 찾아보면 된다. 가장 쉽게 찾을 수 있는 것은 특정 속성을 부여하는 인터페이스를 하나 또는 그 이상으로 구현하는 클래스를 확인한다. 

2. 기존에 존재하는 서로 다른 속성의 인터페이스와 클래스가 하나의 단위로 묶여야 한다면 인터페이스를 바로 적용하기 보다는 클래스를 상속한 자식 클래스에서 인터페이스를 적용하여 인터페이스와 부모 클래스의 연관관계를 최소화시킨다.

어떤 클래스를 변경해야 할 이유는 오직 하나 뿐이어야 한다

OCP : 개방 - 폐쇄 원칙

1. 소프트웨어 엔티티(클래스, 모듈, 함수)는 확장에 대해서는 개방되어야 하지만, 변경에 대해서는 폐쇄되어야 한다. 즉 모듈 자체를 변경하지 않고도 둘러싼 환경을 바꿀 수 있어야 한다. A->B->C 3개의 클래스가 의존된 상태에서 C클래스가 변경되면 A클래스 까지도 영향을 미친다. 이때 A와 B 사이에 인터페이스를 두어 환경 변경에 대해 폐쇄해야한다.

2. GUI를 사용한 MVC모델에서는 View와 Controller의 결합이 너무 강한 경우가 많다. 이때 OCP규칙을 적용하려면 FLIP-FLOP패턴을 적용하여 View와 Controller사이의 결합도를 낮춘다. FLIP-FLOP패턴은 뷰와 컨트롤러 각각 인터페이스를 생성하여 상대방의 인터페이스를 참조하게한 후 컨트롤러모델에서 뷰의 동작을 제어하는 형태를 가지는 방식이다. 이렇게 구현하는 경우 뷰와 컨트롤러 각각 테스트 케이스 작성시 SELF SHUNT패턴을 사용하여 의존성이 있는 객체를 대체할 수 있게 된다. 즉 TDD방식으로 구현하게 된다면 위와 같은 구조로 개발하기 수월해진다.

클래스를 변경하지 않고도 그 클래스의 환경을 바꿀 수 있어야 한다.

LSP : 리스코프 교체 원칙

1. 서브타입은 언제나 자신의 기반 타입으로 교체할 수 있어야 한다. 즉 instanceof(클래스지정) 이나 다운캐스트를 할 필요가 없어야한다. 사용자는 파생클래스에 대해 알 필요가 없어야 한다. 이런 경우는 동일 의미를 가진 클래스이지만 실행 방식이 다른 클래스를 하나의 기반 타입으로 묶으려고 할 때 발생하게 된다. 다른 실행 방식으로 인해 예외 상황을 명시하기 위해 다운캐스트나 instanceof를 사용하게 된다. 이때 동일 의미이지만 다른 기반 성격의 클래스로 분류해야한다.

유도된 크래스으 메서드를 퇴화시키거나 불법으로 만드는 일을 피하라. 기반 클래스의 사용자는 기반 클래스에서 유도된 클래스에 대해 알 필요가 없다.

DIP : 의존 관계 역전 원칙

1. 고차원 모듈은 저차원 모듈에 의존하면 안된다. 이 두모듈 모두 다른 추상화된 것에 의존해야 한다.
2. 추상화된 것은 구체적인 것에 의존하면 안된다. 구체적인 것이 추상화 된것에 의존해야 한다.
즉 자주 변경되는 컨크리트 클래스에 의존하면 안된다. 어떤 클래스에서 상속받아야 한다면, 기반 클래스를 추상 클래스로 만들어야 한다.
어떤 클래스의 참조를 가져야 한다면, 참조 대상이 되는 클래스를 추상 클래스로 만들어야한다. 만약 어떤 함수를 호출해야 한다면 함수를 추상 함수롤 만들어라. 여기서 말하는 클래스는 자주 변경되는 컨크리트 클래스 이다. 즉 개발 중인 클래스이거나 변할 가능성이 높은 비즈니스 규칙을 담은 클래스이다. UML을 사요아면 이 원칙을 쉽게 검사할 수 있다. 다이어그램의 화살표마다 인터페이스나 추상 클래스를 가리키는지 확인하면 된다.

자주 변경하는 컨크리트 클래스 대신 인터페이스나 추상 클래스에 의존하라

ISP : 인터페이스 격리 원칙
비대한 클래스 메서드를 다 사용하는 일은 매우 적다. 즉 필요치 않은 메서드에 의한 변화도 영향을 받게 된다. 이런 의존 관계는 필요한 인터페이스만 제고하여 필요하지 않은 메서드를 보호하면 된다.

어떤 객체의 사용자에게 필요한 메서드만 있는 인터페이스를 제공하라

'UML,OOP,Pattern, TDD' 카테고리의 다른 글

Strategy pattern VS Brigde Pattern  (0) 2011.10.09
TDD - 계약에 의한 설계(DbC, Design by Contract)  (0) 2011.04.19
TDD Tip  (0) 2011.04.19
객체지향 개발 관련 팁  (0) 2011.04.19
UML Tip  (0) 2011.04.19
출처 : UML 실전에서는 이것만 쓴다

로드맵

- UML은 대규모 소프트웨워 구조의 로드맵을 만들 때 유용하다. 이런 로드맨은 어떤 클래스가 다른 클래스에 의존하는지 개발짜가 빨리 파악할 수 있게 해주고 시스템의 구조에 대한 참조 도표로도 사용된다. 굳이 문서로 저장 안해도 된다

반복을 통해 다듬기
- 행위를 제일 먼저 시작하는 것이 좋다. 간단한 시퀀스 다이어그램으로 문제를 풀어나간다. 이후 협력 다이어그램을 작성한 후 구조를 점검하여 클래스 다이그램을 다듬어 나간다. 이때 클래스 간에 의존관계를 최소화하기 위해 적절한 패턴을 사용하는 것이 좋다.

미니멀리즘
- UML은 의사소통을 위해 존재하는 것이지 예쁘게 꾸미기 위해 존재하는 것이 아니다. 다이어그램 한 장에 많은 세부사항을 그려 넣지 말아야 한다. UML다이어그램은 메서드나 변수, 관계를 선언하는 장소로 취급해서는 안된다.


클래스다이어그램

연관
클래스 사이의 연관은 다른 객체의 참조를 가지는 인스턴스 변수를 의미한다. 프로그램 안에서 실제로 일어나는 일을 정확히 설명하는 "~와 연결된다" 와 같은 용어이다

집합
부분/전체 관계를 내포하는 특별한 형태. 집합에 대해 여러 정의가 내려져 있기때문에 혼란을 가져다 준다. 가급적 피하는 것이 좋다. 집합의 규칙은 전체는 자신이 될수 없고(자기참조), 어떤 객체가 자신의 부분이 될수 없고, 두 객체가 서로 상대 객체의 부분이 될수 없다. 그리고 세 객체가 전체/부분 관계의 고리를 만들 수 없다.

합성
집합과 동일한 규칙을 가지고 있으면서 몇가지 규칙이 추가된다.
피보호자의 한 인스턴스를 두 주인이 소유하지 못한다. 하지만 객체 다이어그램과 대응하는 클래스 다이어그램은 문제 없다.
주인은 피보호자의 수명 전체에 책임을 진다. 주인이 소멸되면, 피보호자도 함께 소멸되어야 한다. 즉 주인 객체에서 내에 생성된 피보호 객체는 주인 객체가 메모리에서 해제될때 같이 해제되어야한다.


시퀀스다이어그램

- 시퀀스 다이어그램은 모든 시나리오에서 공통으로 나오는 것을 찾아 초점을 맞춰야한다. 공통된 주제와 공통된 실천 방법을 보이기 위해 다이어그램을 사용해야한다. 사소한 차이점까지 모두 문서로 만들기 위해 다이어그램을 사용하지 마라. 메시지 흐름을 설명하기 위해 시퀀스 다이어그램을 꼭 그려야 한다면 간결하고 절재해서 그려야한다.

첫째. 시퀀스 다이어그램이 정말 필요한지 확인하라. 코드가 의사전달하기 더 쉽고 경제적인 경우가 많다.
둘째. 시퀀스 다이어그램이 필요하다면 여러 시나리오로 쪼갤 수 있는지 확인하라. 거대한 시퀀스 다이어그램은 읽기 쉬운 작은 시퀀스 다이어그램 여러개로 나눌수 있다.
세째. 무엇을 그려야하는지 생각해봐야한다.저차원 연산에 대한 세부사항과 고차원의 개괄인지 생각하여야 한다. 대부분의 경우 고차원 다이어그램이 더 쓸모있다.













'UML,OOP,Pattern, TDD' 카테고리의 다른 글

Strategy pattern VS Brigde Pattern  (0) 2011.10.09
TDD - 계약에 의한 설계(DbC, Design by Contract)  (0) 2011.04.19
TDD Tip  (0) 2011.04.19
객체지향 개발 관련 팁  (0) 2011.04.19
객체지향 개발 원칙  (0) 2011.04.19

문 제

UIAlertView 메세지를 출력하는 도중 Home 버튼과 같이 예외 상황이 경우 UIAlertView의 Delegate 이벤트가 제대로 진행되지 않은 현상

현 상

문제 소스

- (void) spotDownloader:(SpotDownloader *)downloader didDownloadAll:(int)allSpot
{
    //마지막에
 if(NaNetworkReachable() == NO)
 {     
  [i_downloader stop];
  NaMessageViewWithOneButton(Na_STR_ERROR_NO_NETWORK, @"확인", self);
  return; 
 } 
 
 i_progressView.downloadAllNum = allSpot+i_downedNum;
 i_progressView.downloadNum   = allSpot+i_downedNum;
 i_bDownloading = NO;
 i_downloading  = NO;
 
    WSTown *town = [getThemeCountWithTownId(i_downloadTownId, i_downloadCityId) retain];
   
    [SQLiteForWingSpoon updateTownInformation:i_downloadTownId
         spotCount:town.i_spotCount
         themeCountArray:town.i_themeArray
           updateDate:nil valid:2]; 
 [SQLiteForWingSpoon updateCityInformation:i_downloadCityId
          valid:2];
 
 [town release];
 
    NaMessageViewWithYesNoButtonWithDelay([NSString stringWithFormat: Na_STR_OK_DOWNLOAD, [i_downloadTargetTown i_name] ], self, 1, 0.1);
}


다운로드를 받고 완료 메세지(NaMessageViewWithYesNoButtonWithDelay)를 출력하는 도중 Home버튼을 누르게 되면 아래와 같은 순서로 이벤트가 발생하였다.

1. 다운로드 완료 처리 중(spotDownloader 진행 중)
2. 홈 버튼 클릭
2. UIAlertViewDelegate - willPresentAlertView (Background로 가기전에 AlertView가 준비상태로 돌입)
3. AppDelegate - applicationDidEnterBackground (Background 상태)
4. 앱 재 실행
5. UIAlertViewDelegate - didPresentAlertView (Foreground 이전에 AlertView가 표시)
6. AppDelegate - applicationWillEnterForeground (Foreground 상태가 됨)
6. UIAlertViewDelegate - didDismissWithButtonIndex (AlertView가 저절로 닫힘)

이런순으로 Delegate가 진행되어 문제가 발생되었다. 즉 Foreground 이전에 didPresentAlertView가 호출되어 이미 메세지가 뜬 상태로 있다가 Foreground 호출 이후 didDissmissWithButtonIndex가 호출되어 메세지 창이 저절로 닫혀버리는 현상이다. 더욱이 이런게 닫힌 창이 다른 UIAlertView가 호출될 때 갑자기 나타나는 것이다. 그로 인해 원래 UIAlertView에서 호출되어 처리되어야 하는 View가 아닌 다른 view에서 호출되어 BAD_EXCEPTION 발생하는 문제가 생겼다. (어떤 경우에는 6번 과정 이후 자동으로 다시 willPresentAlertView가 호출되어 다시 출력되어 문제가 안생기는 경우도 있으나 위 상태에서 중단 되는 경우가 문제 였다)


해결방법

1. didDismissWithButtonIndex 이벤트가 발생될 때 매개변수로 넘어오는 alertView의 객체 상태로 비정상 닫기 인지 정상  닫기 인지 구분하는 방법을 찾았다.

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

alertView == nil 인 경우 정상 닫힘
alertView != nil 인 경우 비정상 닫힘

2. UIAlertView 내 dismissWithClickedButtonIndex 메시지를 호출하여 AlertView를 다시 출력 안되게끔 막는다.
-> UIAlertView 내 메시지들을 찾아보다가 위 메시지의 역할이 사용자의 Action 없이 AlertView를 닫히게하는 기능이 있다는 것을 깨닫고 비정상 닫힌 경우 위 메시지를 호출하여 다른 UIAlertView와 중복 호출이 안되게 끔 방지하였다

3. 마지막으로 닫혀버린 UIAlertView 메시지를 다시 출력하여 사용자가 AlertView 이상 동작을 못느끼게 재실행한다

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex  // after animation
{
    if(alertView.superview != nil){
        // 기존에 비정상 UIAlertView를 오작동 출력을 방지함
        [alertView dismissWithClickedButtonIndex:buttonIndex animated:NO];
        // 메시지 재출력
        NaMessageViewWithYesNoButton([NSString stringWithFormat: Na_STR_OK_DOWNLOAD, [i_downloadTargetTown i_name] ], self, 1);
       
    }
}






지도 위에 아이콘을 UIView를 사용하여 뿌리는데 iPhone4에서 제대로 이미지가 적용이 되지 않았다

해당 문제에 대해 기존 코드를 다 분해해본 결과 원인은 위 함수가 문제 였다.

retina디스플레이에 맞는 해상도 스케일이 위 함수에서는 제대로 적용이 안되었던 것 같다.

해당 문제에 대해 서칭해본 결과 아래 블로그를 찾았다.

http://www.waterworld.com.hk/en/blog/uigraphicsbeginimagecontext-and-retina-display

UIGraphicsBeginImageContext 를 retina디스플레이에 제대로 적용하기 위해서는 UIGraphicsBeginImageContextWithOptions 를

사용해야 했고 단말 기기의 버전에 따라 호출 함수를 결정해줘야하는 번거로움이 생겼다.

하지만 문제를 해결했으니 다행이다.

위 블로그의 업데이트 된 내용을 보니 ipad쪽에서 UIScreen의 scale을 불러오는 부분에 문제가 있는것 같아 코드를 수정하였다.

void RetinaAwareUIGraphicsBeginImageContext(CGSize size) {
static CGFloat scale = -1.0;
if (scale<0.0) {
UIScreen *screen = [UIScreen mainScreen];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 4.0) {
if( [screen respondsToSelector:@selector(scale)] ){
scale = [screen scale] ;
}else {
scale = 1.0;
}
}
else {
scale = 0.0; // mean use old api
}
}
if (scale>0.0) {
UIGraphicsBeginImageContextWithOptions(size, NO, scale);
}
else {
UIGraphicsBeginImageContext(size);
}
}

이번에 아이콘 변경작업을 하면서 많은 일이 생긴것 같다. 이번 기회에 제대로 당한듯 ㅠㅠ


보통 아이콘 설정에는 

Icon file
CFBundleIconFiles

두 항목에서 설정할 수 있다.
이번에 아이콘을 변경하면서 위 두항목을 모두 변경하고 난 뒤 앱스토어에 등록을 하였는데 오류가 발생하여 거절당했다
원인은 CFBundleIconFile 부분에 디렉토리 명을 삽입하였는데 그 부분이 문제였다.

아이콘 파일이 많아 resource 디렉토리 밑에 디렉토리를 하나 생성하여 넣은 후 프로젝트에 추가를 시켜 놓았는데 상대 경로로 입력해야 되는 걸로 알고 디렉토리명을 넣었다가 오류가 난것이였다(하지만 시뮬레이터와 디바이스에 테스트 할땐 제대로 돌아간다!!!! -_-). 즉 소스내 이미지 파일을 사용하듯 설정 부분에서도 아이콘 명만 기입해야 했었다! -_-;;; 생각해보니 아카이빙할 때 디렉토리라는 개념이 없이 하나의 패키지로 담는데 경로를 지정하니 당연히 제대로 읽지 못하는 것이었다.

거절 이후 원인을 찾아 해결 한 후 다시 앱스토어에 등록을 하였는데.... 이런! 아이폰4에서 아이콘이 흐릿하게 나오는 것이 아닌가? 아마도 아이폰3 아이콘이 나오는것 같았다(@2x.png 이미지가 제대로 안먹힌 것 같았다)

수소문 끝에 원인을 찾아보니 xml 설정에 문제가 있었다.


저렇게 설정해도 빌드에는 문제가 안되지만 아마 CFBundleIconfile항목아래에 있는 Icon.png 파일을 읽어들여 뿌리는것 같다. 즉 아이폰 4에서도 아이폰 3아이콘이 나오는 이유는 저부분이였다. 즉 아래의 기종에 따른 아이콘 설정들이 적용이 안되는 것이다. -_-;

원인이 되는 부분은 key 항목의 Icon files 부분이였다. 저렇게 해도 빌드에는 문제가 안되지만 아래 설정을 깔끔하게 무시하는것 같다.

수정은 Icon files를 CFBundleIconFiles로 변경하니 제대로 아이콘이 적용되었다.


아 정말... 힘들다 ㅠㅠ 단순한 아이콘 설정에도 이렇게 예외상황이 많을 줄이야 ㅠㅠ



1. QuartzCore 프레임워크를 추가한다

2. 헤더에 QuartzCore를 추가한다.

2. 해당 view, button 객체에 아래와 같이 작업을 해준다

둥근 모서리 : [button.layer setCornerRadius:0.0f]
테두리 두께 : [button.layer setBorderWidth:2.0f]
테두리 색 :
UIColor * boarderColor = [[UIColor alloc] initWithRed:xxxx green:xxx blue:xxx alpha:xxx];
[button.layer setBorderColor:[boardercolor CGColor]]

'iOS' 카테고리의 다른 글

아이폰 아이콘 설정 주의사항  (0) 2011.03.11
아이폰 개발 유용팁  (0) 2011.03.11
userInteractionEnabled 영향  (0) 2011.03.04
NSMutableArray 생성 방법  (0) 2011.03.02
Objective C Delegate 활용  (0) 2011.02.24

아이폰의 테이블뷰의 속성 중 userInteractionEnabled을 NO로 지정하게 되면 UITableViewDelegate 가 동작하지 않는다

이 경우 아래의 메소드를 구현하여 임의의 지역에 이벤트를 발생하도록 할 수 있다

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event



- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
 UITouch *touch  = [touches anyObject];
 CGPoint touchPoint   = [touch locationInView:i_tableView];

if ( touchPoint.y > y && touchPoint.y < y+cell_height )
 { 
             특정동작 
 }

-------------  생략 -----------------------------

}




NSMutableArray *wordArray = [NSMutableArray array];

-> 컨베니언스 컨스트럭쳐이므로 autorelease상태인 배열을 반환한다. 해당 인스턴스를 반환할때 따로 autoreelase를 표시 하지 말아야 하며 반환 받은 객체에서는 retain - release를 맞춰주어 오너쉽을 유지해야한다


NSMutableArray *wordArray = [[NSMutableArray alloc]init];

-> 기본 인스턴스 생성 방식이므르로 인스턴스를 반환할때 autorelease를 표시하여 오너쉽 포기를 명시해야 한다. 반환 받은 객체에서는 마찬가지로 retain- release를 맞춰주어 오너쉽을 유지해야한다.
상태

1. TownListViewController에서 이벤트 발생시 RootViewControllerSearch 객체의 특정 메소드 실행
-> 특정 데이터 값 교환

해결

1. ViewPageEventDelegate 프로토콜을 생성하여 TownListViewController에 등록하여 해당 프로토콜을 실행하도록 설정



2. Objective C에서는 프로토콜을 클래스 맴버로 설정할 때 일반 객체와 표현 방법이 다름

일반객체

객체명 * 변수명
-> TestObj * testObject;

프로토콜
id<프로토콜명> 변수명
-> id<TestObj> testObject;

3. 델리게이트 프로토콜을 한 객체에 많이 정의 된 경우 클래스 멤버로 나눠 실행 가능할 것 같음


'iOS' 카테고리의 다른 글

userInteractionEnabled 영향  (0) 2011.03.04
NSMutableArray 생성 방법  (0) 2011.03.02
CFURLCreateStringByAddingPercentEscapes 메모리 관리  (0) 2011.02.17
오퍼레이션 큐에서 메모리릭 상황  (0) 2011.02.17
메모리릭 현상(1)  (0) 2011.01.31

 위 함수는 NSString처럼 프레임워크에서 자동으로 메모리 관리해주는 문자열을 반환하지 않는다.
alloc-init과 같이 할당 받은 후 release과정을 통해 메모리 과정에 신경써주어야함

NSString * tempComment  = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)comment, NULL, CFSTR("?&#%<+"), kCFStringEncodingUTF8);

......

[tempComment release];


'iOS' 카테고리의 다른 글

NSMutableArray 생성 방법  (0) 2011.03.02
Objective C Delegate 활용  (0) 2011.02.24
오퍼레이션 큐에서 메모리릭 상황  (0) 2011.02.17
메모리릭 현상(1)  (0) 2011.01.31
Custom UINavigationController  (0) 2011.01.24

상황

1. NSOperationQueue를 상속받아 커스텀 OperationQueue객체를 만듬
2. NSOperation을 상속받은 커스텀 객체를 위 큐에 추가시킴
3. Queue를 진행하면서 Operation을 수행함 -> 완료 될때 마다 Dealloc이 실행됨
4. 모든 Operation을 완료함
5. 완료 후 커스텀 OperationQueue에 Cancel 메세지를 보냄

원인

1. 오퍼레이션 큐의 모든 오퍼레이션이 실행된 후 dealloc상태에서 Cancel 메세지를 발생시키면 임의의 오퍼레이션에서 Cancel메세지가 발생되어 메모리 릭이 발생된다. 왜 완료된 오퍼레이션에서 Cancel이 작동되는지 정확한 원인은 파악이 안됨
2. 여기서 사용되는 큐는 커스텀 프로그래스 바 작업을 위해 일반 스레드 -> 메인스레드로 변경하는 부분이 들어가 있 작업하는 것이 이유가 되는 것 같음

// 메인스레드로 바꾸는 예
if([NSThread isMainThread] == NO)
{
[self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
return;
}

'iOS' 카테고리의 다른 글

Objective C Delegate 활용  (0) 2011.02.24
CFURLCreateStringByAddingPercentEscapes 메모리 관리  (0) 2011.02.17
메모리릭 현상(1)  (0) 2011.01.31
Custom UINavigationController  (0) 2011.01.24
iPhone TestCase 생성  (0) 2011.01.18
자바 스레드

사용자 정의 스레드 - 메인 스레드가 종료되도 계속 진행
일반 스레드객체.start();

데몬 정의 스레드 - 메인 스레드가 종료될때 같이 종료
스레드객체.setDemone(true);
스레드객체.start();

메소드내 선언된 변수를 반복문에서 다시 선언 할 경우 메모리릭이 발생할 수 있음

NSMutableArray *array = [NSMutableArray array];
...
...
for(int i = 0; i < spotInfo.i_commentArray.count; i++)
{
NSMutableArray *array = [NSMutableArray array];  // <-- 메모리릭 발생가능
...
...
}

'iOS' 카테고리의 다른 글

CFURLCreateStringByAddingPercentEscapes 메모리 관리  (0) 2011.02.17
오퍼레이션 큐에서 메모리릭 상황  (0) 2011.02.17
Custom UINavigationController  (0) 2011.01.24
iPhone TestCase 생성  (0) 2011.01.18
NSOperation  (0) 2011.01.11


아이폰 기본 UINavigationController 사용 외 Custom하는 방법

1. UINavigationController를 상속받은 객체를 생성한다.
-> 초기화시 navigationBarHidden 속성을 YES로 변경한다

#import <Foundation/Foundation.h>
#import "NavViewController.h"

@interface NavController : UINavigationController <UINavigationControllerDelegate> {
NavViewController * i_rootController;
}
@end
-------------------------------------------------------------------------------------------------------------

#import "NavController.h"
@implementation NavController
- (id)init
{
    if(self = [super init])
 {
  self.navigationBarHidden = YES;
 }
    return self;
}
@end


2. 네비게이션을 최초로 실행하는 Controller에서 삽입할 ViewController를 생성한 뒤 위 상속받은 네비게이션컨트롤러에 initWithRootViewController 메소드를 통해 초기화 후 addSubview를 통해 상위 View에 할당한다

UIViewController * navView;
navView = [[NavViewController alloc] init];
i_navControllerArray = [[NavController alloc] initWithRootViewController:navView];
[self.window addSubview:i_navControllerArray.view]; 
[navView release];

3. 생성된 View의 초기화 단계에서는 네이게이션바를 대체할 수있는 커스텀 UI를 생성한다

if(self = [super init])
{
 i_tnb  = [TNB getTnbWithTitle:@"테스트맵" LeftTitle:@"이전" AndRightTitle:@"지도"];
 [i_tnb addTarget:self actionForRightButton:@selector(onShowMapButton:)];
 
 [self.view addSubview:i_tnb];
}

4. 해당 UI에서 네비게이션 버튼 클릭시 발생되는 이벤트시 페이지 이동을 위해서 pushViewController 메소드를 사용하여 신규 View Controller 페이지를 네비게이트 시킨다.
- (void) onShowMapButton:(id)sender
{
 NSLog(@"MapButton");
 
 MapViewController * mapViewController = [[MapViewController alloc]init] ;
 
 [self.navigationController pushViewController:mapViewController animated:YES];
 
 [mapViewController release];
 
}

5. 네이게이트 된 후 이전 페이지로 돌아갈 경우 popViewControllerAnimated 메소드를 사용하여 이전 페이지로 돌아간다
@implementation MapViewController
-(id) init {
 
 if(self = [super init])
 {
  i_tnb  = [TNB getTnbWithTitle:@"맵" LeftTitle:@"이전" AndRightTitle:@"현재위치"];
  [i_tnb addTarget:self actionForLeftButton:@selector(onBackButton:)];
  [self.view addSubview:i_tnb];
 }
 
 return self;
}
- (void) onBackButton:(id)sender
{
 [self.navigationController popViewControllerAnimated:YES];
}
@end

'iOS' 카테고리의 다른 글

오퍼레이션 큐에서 메모리릭 상황  (0) 2011.02.17
메모리릭 현상(1)  (0) 2011.01.31
iPhone TestCase 생성  (0) 2011.01.18
NSOperation  (0) 2011.01.11
NSOperationQueue  (0) 2011.01.10

Unit Test 연동

Xcode에서는 iPhone의 Unit Test를 지원하기 위해 OCUnit이라는 Unit Testing framework를 xcode 3.0 버전부터 공식적으로 지원하고 있다. 따라서, Xcode의 OCUnit을 통해 생성된 프로젝트에 UnitTest Case를 쉽고 빠르게 생성하고 테스트할 수 있다.
Xcode에서는 Logic Test와 Application Test라는 두 가지 타입의 Unit Test를 지원한다.
Logic Test는 App에서가 아닌 Build Phase에서 Test를 진행하며 소프트웨어의 Logic이나 Algorithm을 테스트하기 위한 방식이다.
단순 메소드나 한개 혹은 여러 개 클래스를 테스트 할 수 있다. 기능의 정상적인 동작을 확인하는 테스트 외에 실제 application과 다른환경을 설정하여 테스트하는 Stress Test도 수행할 수 있다. 
Application Test는 동작하는 application에서 기능을 테스트하는 방식이다. 실제 Device 상에서 테스트가 이루어지기 때문에 iPhone에 있는 Resource를 이용하는 모듈에 대한 Test가 가능하며 User Interface Control의 연결이 잘 설정되었는지 여부도 확인할 수 있다. 
 
 iPhone Unit Test를 위해 사용하는 Logic Test와 Application Test의 설정방법은 다음과 같다.
  • Logic Test 설정방법
    • Xcode에서 Project > New Target메뉴나 Groups & files의 Targets그룹에서 마우스 오른쪽 버튼을 클릭하여 Add> New Target으로 새로운 Target Bundle을 생성함.

                          u1.jpg

    • New Target 템플릿 윈도우에서 Cocoa Touch > Unit Test Bundle을 선택한 후 Next 버튼 클릭함.

                           u2.jpg

    • Target Bundle명을 넣고 finish를 클릭하여 Group and Files의 Targets그룹에 새로 추가된 Target Bundle을 확인함.

                           u3.jpg



 

  • Application Test 설정방법
    • Xcode에서 Group & files의 Targets그룹에 현재 생성된 Target Application을 선택한 후 마우스 오른쪽 버튼을 클릭하여 Duplicate를 선택한 후 새로운 Target Application을 생성함.
    • Application Test는 실제 실행을 위한 Executable Target이 필요함. Duplicate 기능을 이용하면 기존의 프로그램 설정을 그대로 적용하여 실행할 수 있는 Executable Target을 생성할 수 있음.
    • 새로 생성된 Target Application 명 규칙은 <Application_name> + Testing의 형태로 설정함. Target Application 명은 자유롭게 설정이 가능하나 마지막에(suffix) 반드시 Testing을 포함시켜야 함. ex) ApplicationTesting

                          u4.jpg 

    • Xcode에서 Project > New Target메뉴나 Groups & files의 Targets그룹에서 마우스 오른쪽 버튼을 클릭하여 Add > New Target으로 새로운 Target Bundle을 생성함.

                              u5.jpg

    • New Target 템플릿 윈도우에서 Cocoa Touch > Unit Test Bundle을 선택한 후 Next 버튼 클릭함.

                          u6.jpg

 

    • Target Bundle명을 넣고 finish를 클릭하여 Group and Files의 Targets그룹에 새로 추가된 Target Bundle을 확인함.
    • 새로 생성되는 Target Bundle명 규칙은 <Application_name> + Tests의 형태로 설정함. 이름은 자유롭게 설정이 가능하나 마지막에는(suffix) 반드시 Tests을 포함시켜야 함. ex) ApplicationTests

                          u7.jpg

 

 

  • TestCase Class생성방법
    • Group and Files 목록에 그룹을 추가하기 위해서 프로젝트 명에서 마우스의 오른쪽을 클릭하여 Add > New Group 메뉴를 선택하고 Test 클래스가 있을 Group을 생성하고 Group 명을 설정함. Group명은 특별한 규칙이 없이 자유롭게 작성이 가능함.

                          u8.jpg

 

    • 새로 생성한 Group에 마우스 오른쪽 버튼을 클릭하여 Add > New File을 실행하면 New File 템플릿 윈도우에서 Objective-C test case class형식의 파일을 선택 후 Next 버튼을 클릭함.

                         u9.jpg

 

    • 생성할 Test case의 파일 명과 파일 명 바로 아래에 있는 Also create XXX.h 옵션도 함께 선택함. 이때 Targets은 Executable Target이 아닌 Target Bundle (ApplicationTests)만 선택한 후 Finish 버튼을 클릭함.

                          u10.jpg

 

    • 생성한 Test class Group에 새로 생성된 Test Case Class 코드가 추가된 것을 확인할 수 있음.

                          u11.jpg

 

  • Target Dependency 설정
    • Target 그룹의 Target Bundle (ApplicationTests)을 더블 클릭한 후 Target Info 윈도우에서 General 탭을 선택함.

                          u12.jpg

    • Direct Dependencies의 ‘+’ 버튼을 클릭하여 원 Application Target 'OCT'을 선택하여 추가함

                          u13.jpg

 

    • Target 그룹의 Target Application (ApplicationTesting)을 더블 클릭한 후 Target Info 윈도우에서 General 탭을 선택함.

                          u14.jpg

 

    • Direct Dependencies의 ‘+’ 버튼을 클릭하여 Target Bundle 'ApplicationTests'을 선택하여 추가함 

                          u15.jpg

 

    • Products 폴더에서 생성된 Target Bundle 이름의 octest파일(ApplicationTests.octest)을 Target Application(ApplicationTesting)> Copy Bundle Resource로 dragging하여 Copy시켜 생성함.

<Products 폴더에 octest 파일이 빨강색인 경우>
octest 파일의 글자 색이 빨강색으로 나올 경우 Build가 진행되지 않았기 때문으로 Build를 진행시키면 빨강색은 사라짐.

 

 

                        

 

                         u16.jpg

 

    • Xcode 좌측 상단에 있는 설정버튼을 클릭하여 Active Target을 Target Application (ApplicationTesting)으로 선택함.
    • Active Executable 은 Target Application(ApplicationTesting – iPhone Simulator3.1.3)선택함.

                        u17.jpg

 

  • Build 환경 설정 및 Unit Test결과확인
    • Group&files에서 Project와 Target을 더블클릭하면 빌드설정 창이 나타나고, BaseSDK 설정을 Device 모드로 변경함. 
    • UnitTest 코드가 생성되면 소스코드 안에 LigicTest와 ApplicationTest를 수행할 수 있는 샘플 테스트코드가 기본적으로 제공됨. 실제 새로운 테스트코드를 작성할 경우 이 샘플코드는 지우고 사용함.  
    • 샘플코드의 헤더파일에서 정의된 USE_APPLICATION_UNIT_TEST 값을 '1'로 설정하면 testAppDelegate함수가 호출되면서 ApplicationTest 방식의 테스트가 수행됨.
    •  USE_APPLICATION_UNIT_TEST 값을 '0'으로 설정하면 testMath 함수를 호출되며 LogicTest 방식의 테스트가 수행됨.
    • Device가 연결되지 않은 경우에는 USE_APPLICATION_UNIT_TEST 값 설정을 '0'으로 변경하고 Simulator로 logicTest를 수행하고 결과를 확인할 수 있음. 

u29.jpg

 

    • 설정을 모두 마치고 Xcode에서 Build > Build를 수행하여 결과를 확인함.
    • Xcode에서는 Build 시 Unit Test 결과를 Xcode 하단에 함께 표시하고 있음.
      Test 성공 시 ‘Succeeded’라는 메시지가 표시되고 Test 실패 시 ‘Failed’라는 메시지가 표시됨.

                          u20.jpg

    • 표시된 결과 메시지를 클릭하여 Unit Test의 수행된 총 테스트 케이스와 어떤 테스트 케이스에서 성공 및 실패 여부, 테스트케이스 소요시간 등의 상세정보를 확인함.

                          u21.jpg

 

                          u22.jpg

 

 

  •  Unit Test 결과의 CI 연동
    • OCUnit 결과를 JUnit 형태의 xml파일로 변경시켜주는 ocunit2junit.rb 파일을 /usr/bin/ 디렉터리에 추가함
    • xcodebuild clean 명령어를 설정하고 Target은 LogicTest Target Bundle 명으로 설정함.

                         u23.jpg

xcodebuild clean -target "LogicTest Target bundle 명” -configuration Debug

 

    • Target 대상 프로젝트를 수행시키는 xcodebuild 명령어 설정함.

                          u24.jpg

 

                                    xcodebuild -target "LogicTests" -configuration Debug

                                    -sdk /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.3.sdk/

 

    • Hudson CI Build의 Execute Shell에서 xcode build설정 다음에 | /usr/bin/ocunit2junit.rb 으로 설정함. 
      ocunit2junit.rb는 OCunit의 결과파일을 JUnit 형태의 xml 파일로 변경하여 Hudson CI의 JUnit Plug- in을 통해 설정할 수 있는 스크립트 파일임. 

                          u25.jpg

    • Hudson CI의 Publish JUnit test result report을 선택하고 test-reports/*.xml 로 설정함.

                         u26.jpg

    • Build Now를 실행하면 해당 Unit Test 결과 그래프를 확인함.


                   u27.jpg


'iOS' 카테고리의 다른 글

메모리릭 현상(1)  (0) 2011.01.31
Custom UINavigationController  (0) 2011.01.24
NSOperation  (0) 2011.01.11
NSOperationQueue  (0) 2011.01.10
NSNotificationCenter  (0) 2011.01.05

sudo vim /Library/LaunchDaemon/com.시작서비스명.plist

<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
        "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>com.tomcat-5.5.launchd</string>
        <key>ProgramArguments</key>
        <array>
                <string>/Users/taehoonkoo/WorkSpace/severs/apache-tomcat-5.5.31/bin/startup.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
</dict>
</plist>

<string></string>의 값 부분은 실행 파일 path는 Machine의 설정에 따라서 바뀌어야 한다.
sudo chown root:wheel /Library/LaunchDaemon/com.시작서비스명.plist으로 소유권을 옮겨 주면, 다음 부팅 때 부터 자동 실행된다.

'CI 설정' 카테고리의 다른 글

간단 Hudson server 설정  (0) 2011.01.17
톰캣주소 : http://tomcat.apache.org
hudson주소 : http://hudson-ci.org

환경 세팅 : JAVA_HOME=JDK경로, CATALINA_HOME=TOMCAT경로

아래 방법은 webapp에 복사 없이 hudson context 추가하는 방식이다. 
1. hudson.war 전용 디렉토리를 생성한다
예 : /Users/사용자../Server/hudson/
2. hudson.war를 복사한다
3. tomcat이 설치된 디렉토리로 이동 후 conf/ 폴더로 이동한다
4.conf 디렉토리내 Catalina / localhost 로 이동한다
예 : ${tomcathome}/conf/Catalina/localhost
5. hudson.xml 을 생성한다 (vi hudson.xml)
6.xml 에 hudson의 Context정보를 입력한다.
<?xml version='1.0' encoding='utf-8'?>
<Context path="/hudson"   docBase=“…hudson.war 가 위치한 디렉토리…"   debug="0"   reloadable="true"   crossContext="true" />

7. tomcat를 재시작한다
8. http://localhost:8080/hudson 으로 접속하여 hudson을 확인한다

'CI 설정' 카테고리의 다른 글

OSx 시작 서비스 등록  (0) 2011.01.17


C#에서 싱글톤 구현할 때

public class CommonUtil
{

    private static CommonUtil instance;

    private CommonUtil() { }

    public static CommonUtil Instance
    {
        get
        {
            lock(syncRoot)  // 멀티스레드에서 원자 상태를 유지하기 위해
            {
               if (instance == null)
               {
                   instance = new CommonUtil();
                }
            }
            return instance;
        }
    }
}




'LivePhoto개발' 카테고리의 다른 글

C# HMAC-SHA1 암호화  (2) 2010.11.09
C# Byte <-> String 문자열 변환  (0) 2010.11.09
환경설정 주의사항  (0) 2010.11.05
플러그인 프로젝트 세팅 순서  (0) 2010.11.05
라이브포토 기본 실행순서  (0) 2010.11.05

실행순서

start or main -> isFinished -> YES -> stop
                                       -> NO -> suspended


@interface TestQueue : NSOperation {

 NSString * i_Id;
 NSOperationQueue * i_queue;
}

-(id)initWithId:(NSString *)qid inOperationQueue:(NSOperationQueue *) queue;

@end


@implementation TestQueue
-(id)initWithId:(NSString *)qid inOperationQueue:(NSOperationQueue *) queue
{
 if(self=[super init])
 {
  i_Id = qid;
  i_queue = [queue retain];
 }
 
 return self;
}
- (void)main
{
 NSLog(@"[%d] Queue Main : %@",[i_queue operationCount], i_Id);
 return;
}
/*
- (void)start
{
 NSLog(@"Queue Start : %@", i_Id);
}*/
- (void)stop
{
 NSLog(@"Queue Stop : %@", i_Id);
}
- (void)dealloc
{
    [i_queue release];  
 
 [super dealloc];
}
- (void)cancel
{
 NSLog(@"Queue Cancel : %@", i_Id);
 
 [super cancel];
}
- (BOOL)isFinished
{
 NSLog(@"Queue Finished : %@", i_Id);
 
 return YES;
}

@end

'iOS' 카테고리의 다른 글

Custom UINavigationController  (0) 2011.01.24
iPhone TestCase 생성  (0) 2011.01.18
NSOperationQueue  (0) 2011.01.10
NSNotificationCenter  (0) 2011.01.05
NSSearchPathForDirectoriesInDomains  (0) 2011.01.05


NSOperationQueue

The NSOperationQueue class regulates the execution of a set of NSOperation objects. After being added to a queue, an operation remains in that queue until it is explicitly canceled or finishes executing its task. Operations within the queue (but not yet executing) are themselves organized according to priority levels and inter-operation object dependencies and are executed accordingly. An application may create multiple operation queues and submit operations to any of them.

NSOperationQueue클래스는 NSOperation객체의 집합을 실행을 조절한다. 큐를 추가한 후, 연산의 테스크가 실행하여 끝나던가 취소하기 전까지 큐안에 남아있다. 큐안에 연산은 레벨 순위와 내부연산객체의 의존관계에 따라 조직되고 실행된다. 어플리케이션은 멀티 연산 큐를 생성하고 누구라도 연산을 수행한다 

Inter-operation dependencies provide an absolute execution order for operations, even if those operations are located in different operation queues. An operation object is not considered ready to execute until all of its dependent operations have finished executing. For operations that are ready to execute, the operation queue always executes the one with the highest priority relative to the other ready operations. For details on how to set priority levels and dependencies, see NSOperation Class Reference.

연산은 다른 연산 큐에 위치하고 있지만, 내부연산 의존관계는 연산에 대한 확실한 실행 순서를 제공한다. 연산 객체는 모든 연관된 연산이 끝나기 전까지 실행에 대한 준비를 하지 않는다. 실행을 위해 준비가 되는 연산에 대해 연산 큐는 언제나 다른 준비된 연산에 대한 가장 높은 우선 순위로 실행된다. 우선순위와 의존관계에 대해 자세하고 알고 싶다면 NSOperation 클래스 레퍼런스를 확인해라

You cannot directly remove an operation from a queue after it has been added. An operation remains in its queue until it reports that it is finished with its task. Finishing its task does not necessarily mean that the operation performed that task to completion. An operation can also be canceled. Canceling an operation object leaves the object in the queue but notifies the object that it should abort its task as quickly as possible. For currently executing operations, this means that the operation object’s work code must check the cancellation state, stop what it is doing, and mark itself as finished. For operations that are queued but not yet executing, the queue must still call the operation object’s start method so that it can processes the cancellation event and mark itself as finished.

큐에 추가한 후 연산을 직접 제거하는건 불가능하다. 이 연산은 테스크가 끝났다고 알리기 전까지 큐에 남아있다. 태스크 종료는 연산이 완료를 반드시 의미하지 않다. 연산 취소가능하다. 연산객체의 취소는 큐안에 객체가 떠나며 가능한 빠르게 태스크에 대해 거부됨을 객체에 알린다. 최근 실행하는 연산에 대해 객체의 작업이 어떤 이유로 멈추었는지 취소상태를 확인하는 코드가 필요하다. 아직 실행되지 않은 기다리고 있는 연산에 대해, 큐는 연산객의 시작 메소드가 호출되도록 이벤트 취소와 종료 상태를 진행 할수 있다

Operation queues usually provide the threads used to run their operations. In Mac OS X v10.6 and later, operation queues use the libdispatch library (also known as Grand Central Dispatch) to initiate the execution of their operations. As a result, operations are always executed on a separate thread, regardless of whether they are designated as concurrent or non-concurrent operations. In Mac OS X v10.5, however, operations are executed on separate threads only if their isConcurrent method returns NO. If that method returns YES, the operation object is expected to create its own thread (or start some asynchronous operation); the queue does not provide a thread for it.

연산 큐는 보통 그들의 연산 실행에 사용되는 스레드를 제공한다. Mac OS X 10.6, 이후 버전은 연산 큐는 연산들의 실행핼을 초기화 시키는 libdispatch라이브러리를 사용한다. 그 결과 병행이나 비병행 연산으로 디자인이 되어있더라도 연산은 언제나 분리된 스레드 상에서 실행되어진다. 하지만 10.5에서 연산은 오직 병행 메소드 결과가 NO 일때 분리된 스레드로 수행이 된다. 만약 메소드의 결과가 YES인 경우 연산 객체는 고유한 스레드가 생성될 (이거나 비동기 연산 시작할때) 것이다.

예제

 @interface testObj : NSOperation
{
 
}

@end

NSOperationQueue    *i_Queue;

testObj *qObj = [[testObj alloc]init];

[i_Queue addOperation:qObj];

[qObj release];

'iOS' 카테고리의 다른 글

iPhone TestCase 생성  (0) 2011.01.18
NSOperation  (0) 2011.01.11
NSNotificationCenter  (0) 2011.01.05
NSSearchPathForDirectoriesInDomains  (0) 2011.01.05
Reachability & SCNetworkReachability  (0) 2011.01.04


NSNotificationCenter

An NSNotificationCenter object (or simply, notification center) provides a mechanism for broadcasting information within a program. An NSNotificationCenter object is essentially a notification dispatch table.

NSNotificationCenter 객체는 프로그램내 broadcasting에 대한 메커니즘에을 제공한다.
이 객체는 통지처리 테이블(notification dispatch table)을 기본으로 한다

Objects register with a notification center to receive notifications (NSNotification objects) using the addObserver:selector:name:object: or addObserverForName:object:queue:usingBlock: methods. Each invocation of this method specifies a set of notifications. Therefore, objects may register as observers of different notification sets by calling these methods several times.

객체는 addObserver:selector:name:object: 나 addObserverForName:object:queue:usingBlock: methods를
사용하여 NSNotificationCenter 객체를 알림센터(notification center)에 등록한다

When an object (known as the notification sender) posts a notification, it sends an NSNotification object to the notification center. The notification center then notifies any observers for which the notification meets the criteria specified on registration(지정된 표준 등록) by sending them the specified notification message, passing the notification as the sole argument.
 
객체(notification sender로 알려진..) 알림을 발송 할 때 알림센터에 NSNotification 객체를 보낸다.

A notification center maintains a notification dispatch table which specifies a notification set for a particular observer. A notification set is a subset of the notifications posted to the notification center. Each table entry contains three items:

알림센터는 특별한 observer에 대한 알림집합이 명시된 알림 발송 테이블을 유지한다. 알림집합은 알림센터에 보내지는 알림의 하위집합이다. 각 테이블 엔트리는 3가지 항목을 포함한다

Notification observer: Required. The object to be notified when qualifying notifications are posted to the notification center.

Notification name: Optional. Specifying a name reduces the set of notifications the entry specifies to those that have this name.

Notification sender: Optional. Specifying a sender reduces the set of notifications the entry specifies to those sent by this object.

Table 1 shows the four types of dispatch table entries and the notification sets they specify. (This table omits the always present notification observer.)


defaultCenter

Returns the process’s default notification center.

+ (id)defaultCenter
Return Value

The current process’s default notification center, which is used for system notifications.

Availability
  • Available in iOS 2.0 and later.

예제

옵저버 등록

NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];

[defaultCenter addObserver:self  // 센터에 옵저버 등록 
                            selector:@selector(reachabilityChanged:)   // 옵저버가 가지고 있는 메소드 셀렉터 -> self(appDelegate)의 reachabilityChanged: 호출
                               name:Na_STR_REACHABILITY_NOTIFICATION // 메세지를 보내서 알리고 싶은 노티피케이션명을 지정
                               object:nil // 특정 객체가 포스팅한 통지만 받고 싶을 때 지정
];


옵저버 삭제

[removeObserver:@selector(reachabliityChanged)]





----NotificationObj.h--------
#import <Foundation/Foundation.h>

@interface NotificationObj : NSObject {

}
- (void) callChange;
- (void) regNotification;
- (void) postNotification;

@end


----NotificationObj.m--------
#import <Foundation/Foundation.h>
#import "NotificationObj.h"

@implementation NotificationObj

- (void) regNotification {
 
 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
 
 // 네트워크 연결 상태가 변경할 때 마다 노티피케이션을 포스트하기 위해 defaultCenter에 옵저버 등록
 [defaultCenter addObserver:self
       selector:@selector(callChange) 
        name:@"CALL_CHANGE"  
      object:nil];
}

- (void) postNotification {
 
 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
 [defaultCenter postNotificationName:@"CALL_CHANGE"  
        object:self];
}

- (void) callChange {
 
 NSLog(@"Notification Post");
}

@end                   

----main.m--------
#import <Foundation/Foundation.h>
#import "NotificationObj.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

 NotificationObj * nObj = [[NotificationObj alloc] init];
   
 [nObj regNotification];
 
 [nObj postNotification];
 
 [pool release];
 
    return 0;
}

'iOS' 카테고리의 다른 글

NSOperation  (0) 2011.01.11
NSOperationQueue  (0) 2011.01.10
NSSearchPathForDirectoriesInDomains  (0) 2011.01.05
Reachability & SCNetworkReachability  (0) 2011.01.04
NSUserDefaults  (0) 2011.01.04


NSSearchPathForDirectoriesInDomains

NSArray * NSSearchPathForDirectoriesInDomains (
   NSSearchPathDirectory directory,
   NSSearchPathDomainMask domainMask,
   BOOL expandTilde
);

Discussion

Creates a list of path strings for the specified directories in the specified domains.
The list is in the order in which you should search the directories.If expandTilde is YES, tildes are expanded as described in stringByExpandingTildeInPath.For more information on file system utilities, see Locating Directories on the System.

지정된 도메인안에 지정된 디렉토리에 대한 경로 문자열의 리스트를 생성 한다. 리스트는 디렉토리를 찾는 곳이다.
만약 expandTilde가 YES라면 tildes는 stringByExpandingTildeInPath안에 명시된 것 거럼 확장된다.
파일 시스템 유틸에 대해 좀 더 정보를 원한다면 Locating Dirctories on the System을 보라

NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);    
NSString *cacheDirectory = [paths objectAtIndex:0];

결과 : /Users/.../Library/Application Support/iPhone Simulator/4.2/Applications/DD5D66BF-AA44-4B03-A479-1423B1930444/Library/Caches

'iOS' 카테고리의 다른 글

NSOperationQueue  (0) 2011.01.10
NSNotificationCenter  (0) 2011.01.05
Reachability & SCNetworkReachability  (0) 2011.01.04
NSUserDefaults  (0) 2011.01.04
IPhon Welcome Image  (0) 2011.01.04
Reachability

Reachability  아이폰과 아이팟터치의 네트워크 상태를 모니터하는 SystemConfiguration framework를 사용하는 데모 샘플이다.
이 예제는 IP routed와 트래픽이 EDGE나 3G와 같은 WWAN인터페스를 통해 route되는 방법을 설명하였다.

http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html

SCNetworkReachability

SCNetworkReachability 인터페이스는 시스템의 현재 네트워크 상태와 타겟 호스트의 도달가능성을 결정하는 응용프로그램을 가능하게 한다.

네트워크 스택안에 있는 응용프로그램에 의해 보내진 데이터 패킷이 로컬 장비를 떠나게 될때 도달가능한지 결정한다. Reachability는 데이터 패킷이 실제로 호스트에 받았는지 보장하지 않는다.

SCNetworkReachability 프로그래밍 인터페이스는 비동기와 동기 모델을 지원한다. 동기 모델에서 SCNetworkReachabilityGetFlags 함수에 의해 도달 상태를 얻을 수 있다. 비동기 모델에서는 클라이언트 객체의 스레드의 run loop상에서 SCNetworkReachability 객체를 스케줄 할수 있다.

클라이언트는 원격 호스트 reachability 상태가 변할 때 알림을 받은 콜백 함수에 적용된다

'iOS' 카테고리의 다른 글

NSNotificationCenter  (0) 2011.01.05
NSSearchPathForDirectoriesInDomains  (0) 2011.01.05
NSUserDefaults  (0) 2011.01.04
IPhon Welcome Image  (0) 2011.01.04
메소드 함수 가변인수 정의  (0) 2010.12.28

목적 : NSUserDefaults 클래스는 시스템과 의사소통하는 계획된 인터페이스를 제공한다.(환경값 저장)
예 : 사용자 화면 출력 단위, 자동 저장여부

방법
저장 : [[NSUserDefaults standardUserDefaults] setInteger:KEY_VALUE forKey:KEY_NAME];
읽기 : [[NSUserDefaults standardUserDefaults] integerForKey:KEY_NAME];

'iOS' 카테고리의 다른 글

NSNotificationCenter  (0) 2011.01.05
NSSearchPathForDirectoriesInDomains  (0) 2011.01.05
Reachability & SCNetworkReachability  (0) 2011.01.04
IPhon Welcome Image  (0) 2011.01.04
메소드 함수 가변인수 정의  (0) 2010.12.28
아이폰 앱이 처음 실행될때 화면에 보이는

스플래쉬 애니메이션 이미지는 설정이 따로 있는게 아니라 Resources 폴더내

Default.png 이름으로 설정하면 된다.

'iOS' 카테고리의 다른 글

NSNotificationCenter  (0) 2011.01.05
NSSearchPathForDirectoriesInDomains  (0) 2011.01.05
Reachability & SCNetworkReachability  (0) 2011.01.04
NSUserDefaults  (0) 2011.01.04
메소드 함수 가변인수 정의  (0) 2010.12.28

사용목적 : printf와 같이 동일 객체 받아들일 수 있는 가변 인수를 생성할때

메소드 정의

@interface 클래스명
- (반환타입) 메소드명 : (인자 타입)가변인자명, ... NS_REQUIRES_NIL_TERMINATION;
@end


NS_REQUIRES_NIL_TERMINATION
-> 가변 인수의 마지막에 NULL이나 nil을 두어 인수의 끝을 표시, NULL을 입력 못할 경우 오작동
-> 함수의 프로토타입 선언 끝에 매크로를 기술하여 이런 잠재 위험에 대처


메소드 구현

@implementation 클래스명
-(반환타입) 메소드명 : 가변인자, ...
{
va_list varglist;       // 가변인자를 리스트 형으로 받을 임시 객체

va_start(varglist, 가변인자);   // 가변인자를 리스트형으로 변환

while((item = va_arg(varglist, 인자타입)) != nil) {
// 지정한 인자타입의 item을 사용
}

va_end(varglist);   // 가변인자 종료
}
@end


'iOS' 카테고리의 다른 글

NSNotificationCenter  (0) 2011.01.05
NSSearchPathForDirectoriesInDomains  (0) 2011.01.05
Reachability & SCNetworkReachability  (0) 2011.01.04
NSUserDefaults  (0) 2011.01.04
IPhon Welcome Image  (0) 2011.01.04

+ Recent posts