2011-05-29 155 views
0

我被卡住了,需要一些幫助理解爲什麼這不起作用。爲什麼不能將這個變量從一個類傳遞給另一個

我希望能夠下載頁面的HTML,然後將其格式化爲正確顯示,第二類(spriing)中的代碼將下載並在UITextView中顯示HTML,如果它放在ViewController中,然而,這是打破了MVC的權利?

所以任何人都可以告訴我爲什麼我在mStringData變量上超出範圍錯誤?

我的課程如下:

我有一個類是視圖控制器;

//Class for the download and processing of data from website 

#import "FirstViewController.h" 

@implementation FirstViewController 

// The designated initializer. Override to perform setup that is required before the view is loaded. 
//- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 
// if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { 
//  // Custom initialization 
//} 
// return self; 
//} 


/* 
// Implement loadView to create a view hierarchy programmatically, without using a nib. 
- (void)loadView { 
} 
*/ 

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 
- (void)viewDidLoad { 
    [super viewDidLoad]; 

    spriing = [Spriing new]; 

    [spriing downloadData:@"http://www.spriing.co.uk/services/"]; 
    SpriingTxt.text = spriing.mStringData; 
} 

/* 
// Override to allow orientations other than the default portrait orientation. 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    // Return YES for supported orientations 
    return (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 
*/ 

- (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. 
} 

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


- (void)dealloc { 
    [super dealloc]; 
    [mRecData release]; 
    [mStringData release]; 
} 

和一個單獨的類;

#import "Spriing.h" 

@implementation Spriing 

@synthesize mStringData; 
@synthesize mRecData; 

- (void)downloadData: (NSString*) URL{ 

    mBaseURL = URL; 
    // Create the request. 
    NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:mBaseURL] 
             cachePolicy:NSURLRequestUseProtocolCachePolicy 
             timeoutInterval:60.0]; 

    // create the connection with the request 
    // and start loading the data 
    mCon=[[NSURLConnection alloc] initWithRequest:request delegate:self]; 

    if (mCon) 
    { 
     // create var to store data 
     mRecData = [[NSMutableData data] retain]; 
    } 
    else 
    { 
     // Inform the user that the connection failed. 
    } 
} 

//If the connection is reset 
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 
    //reset the data length 
    [mRecData setLength:0]; 
} 

//Obtaining new data 
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    //Add any newly recieved data to the currently stored data 
    [mRecData appendData:data]; 
} 

//If something went wrong 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    //Release the connection 
    [mCon release]; 
    //Release the data 
    [mRecData release]; 

    //Alert the user 
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Error!" 
                message:@"No internet connection!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease]; 
    [alert show]; 
    [alert release]; 
} 

//When its done 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    //NSLog(@"finished"); 

    // Once this method is invoked, "responseData" contains the complete result 
    self.mStringData = [[[NSString alloc] initWithData:mRecData encoding:NSUTF8StringEncoding] retain]; 

    //NSLog(@"%@", mStringData); 

    self.mStringData = [self processData:mStringData]; 

    //NSLog(@"%@", mStringData); 

    //SpriingTxt.text = mStringData; 

    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 

    //mStringData = nil; 
} 

- (NSURLRequest *)connection:(NSURLConnection *)connection 
      willSendRequest:(NSURLRequest *)request 
      redirectResponse:(NSURLResponse *)redirectResponse 
{ 
    [mBaseURL autorelease]; 
    mBaseURL = [[request URL] retain]; 
    return request; 
} 

-(NSString*) processData: (NSString*) string 
{ 
    NSMutableString *html = [NSMutableString stringWithCapacity:[string length]]; 

    NSScanner *scanner = [NSScanner scannerWithString:string]; 

    NSString *tempText = nil; 

    while (![scanner isAtEnd]) 
    { 
     [scanner scanUpToString:@"<" intoString:&tempText]; 

     if (tempText != nil) 
      [html appendString:tempText]; 

     [scanner scanUpToString:@">" intoString:NULL]; 

     if (![scanner isAtEnd]) 
      [scanner setScanLocation:[scanner scanLocation] + 1]; 
     tempText = nil; 
    } 

    return html; 
} 

- (void) dealloc 
{ 
    [super dealloc]; 
    //[mStringData release]; 
} 

@end 

回答

3

您正在開始一個需要一段時間的URL的異步請求。雖然它立即返回,但並不意味着數據已被下載。當數據完成下載時,NSURLRequest的代表將收到通知。在此之前,在分配下載的數據之前,可能有mStringData中的數據可能是nil。所以當你在異步請求後立即執行SpriingTxt.text = spriing.mStringData;而沒有下載數據時,SpriingTxt.text被分配爲nil

要解決這個問題,您可以創建一個同步請求,這個請求將阻塞,直到數據被下載,這通常是一個壞主意,或者當您的異步請求的數據已經通過委託或通知發送給視圖控制器時已被下載。

爲了實現委託

代表使用協議來實現。您將在委託對象中創建一個delegate屬性,該屬性將爲Spriing,因爲它將讓委託人知道字符串何時被下載,並且視圖控制器將作爲委託,因爲它想知道數據何時可用,以便它可以更新其觀點。代表們通常不會被保留,因爲大多數時候它是創建成爲代表的對象。因此保留代表將在這種情況下創建保留週期。有很多關於創建代表的教程。粗略實現將是,

Spriing.h

@protocol SpriinDelegate; 

@interface Spriing:... { 
    id<SpriingDelegate> delegate; 
    ... 
} 

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

@end 

@protocol SpriingDelegate 
    - (void)spriing:(Spriing*)aSpriing didFinishDownloadingString:(NSString*)aString; 
@end 

Spriing.m

@implementation Spriing 

@synthesize delegate; 

... 

//When its done 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    ... 

    self.mStringData = [self processData:mStringData]; 

    if (self.delegate && [self.delegate respondsToSelector:@selector(spriing:didFinishDownloadingString:)]) { 
     [self.delegate spriing:self didFinishDownloadingString:self.mStringData]; 
    } 

    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
} 

... 
@end 
在視圖控制器

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    spriing = [Spriing new]; 
    spriing.delegate = self; 

    [spriing downloadData:@"http://www.spriing.co.uk/services/"]; 
} 

- (void)spriing:(Spriing*)aSpriing didFinishDownloadingString:(NSString*)aString { 
    SpriingText.text = aString; 
} 

... 
+0

1,而是一個同步請求是_bad_主意在這種情況下,因爲它會阻塞主線程。 – 2011-05-29 19:18:22

+0

@Josh我做了狀態它會阻止。這是一個壞主意。我可能會編輯這一點。 – 2011-05-29 19:26:05

+0

@Deepak對不起,如果我是一個痛苦,但我會如何設置代表?例如我是否創建一個新的類或將它放在現有的類中? – nhunston 2011-05-29 19:29:11

相關問題