본문 바로가기

General/iOS

[iPhone] parsing, tableview

코드 출처 : http://blog.naver.com/jforyoum/60119769178


전체적으로 코드를 훑어보기 위해서 작성한 글


android에서의 domain
역시 따로 클래스를 만들어 놓고 쓰는듯.
책정보들을 파싱할 경우 (예제 xml - http://sites.google.com/site/iphonesdktutorials/xml/Books.xml)
Book 이라는 클래스를 NSObject를 상속받아 만듬.

//  Book.h


#import <Foundation/Foundation.h>


@interface Book : NSObject 

{

//attribute 해당하는 변수

NSInteger bookID;

//element 해당하는 변수 - 되도록 태그명과 변수명을 일치시키는 것이 좋다.

NSString *title;

NSString *author;

NSString *summary;

}

@property (nonatomic) NSInteger bookID;

@property (nonatomic, retain) NSString *title;

@property (nonatomic, retain) NSString *author;

@property (nonatomic, retain) NSString *summary;


@end 

//  Book.m


#import "Book.h"


@implementation Book


@synthesize title, author, summary, bookID;


- (void) dealloc 

{

//id int이므로 release 필요가 없다.

[summary release];

[author release];

[title release];

[super dealloc];

}

@end  







xml parser
NSObject를 상속받아 만들고, NSXMLParserDelegate를 연결해줌
initXMLParser와 start/endElement 및 character 메소드 구현
android, java에서도 SAXParser를 사용하면, 4가지 핸들러중 하나를 구현(implements)하거나,
아래처럼 커스텀해서 사용할 것만 override해서 디폴트핸들러로 만드는(extends) 방법이 있다.
어쨋든 SAX 파서를 사용한듯

//  XMLParser.h : 실제 파싱에 이용할 클래스


#import <Foundation/Foundation.h>


//클래스 전방선언

@class XMLParsingAppDelegate, Book;


@interface XMLParser : NSObject <NSXMLParserDelegate>

{

//데이터 배열에 접근하기 위해서 필요한 AppDelegate객체에 대한 포인터

XMLParsingAppDelegate *appDelegate;


//파싱에 사용할 임시 변수

NSMutableString *currentElementValue;

Book *aBook;

}


//appDelegate변수 초기화를 위한 메서드

- (XMLParser *) initXMLParser;


@end  

//  XMLParser.m


#import "XMLParser.h"


//전방선언 클래스에 대한 헤더파일을 import

#import "XMLParsingAppDelegate.h"

#import "Book.h"


@implementation XMLParser

- (XMLParser *)initXMLParser 

{

self = [super init];

if(self != nil)

//AppDelegate객체에 대한 포인터를 만드는 방법 - 중요

appDelegate = (XMLParsingAppDelegate *)[[UIApplication sharedApplication] delegate];

return self;

}


//시작 태그를 만났을 호출되는 메서드

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName

  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName

attributes:(NSDictionary *)attributeDict

{

//Books 만나면 파일의 시작을 만난 것이므로 데이터 배열의 메모리 할당

if([elementName isEqualToString:@"Books"]) 

{

appDelegate.books = [[NSMutableArray alloc] init];

}

      //Book 만나면 하나의 데이터 시작을 만난 것이므로 하나의 데이터를 메모리 할당 - id 찾아와서 저장

else if([elementName isEqualToString:@"Book"]) 

{

aBook = [[Book alloc] init];

aBook.bookID = [[attributeDict objectForKey:@"id"] integerValue];

}

}


// 태그(element) 만났을 호출되는 메서드

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 

{

//처음 호출되는 것이라면  currentElementValue 메모리 할당하고 string대입

if(!currentElementValue) //currentElementValue YES 아니라면 == nil 이라면

currentElementValue = [[NSMutableString alloc] initWithString:string];

//처음 호출되는 경우가 아니라면 이전 데이터에 이어 붙이기

else

[currentElementValue appendString:string];

}


//종료태그를 만났을 호출되는 메서드

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 

{

if([elementName isEqualToString:@"Books"]) //닫는 태그가 Books라면 파일의 끝이므로 종료

return;

//Book이라면 하나의 데이터 종료이므로 데이터배열에 저장하고 초기화

if([elementName isEqualToString:@"Book"]) 

     //닫는 태그가 Book이라면 지금까지 만든 aBook Books 대입

{

[appDelegate.books addObject:aBook];

[aBook release];

aBook = nil;

}

//그외의 태그는 태그명에 해당하는 변수에 currentElementValue 저장하고 초기화

else 

     //닫는 Books Book 아니라면 == element 만났다면.

[aBook setValue:currentElementValue forKey:elementName]; 

          //변수명을 맞췄을 경우 요렇게만 써줘도 된다.아니면 if 써야함.

[currentElementValue release];

currentElementValue = nil;

}


- (void) dealloc 

{

[aBook release];

[currentElementValue release];

[super dealloc];

}


@end  






RootViewController 
android에서 activity라고 보면 되겠다. 셀을 커스텀 한다면 새로만든 커스텀셀 클래스는 adpater로 생각하면 될듯한다.
이 예제는 Navigation-based 로 프로젝트를 생성했다.
View-based 로 프로젝트를 생성했을때, ViewController라고 생각하면 될듯하다.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
메소드가 구현되어있다.
데이터는 밖에서 사용하지 않을건지 프로퍼티와 신디사이즈가 없다.

// h


#import <UIKit/UIKit.h>


@class XMLParsingAppDelegate, DetailView; // DetailView : 하위데이터 출력


@interface RootViewController : UITableViewController

{

XMLParsingAppDelegate *appDelegate;

DetailView *detailController;

}


@end  

//  RootViewController.m


#import "RootViewController.h"

#import "XMLParsingAppDelegate.h"

#import "Book.h"

#import "DetailView.h"


@implementation RootViewController


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 

{

    return 1;

}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 

{

    return [appDelegate.books 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];

    }

    

    Book *aBook = [appDelegate.books objectAtIndex:indexPath.row];

    cell.textLabel.text = aBook.title;

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;


    return cell;

}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 

{

    if(detailController == nil)

    detailController = [[DetailView alloc]init];

    Book *aBook = [appDelegate.books objectAtIndex:indexPath.row];

    detailController.aBook = aBook;

    [self.navigationController pushViewController:detailController animated:YES];

}


- (void)didReceiveMemoryWarning 

{

    [super didReceiveMemoryWarning];

}


- (void)viewDidUnload {}


- (void)viewDidLoad

{

    [super viewDidLoad];

    appDelegate = (XMLParsingAppDelegate *)[[UIApplication sharedApplication] delegate];

    //포인터 생성

    self.title = @"Books";

}


- (void)dealloc 

{

    [detailController release];

    [appDelegate release];

    [super dealloc];

}



@end 





AppDelegate

// XMLParsingAppDelegate.h : 클래스의 배열


#import <UIKit/UIKit.h>


@interface XMLParsingAppDelegate : NSObject <UIApplicationDelegate> 

{

UIWindow *window;

    UINavigationController *navigationController;

//파싱한 데이터를 저장할 배열 - Book객체들의 배열

//무조건 프로퍼티를 만들어야 - 밖에서 출력해야 하므로.

NSMutableArray *books;

}


@property (nonatomic, retain) IBOutlet UIWindow *window;

@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;


@property (nonatomic, retain) NSMutableArray *books;


@end

//  XMLParsingAppDelegate.m


#import "XMLParsingAppDelegate.h"

#import "RootViewController.h"

//실제 파싱에 이용할 클래스의 헤더파일 import

#import "XMLParser.h"


@implementation XMLParsingAppDelegate


@synthesize window;

@synthesize navigationController;

@synthesize books;


#pragma mark -

#pragma mark Application lifecycle


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

{    

    

NSURL *url = [[NSURL alloc] initWithString:@"http://sites.google.com/site/iphonesdktutorials/xml/Books.xml"];

NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];

XMLParser *parser = [[XMLParser alloc] initXMLParser];

//xmlParser parser객체에게 delegate 있는 메서드들의 처리를 위임

[xmlParser setDelegate:parser];

//실제 데이터 파싱 시작 - 성공하면 YES 리턴하고 실패하면 NO 리턴

BOOL success = [xmlParser parse];

if(success)

{

UIAlertView * dlg = [[UIAlertView alloc]initWithTitle:@"파싱 결과" message:@"성공" delegate:nil cancelButtonTitle:@"확인" otherButtonTitles:nil];

[dlg show];

[dlg release];

}

else

{

UIAlertView * dlg = [[UIAlertView alloc]initWithTitle:@"파싱 결과" message:@"실패" delegate:nil cancelButtonTitle:@"확인" otherButtonTitles:nil];

[dlg show];

[dlg release];

}

[window addSubview:navigationController.view];

    [window makeKeyAndVisible];


    return YES;

}


- (void)applicationWillResignActive:(UIApplication *)application {}

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

- (void)applicationWillEnterForeground:(UIApplication *)application {}

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

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

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {}


- (void)dealloc 

{

[books release];

[navigationController release];

[window release];

[super dealloc];

}


@end 







TableView

//  DetailView.h


#import <UIKit/UIKit.h>


@class Book;


@interface DetailView : UIViewController <UITableViewDelegate, UITableViewDataSource>

{

UITableView *tableView;

//상위 컨트롤러로부터 데이터를 넘겨받을 변수 - 당연히 프로퍼티가 있어야

Book *aBook;

}

@property (nonatomic, retain) Book *aBook;


@end

//  DetailView.m


#import "DetailView.h"

#import "Book.h"


@implementation DetailView


@synthesize aBook;


- (void)viewDidLoad 

{

    [super viewDidLoad];

    self.title = @"세부 정보";

tableView = [[UITableView alloc]initWithFrame:CGRectMake(0,0, 320, 400) style:UITableViewStyleGrouped];

tableView.delegate = self;

tableView.dataSource = self;

[self.view addSubview:tableView];

}


- (void)viewWillAppear:(BOOL)animated 

{

[super viewWillAppear:animated];

[tableView reloadData];

}


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 

{

    return 3;

}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 

{

    return 1;

}


- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath 

{    

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil

{

        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];

    }

switch(indexPath.section)

{

case 0:

cell.textLabel.text = aBook.title;

break;

case 1:

cell.textLabel.text = aBook.author;

break;

case 2:

cell.textLabel.text = aBook.summary;

break;

}

return cell;

}


- (NSString *)tableView:(UITableView *)tblView titleForHeaderInSection:(NSInteger)section 

{

NSString *sectionName = nil;

switch(section)

{

case 0:

sectionName = [NSString stringWithString:@"Title"];

break;

case 1:

sectionName = [NSString stringWithString:@"Author"];

break;

case 2:

sectionName = [NSString stringWithString:@"Summary"];

break;

}

return sectionName;

}


- (void)didReceiveMemoryWarning 

{

    [super didReceiveMemoryWarning];

}


- (void)viewDidUnload 

{

    [super viewDidUnload];

}


- (void)dealloc 

{

[aBook release];

[tableView release];

    [super dealloc];

}


@end