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
@end
Nesse 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;
}
@end
Um 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];
}
@end
O 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.


4br4ç05,
nglauber
Nenhum comentário:
Postar um comentário