RSS를 읽어 오는 간단한 리더기를 만들어 보겠습니다. 맥에서는 NSXMLDocument란 편리한 클래스가 있지만 아이폰 SDK에는 포함되어 있지 않습니다. 그렇기 때문에 NSXMLParser를 사용해서 RSS xml을 읽어오는 간단한 샘플을 만들어 보겠습니다.

인터넷을 통해 데이터를 가져오는 부분은 이전  "NSURLConnection으로 웹페이지 내용 가져오기"란 포스팅을 참고 하시기 바랍니다. 여기서는 파싱하는 부분만 간단히 살펴보겠습니다.


1. NSXMLParser 생성
xml 데이터 파싱은 네트워크로 데이터 수신이 완료된 후 불려지는 connectionDidFinishLoading 메소드에서 아래와 같이 처리합니다.

NSXMLParser *parser = [[NSXMLParser alloc] initWithData:receiveData];

[parser setDelegate:self];
[parser parse];
[parser release];

NSXMLParser 오브젝트를 수신된 데이터가 저장된 NSData 타입의 receiveData를 인자로 초기화를 합니다. setDelegate 메소드로 현재 오브젝트를 NSXMLParser의 딜리케이트로 지정합니다. 지정된 오브젝트는 요소별로 파싱의 시작/종료와 파싱된 스트링을 받을 수 있는 메소드를 구현해야 합니다.

parse 메소드로 파싱이 시작됩니다. 파싱은 자동으로 처리되지 않으며, 각 단계별로 딜리게이트된 메소드를 구현하여 필요와 형식에 맞게 직접 처리해야 합니다.

2. Delegate 메소드 구현
NSXMLParser에는 많은 딜리게이트 메소드가 있지만 가장 중요하고 거의 반드시 구현해야될 메소드는 parser:didStartElement, parser:foundCharacters, parser:didEndElement입니다.

parser:didStartElement로 한 요소의 파싱이 시작됨을 알수 있습니다. parser:foundCharacters로 해당 문자열들이 넘어 옵니다. 토큰 단위로 넘어 오기 때문에 넘어 오는 문자열들을 계속 저장해야 합니다. parser:didEndElement가 실행되면 비로소 한 요소의 파싱이 끝난 것을 알 수 있습니다. 이 메소드에서 해당 요소에 따른 필요한 처리를 합니다.

1) 시작 메소드 구현
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    if ([elementName isEqualToString:@"item"])
        elementType = etItem;
   
    [xmlValue setString:@""];
}

두번째 인자인 elementName으로 해당요소의 이름이 전달됩니다. 세번째와 네번째 인자는 네임스페이스와 관련된 uri와 전체이름이 전달됩니다. 만약 해당 xml이 네임스페이스를 사용한다면 이전에 [parser setShouldProcessNamespaces:YES];로 네임스페이스를 처리하도록 설정해야 합니다. NSXMLParser의 shouldProcessANamespace의 기본값은 NO 입니다.

마지막 인자인 attributeDict에는 해당 요소의 속성들이 전달됩니다. 만약 <item lang="ko"> 와 같이 되어 있다면 attributeDict 딕셔너리에 key가 'lang', value가 'ko'로 저장되어 전달됩니다.

여기서는 다른 인자들은 무시하고 item이란 이름의 요소가 시작될때 부터 데이터들을 저장하도록 요소이름이 item인지만 확인합니다. 그리고 xmlValue에 새로운 데이터를 저장하기 위해 이전에 저장된 값들을 초기화합니다.

2) 데이터 저장 메소드 구현
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (elementType == etItem) {
        [xmlValue appendString:string];
    }
}
토큰별로 넘어오는 문자열을 xmlValue에 저장합니다.

3) 종료 메소드 구현
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    if (elementType != etItem)
        return;

    if ([elementName isEqualToString:@"title"]) {
        [currectItem setValue:[NSString stringWithString:xmlValue] forKey:elementName];
    } else if ([elementName isEqualToString:@"link"]) {
        [currectItem setValue:[NSString stringWithString:xmlValue] forKey:elementName];
    } else if ([elementName isEqualToString:@"description"]) {
        [currectItem setValue:[NSString stringWithString:xmlValue] forKey:elementName];
    } else if ([elementName isEqualToString:@"category"]) {
        [currectItem setValue:[NSString stringWithString:xmlValue] forKey:elementName];
    } else if ([elementName isEqualToString:@"pubDate"]) {
        [currectItem setValue:[NSString stringWithString:xmlValue] forKey:elementName];
    } else if ([elementName isEqualToString:@"item"]) {
        [xmlParseData addObject:[NSDictionary dictionaryWithDictionary:currectItem]];
    }
}

한 요소가 끝날때 호출됩니다. 여기서는 RSS의 title, link, description, category, pubData 항목들만 currentItem 딕셔너리에 저장합니다. 한 포스팅의 마지막 요소인 </item>일 경우에는 xmlParseData에 현재 딕셔너리를 추가합니다.

3. 테이블뷰 출력
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [xmlParseData 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 *dict = [xmlParseData objectAtIndex:indexPath.row];
    [[cell textLabel] setText:[dict objectForKey:@"title"]];
   
    return cell;
}

여기서 테이블뷰는 아무 동작을 하지않으며 xmlParseData에 저장된 해당 title만 출력합니다. 빌드 후 실행하면 아래와 같이 해당 RSS의 제목이 출력되는 것을 확인할 수 있습니다.

간단한 RSS 리더기를 구현해 보았습니다. 전체 소스는 아래의 압축파일을 다운로드 받아 확인하실 수 있습니다. 정확하고 자세한 내용은 아이폰 개발자 센터에서 제공하는 Introduction to Event-Driven XML Programming Guide for Cocoa 문서 또는 SeismicXML 샘플코드를 확인하시기 바랍니다.

'iOS' 카테고리의 다른 글

아이폰 OS 4  (8) 2010.04.09
인터페이스빌더 Table View Cell 사용하기  (0) 2009.06.25
cocos2d 개발환경 설정  (24) 2009.04.13
iPhone SDK 3.0 beta 2  (4) 2009.04.05
UITableView의 메모리 누수 현상  (4) 2009.02.05
AND

집의 맥에서도 아이폰 개발환경을 만들기 위해 프로비져닝 코드를 등록하는 작업을 하고, 간단히 정리해 보았습니다.

1. 기존에 설치된 맥
아이폰 개발자 포털에서 발급받은 인증서가 설치된 기존의 맥에서 키체인 접근을 실행합니다. 키체인 접근은 응용 프로그램 아래에 유틸리티 디렉토리에 있습니다.

인증서 항목을 보면 기존에 등록해 놓은 인증서들이 있습니다. 다른 시스템에 등록할 해당 인증서를 마우스 우클릭을 한 후에 '보내기' 메뉴를 클릭합니다.


적당한 이름을 입력하고 파일포맷을 .p12로 되어 있는 것을 확인한 후에 저장 버튼을 클릭합니다. 

패스워드를 설정 창이 뜨면 사용할 패스워드를 지정합니다. 이 패스워드는 다른 시스템에서 다시 인증서를 등록할 때 사용합니다.
위에서 저장한 *.p12 파일을 새로 설치할 맥으로 복사합니다.

2. 새로 설치할 맥
위에서와 동일하게 키체인 접근을 실행하고, 파일 메뉴에서 항목 가져오기를 클릭합니다. 파일 선택창이 뜨면 기존 시스템에서 복사온 .p12 파일을 선택합니다.

이전 시스템에서 등록한 패스워드를 입력합니다.
애플의 아이폰 프로그램 개발자 포털에서 개발(또는 배포) 프로비져닝 프로파일을 다운로드 받습니다. 다운로드 받은 파일을 Xcode로 드래그합니다. 아래와 같이 Xcode에서 설정에서 해당 프로파일이 등록되어 있는 것을 확인할 수 있습니다. 만약 항목이 비활성화되어 있으면 인증서가 제대로 설치되지 않은 것입니다.



어플리케이션 로더로 바이너리 업로드시, 아이폰 개발자로 등록된 아이디가 틀릴 경우에는 Wiondow 메뉴에서 Run Setup Wizard... 를 클릭하여 새로운 아이디, 패스워드를 설정합니다.

'App Store' 카테고리의 다른 글

한국사 연표 어플리케이션  (10) 2010.03.23
스모킹 카운터 한글화  (4) 2010.02.22
아이폰 어플리케이션 업로드  (2) 2009.06.08
App들 업그레이드  (2) 2009.05.28
앱스토어에 대한 소고 - 1  (4) 2009.05.09
AND

1950년대 초부터 프로그래밍을 시작한 1세대 개발자인 로버트 L. 글래스가 쓴 책입니다. 1995년에 초판이 나왔고, 이후 2006년에 내용을 변경하고 추가하여 재발행되었습니다. 머리가 못 따라가 같은 저자가 쓴 소프트웨어 컨플릭트 2.0을 괴로워하면서 읽은 경험이 있기에 선뜻 읽을 마음이 들지 않았습니다. 하지만 결국은 읽어보게 되었습니다.

역시나 소프트웨어 컨플릭트 2.0과 같이 수필에 가까운 내용으로 정확하게 정답을 제시해 주거나 확실한 결말이나 선택이 없는 경우가 많습니다. 그 대신에 저자의 생각, 경험과 함께 각종 자료들을 제시해 주어 독자들에게 생각할 거리, 숙제를 내준다는 느낌입니다. 하지만 개인적으로는 소프트웨어 컨플릭트 2.0 보다는 훨씬 읽기가 편했습니다.

소프트웨어 크리에이티비티 2.0
카테고리 컴퓨터/IT
지은이 로버트 L. 글래스 (위키북스, 2009년)
상세보기

창의성에 관한 직접적인 내용 보다는 "관리층, 학계, 통제, 관리, 방법론, 정형기법, 측정, 프로세스, 이론"  VS "실무자, 업계, 경험, 자율, 애자일, 유연성"을 주로 다루고 있습니다. 양 진영간의 대립에 중간자적인 입장을 취하는 것 같지만, 대부분 후자에 힘을 실어 주고 있습니다. 제목에 나와 있는 창의력에 밀접한 주제는 뒷부분에 언급하고 있으나 이 역시 추상적입니다. 창의력이란 것 자체가 추상적이니 어쩔 수 없을 것 같습니다.

"9.4 잃어버린 재미를 찾습니다"란 장에는 아래와 같은 내용이 있습니다.

재미. 바로 이것이 소프트웨어의 핵심이 아니던가. 소프트웨어로 먹고 자고 숨쉬는 우리가 이 일을 계속하는 이유는 재미있기 때문이다.

...중략...

정말이지 어찌 된 영문일까? 경력이 쌓였다. 보수도 올랐다. 책임감도 커졌다. 책도 몇 권 냈고, 칼럼도 몇 개 썼다. 연구도 했고, 논문도 몇 편 냈다. 모든 소년 소녀가 꿈꾸는 미래가 아닌가! 하지만 그 와중에 나는 뭔가를 잃어버렸다. 되찾고 싶어서 여러분에게 도움을 청하는 바이다.

이 책과 소프트웨어 컨플릭트 2.0을 재출간 했던 2006년 당시에 저자는 75세의 나이였습니다. 그 나이에 과연 무엇을 다시 되찾고 싶었을까요? 소프트웨어 개발에 관한 그의 끊임없는 관심과 열정은 놀랍기까지 합니다. 내용에 있어서 다소 산만하고 추상적인 부분은 있지만, 작가의 오랜 경험에서 나온 각종 지식, 예시, 시각들을 엿보고 같이 생각해볼 수 있는 재미있는 책인 것 같습니다.

'책 이야기 > IT 일반' 카테고리의 다른 글

미래를 만든 Geeks  (1) 2010.06.24
번역서의 표지 디자인  (8) 2009.08.31
드리밍 인 코드  (2) 2009.05.20
레이몬드 첸의 윈도우 개발 282 스토리  (0) 2008.01.18
스티브 워즈니악  (4) 2007.12.31
AND