我從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的新手,所以我很容易誤解內存管理方面的問題,並在視圖中獲取標籤。
發生了什麼事情是我點擊表格視圖加載一篇文章,第一篇文章只顯示文章標題。然後我回去,嘗試點擊另一個,它崩潰。
我很抱歉張貼這麼多的代碼,但我想如果有人選擇幫助它可能是最好的整個圖片。
非常感謝你,如果你應該承擔這樣的任務!
在發佈所有代碼之前,您應該嘗試自己調試一段時間。使用XCode的運行和調試選項,並在應用程序崩潰時使用日誌查看堆棧跟蹤。您也可以在您的代碼中放置NSLog(),以確保您的變量包含您認爲應包含的內容。如果您收到任何您無法解讀的錯誤消息,請告訴我們! – Tozar 2010-11-10 05:48:34