Neste post vou mostrar como ler arquivos XML em aplicações iOS. O XML que estou lendo, eu baixei no site do livro Google Android do Ricardo Lecheta (eu tento, mas não deixo o Android :)
O modelo do estrutura do XML que iremos ler é apresentado abaixo:
<?xml version="1.0" encoding="utf-8"?> <carros> <carro> <nome>Modelo do Carro</nome> <desc>Descrição do Carro</desc> <url_info>http://www.ferrari.com/</url_info> <url_foto>http://www.livroandroid.com.br/</url_foto> </carro> ... </carros>Crie um novo projeto no Xcode utilizando o template "Single View Application". Agora acesse o site do livro e baixe o XML, em seguida adicione-o ao seu projeto no Xcode na pasta "Supporting Files". A estrutura do projeto (no final) deve ficar conforme abaixo:
Como você deve ter observado, o carro descrito no XML tem os atributos nome, desc, url_info e url_foto. Vamos criar uma classe que representará esse objeto em código.
// Carro.h --------------------------------------- #import <Foundation/Foundation.h> @interface Carro : NSObject @property (strong, nonatomic) UIImage *image; @property (strong, nonatomic) NSString *nome; @property (strong, nonatomic) NSString *descricao; @property (strong, nonatomic) NSString *urlInfo; @property (strong, nonatomic) NSString *urlFoto; @end // Carro.m --------------------------------------- #import "Carro.h" @implementation Carro @synthesize nome, descricao, urlFoto, urlInfo, image; @endVou alterar o AppDelegate da aplicação para ficar desta forma:
// NGAppDelegate.h ------------------------------- #import <UIKit/UIKit.h> @class NGViewController; @interface NGAppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) UINavigationController *navigationController; @end // NGAppDelegate.m ------------------------------- #import "NGAppDelegate.h" #import "NGViewController.h" @implementation NGAppDelegate @synthesize window = _window; @synthesize navigationController; - (BOOL)application: (UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions{ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; NGViewController *viewController = [[NGViewController alloc] initWithNibName: @"NGViewController" bundle:nil]; navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; self.window.rootViewController = self.navigationController; [self.window makeKeyAndVisible]; return YES; } // Outros métodos não alterados @endNesse template, a aplicação é criada com uma UIViewController simples. Vamos utilizar uma UITableViewController que listará os dados lidos através de um objeto da class NSXMLParser. Sua utilização é bem similar ao SAX do Java, e teremos que implementar um protocolo NSXMLParserDelegate, e a medida que as tags são lidas os métodos desse protocolo são chamados.
#import <UIKit/UIKit.h> #import "Carro.h" @interface NGViewController : UITableViewController <NSXMLParserDelegate>{ NSMutableArray *carros; Carro *carro; NSString *currTag; } @endUm NSMutableArray armazenará os objetos Carro criados a partir da leitura do XML. Durante o parser do XML, precisamos saber que tag está sendo lida, para tal setarmos o atributo currTag com tag que corresponde a propriedade da classe Carro. Por exemplo, quando o parser encontrar uma tag "carro", criamos um objeto Carro, já quando encontramos uma tag "nome", devemos definir o a propriedade nome do objeto carro. Por fim, ao encontrar a tag "/carro" devemos adicionar o objeto carro na lista.
Vamos agora a implementação da tela (lembrando que só estamos mostrando os métodos alterados):
#import "NGViewController.h" #import "Carro.h" @implementation NGViewController - (void)viewDidLoad{ [super viewDidLoad]; self.title = @"Carros"; carros = [[NSMutableArray alloc] init]; // Pega o caminho do arquivo XML NSString *xmlPath = [[NSBundle mainBundle] pathForResource:@"carros" ofType:@"xml"]; // Obtém os bytes do arquivo NSData *xmlData = [NSData dataWithContentsOfFile:xmlPath]; // Cria o objeto que fará o parser do XML NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:xmlData]; [xmlParser setDelegate:self]; [xmlParser parse]; } // Métodos chamado quando NSXMLParser // inicia a leitura de uma TAG -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { currTag = elementName; // Se achou a TAG carro, crie um novo objeto if ([currTag compare:@"carro"] == NSOrderedSame){ carro = [[Carro alloc] init]; } } // Método chamado quando vai ler o // conteúdo da TAG -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { if ([currTag compare:@"nome"] == NSOrderedSame && carro.nome == nil){ carro.nome = string; } else if ([currTag compare:@"desc"] == NSOrderedSame && carro.descricao == nil){ carro.descricao = [string stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; } else if ([currTag compare:@"url_info"] == NSOrderedSame && carro.urlInfo == nil){ carro.urlInfo = [string stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; } else if ([currTag compare:@"url_foto"] == NSOrderedSame && carro.urlFoto == nil){ carro.urlFoto = [string stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; } } // Método chamado quando termina de ler uma tag -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { // Se a tag lida for "carro", adiciona à lista if ([elementName compare:@"carro"]==NSOrderedSame){ [carros addObject:carro]; } } // Método de UITableViewController -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [carros count]; } -(NSInteger)numberOfSectionsInTableView: (UITableView *)tableView { return 1; } -(UITableViewCell *)tableView:(UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; } Carro *_carro = [carros objectAtIndex:indexPath.row]; cell.textLabel.text = _carro.nome; cell.detailTextLabel.text = _carro.urlInfo; return cell; } -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { // Obtém o carro da linha selecionada Carro *_carro = [carros objectAtIndex:indexPath.row]; // Abre o site do carro selecionado NSURL *url = [NSURL URLWithString:_carro.urlInfo]; [[UIApplication sharedApplication] openURL:url]; } @endO código acima está comentado e parte relacionada com a UITableViwController foi detalhada nesse post aqui.
Feito isso, precisamos fazer alguns ajustes no NIB. Abra o NGViewController.xib e remova a UIView e adicione uma UITableViewController. Ligue esse componente ao Outlet da propriedade view, e o dataSource e delegate. Além disso, alterei também a propriedade "Top Bar" para "Navigation Bar". Feito isso, podemos rodar nossa aplicação. O resultado é apresentado abaixo.
Qualquer dúvida, deixem seus comentários.
4br4ç05,
nglauber
Nenhum comentário:
Postar um comentário