为什么我不能将这个变量从一个类传递给另一个类

时间:2011-05-29 18:37:16

标签: iphone objective-c

我陷入困境,需要帮助理解为什么这不起作用。

我希望能够下载页面的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

1 个答案:

答案 0 :(得分: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;
}

...