2010-11-10 23 views
0

我从API中提取数据并填写文章标题(来自Article对象)的UITableView。据我所知,我有那部分工作。当我在表格视图中触摸某行时,我正努力展示文章的细节。帮助!需要进行代码审查:试图通过API调用显示对象详细信息(解析XML)

我正确地捕获了文章ID,然后向API发出请求以提取其数据,并执行与我在前一步中加载文章UITableView所做的操作非常相似的事情。这是我为获得文章详细解析:

// ArticleDetailParser.h 
#import <Foundation/Foundation.h> 
#import "Article.h" 

@class Article; 
@class ArticleDetailParser; 

@protocol ArticleDetailParserDelegate <NSObject> 
- (void)parserDidFinish:(ArticleDetailParser *)parser; 
- (void)parser:(ArticleDetailParser *)parser didFailWithError:(NSError *)error; 
@end 

@interface ArticleDetailParser : NSObject <NSXMLParserDelegate> { 
id<ArticleDetailParserDelegate> delegate; 

NSMutableString *currentCharacters; 
Article *currentArticle; 
NSMutableArray *articlesCollection; 
NSMutableData *xmlData; 
NSURLConnection *connectionInProgress; 
} 

@property (nonatomic, assign) id<ArticleDetailParserDelegate> delegate; 

- (void)parseUrl:(NSString *)url; 
- (void)beginParsing:(NSURL *)xmlUrl; 
- (Article *)detailedArticle; 

@end 

而这里的实现:

// ArticleDetailParser.m 
#import "ArticleDetailParser.h" 

@implementation ArticleDetailParser 

@synthesize delegate; 

#pragma mark - 
#pragma mark Parsing methods 

- (void)parseUrl:(NSString *)url 
{ 
NSURL *xmlUrl = [NSURL URLWithString:url]; 
[self beginParsing:xmlUrl]; 
} 

- (void)beginParsing:(NSURL *)xmlUrl 
{ 
[articlesCollection removeAllObjects]; 
articlesCollection = [[NSMutableArray alloc] init]; 

NSURLRequest *request = [NSURLRequest requestWithURL:xmlUrl cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30]; 

// clear existing connection if there is one 
if (connectionInProgress) { 
    [connectionInProgress cancel]; 
    [connectionInProgress release]; 
} 

[xmlData release]; 
xmlData = [[NSMutableData alloc] init]; 

// asynchronous connection 
connectionInProgress = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; 
} 

- (Article *)detailedArticle 
{ 
return [articlesCollection objectAtIndex:0]; 
} 

#pragma mark - 
#pragma mark NSXMLParserDelegate methods 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
[xmlData appendData:data]; 
} 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{ 
if ([elementName isEqual:@"article"]) { 
    currentArticle = [[Article alloc] init]; 
    return; 
} 
if ([elementName isEqual:@"id"]) { 
    currentCharacters = [[NSMutableString alloc] init]; 
    return; 
} 
if ([elementName isEqual:@"title"]) { 
    currentCharacters = [[NSMutableString alloc] init]; 
    return; 
} 
if ([elementName isEqual:@"alphabetical_title"]) { 
    currentCharacters = [[NSMutableString alloc] init]; 
    return; 
} 
if ([elementName isEqual:@"body"]) { 
    currentCharacters = [[NSMutableString alloc] init]; 
    return; 
} 
if ([elementName isEqual:@"body_html"]) { 
    currentCharacters = [[NSMutableString alloc] init]; 
    return; 
} 
if ([elementName isEqual:@"category"]) { 
    currentCharacters = [[NSMutableString alloc] init]; 
    return; 
} 
if ([elementName isEqual:@"authors"]) { 
    currentCharacters = [[NSMutableString alloc] init]; 
    return; 
} 
if ([elementName isEqual:@"last_updated"]) { 
    currentCharacters = [[NSMutableString alloc] init]; 
    return; 
} 
} 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
{ 
[currentCharacters appendString:string]; 
} 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{ 
if ([elementName isEqual:@"article"]) { 
    [articlesCollection addObject:currentArticle]; 
    [currentArticle release], currentArticle = nil; 
    return; 
} 
if ([elementName isEqual:@"id"]) { 
    [currentArticle setArticleID:currentCharacters]; 
    [currentCharacters release], currentCharacters = nil; 
    return; 
} 
if ([elementName isEqual:@"title"]) { 
    [currentArticle setTitle:currentCharacters]; 
    [currentCharacters release], currentCharacters = nil; 
    return; 
} 
if ([elementName isEqual:@"alphabetical_title"]) { 
    [currentArticle setAlphabeticalTitle:currentCharacters]; 
    [currentCharacters release], currentCharacters = nil; 
    return; 
} 
if ([elementName isEqual:@"body"]) { 
    [currentArticle setBody:currentCharacters]; 
    [currentCharacters release], currentCharacters = nil; 
    return; 
} 
if ([elementName isEqual:@"body_html"]) { 
    [currentArticle setBodyHtml:currentCharacters]; 
    [currentCharacters release], currentCharacters = nil; 
    return; 
} 
if ([elementName isEqual:@"category"]) { 
    [currentArticle setCategory:currentCharacters]; 
    [currentCharacters release], currentCharacters = nil; 
    return; 
} 
if ([elementName isEqual:@"authors"]) { 
    [currentArticle setAuthors:currentCharacters]; 
    [currentCharacters release], currentCharacters = nil; 
    return; 
} 
if ([elementName isEqual:@"last_updated"]) { 
    [currentArticle setLastModified:currentCharacters]; 
    [currentCharacters release], currentCharacters = nil; 
    return; 
} 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData]; 
[parser setDelegate:self]; 

[parser parse]; 
[parser release]; 

[delegate parserDidFinish:self]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
[currentArticle release]; 
currentArticle = nil; 

[currentCharacters release]; 
currentCharacters = nil; 

[articlesCollection release]; 
articlesCollection = nil; 

[connectionInProgress release]; 
connectionInProgress = nil; 

[xmlData release]; 
xmlData = nil; 

NSLog(@"connection failed: %@", [error localizedDescription]); 

[delegate parser:self didFailWithError:error]; 
} 

@end 

做任何事情你立场是错误的?这里是我的控制,我正在做使用ArticleDetailParser的:

// ArticleDetailViewController.h 
#import <UIKit/UIKit.h> 
#import "ArticleDetailParser.h" 

@class Article; 

@interface ArticleDetailViewController : UIViewController <ArticleDetailParserDelegate> { 
Article *article; 
UILabel *aTitle; 
UILabel *aCategory; 
UILabel *aAuthors; 
UIActivityIndicatorView *activityView; 
} 

@property (nonatomic, assign) Article *article; 
@property (nonatomic, assign) UIActivityIndicatorView *activityView; 

- (void)loadArticleDetail; 
- (void)showArticle; 

@end 

所述控制器的实现:

// ArticleDetailViewController.m 
#import "ArticleDetailViewController.h" 

@implementation ArticleDetailViewController 

@synthesize article, activityView; 

#pragma mark - 
#pragma mark init and dealloc 

- (id)init 
{ 
[super initWithNibName:nil bundle:nil]; 

[[self navigationItem] setTitle:@"Article Details"]; 

article = [[Article alloc] init]; 

aTitle = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 280, 25)]; 
aCategory = [[UILabel alloc] initWithFrame:CGRectMake(20, 30, 280, 25)]; 
aAuthors = [[UILabel alloc] initWithFrame:CGRectMake(20, 50, 280, 25)]; 

activityView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)]; 
[[self activityView] sizeToFit]; 
[[self activityView] setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin)]; 

return self; 
} 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{ 
return [self init]; 
} 

- (void)dealloc { 
[article release]; 
[aTitle release]; 
[aCategory release]; 
[aAuthors release]; 
[activityView release]; 
    [super dealloc]; 
} 

#pragma mark - 
#pragma mark Web Service methods 

- (void)loadArticleDetail 
{ 
NSString *urlToRequest = [NSString stringWithFormat:@"http://wvencyclopedia.org/articles/%@.xml", [[self article] articleID]]; 
ArticleDetailParser *aDetailParser = [[ArticleDetailParser alloc] init]; 
[aDetailParser setDelegate:self]; 
[aDetailParser parseUrl:urlToRequest]; 
[aDetailParser release]; 
} 

#pragma mark - 
#pragma mark ArticleDetailParserDelegate methods 

- (void)parserDidFinish:(ArticleDetailParser *)parser 
{ 
article = [parser detailedArticle]; 
[[self activityView] stopAnimating]; 
} 

- (void)parser:(ArticleDetailParser *)parser didFailWithError:(NSError *)error 
{ 
NSString *errorString = [NSString stringWithFormat:@"Fetch failed: %@", [error localizedDescription]]; 

UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:errorString delegate:nil cancelButtonTitle:@"OK" destructiveButtonTitle:nil otherButtonTitles:nil]; 
[actionSheet showInView:[[self view] window]]; 
[actionSheet autorelease]; 
} 

#pragma mark - 
#pragma mark UIView methods 

- (void)showArticle 
{ 
[aTitle setText:[[self article] title]]; 
[[self view] addSubview:aTitle]; 
[aTitle release]; 

[aCategory setText:[[self article] category]]; 
[[self view] addSubview:aCategory]; 
[aCategory release]; 

[aAuthors setText:[[self article] authors]]; 
[[self view] addSubview:aAuthors]; 
[aAuthors release]; 
} 

#pragma mark - 
#pragma mark UIViewController methods 

- (void)viewWillAppear:(BOOL)animated 
{ 
[super viewWillAppear:animated]; 
[self loadArticleDetail]; 
[[self activityView] startAnimating]; 
[self showArticle]; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
[[self view] setBackgroundColor:[UIColor groupTableViewBackgroundColor]]; 
} 

- (void)viewDidUnload { 
    [super viewDidUnload]; 
    // Release any retained subviews of the main view. 
    // e.g. self.myOutlet = nil; 
} 

- (void)loadView 
{ 
[super loadView]; 

UIBarButtonItem *loadingView = [[UIBarButtonItem alloc] initWithCustomView:[self activityView]]; 
[[self navigationItem] setRightBarButtonItem:loadingView]; 
} 

#pragma mark - 
#pragma mark Memory Management 

- (void)didReceiveMemoryWarning { 
    // Releases the view if it doesn't have a superview. 
    [super didReceiveMemoryWarning]; 

    // Release any cached data, images, etc that aren't in use. 
} 

@end 

这是书籍教程超出了我的第一真正 iPhone应用程序,并我也是Objective-C的新手,所以我很容易误解内存管理方面的问题,并在视图中获取标签。

发生了什么事情是我点击表格视图加载一篇文章,第一篇文章只显示文章标题。然后我回去,尝试点击另一个,它崩溃。

我很抱歉张贴这么多的代码,但我想如果有人选择帮助它可能是最好的整个图片。

非常感谢你,如果你应该承担这样的任务!

+0

在发布所有代码之前,您应该尝试自己调试一段时间。使用XCode的运行和调试选项,并在应用程序崩溃时使用日志查看堆栈跟踪。您也可以在您的代码中放置NSLog(),以确保您的变量包含您认为应包含的内容。如果您收到任何您无法解读的错误消息,请告诉我们! – Tozar 2010-11-10 05:48:34

回答

0

您的应用程序崩溃的原因可能是由于您的UILabel在showArticle中释放它们时被取消分配的。 当处理对象(需要名称前面的星号的变量类型)时,您需要使用 @property (nonatomic, retain) 而不是 @property (nonatomic, assign) 。对原始类型使用assign,如整数和双精度。