2013-10-30 53 views
0

我有一个关于在iOS/Objective-C中传递数据的问题。我刚开始创建一个连接并从网站获取数据的应用程序,现在我遇到了问题。单击按钮时从另一个类返回一个NSDictionary

我的默认和根视图控制器被称为ViewController。它具有基本的登录UI视图:2个文本框和一个按钮。

当按钮被点击/触摸时,ViewController调用另一个类叫做LoginService的方法。现在LoginService处理到网站的连接。我没有问题连接到网站,并从中获取数据,但我有一个问题,返回提取的数据,现在处理为NSDictionary,到ViewController

我尝试的第一件事是在ViewController中创建一个setter方法,它将实例变量userProfile设置为传入它的NSDictionary。但是,它失败了。我试图在LoginService的NSURLConnectionDataDelegate方法connectionDidFinishLoading中使用它。

这可能是一个愚蠢的问题,但我不知道如何将按钮被单击后,从LoginService传递到ViewController提取的NSDictionary。我需要块,队列还是其他?我的意思是,例如,我需要在登录按钮下面设置一个标签,以便登录的用户名。我该如何执行此操作?

希望有人能帮助我。我将不胜感激。

+1

你基本上需要明白这是经常用于这类用途的“代表”的格局。读了它在这里:http://www.tutorialspoint.com/ios/ios_delegates.htm 或者你使用的块可以实现一个解决方案:http://www.abdus.me/ios-programming-tips/uialertview -with块,回拨/ –

回答

1

由于丹已经解释了这样做的块模式,我会尝试解释委托模式。为使这项工作的步骤:

LoginService.h

在login服务这样创建一个协议定义:

@protocol LoginServiceDelegate 

    -(void)applicationLoggedIn:(NSMutableDictionary*) responseData; 

    @end 

现在添加一个成员指针持有该委托,并添加属性为这个

@interface LoginService { 

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

LoginService.m

一旦你得到了在connectionDidFinishLoading登录的响应,只调用像下面的委托方法:

if ([delegate respondsToSelector:@selector(applicationLoggedIn:)]) { 
      [delegate applicationLoggedIn:responseDict]; 
    } 

LoginViewController.h

现在,在您LoginViewController利用这一点,你需要实现这个协议

#import "LoginService.h" 
    @interface LoginViewController<LoginServiceDelegate> 

LoginViewController.m

分配delegat login服务的E要LoginViewController

LoginService* loginService = [[LoginService alloc]init]; 
    loginService.delegate = self; 

实现协议方法为:

-(void)applicationLoggedIn:(NSDictionary*)response{ 

    } 

希望这有助于。

+0

您好,我有一个问题。这对我来说,似乎是做了正确的方式是我想做的事。我只想问,为什么我要使用这块代码:'如果([委托respondsToSelector:@selector(applicationLoggedIn :)]){ [代表applicationLoggedIn:responseDict]。 }'希望收到你的来信,谢谢:) – christianleroy

1

基本上你需要ViewController有一个公共方法,当它完成它的工作时LoginService可以调用它,而NSDictionary将是这个方法的一个参数。 LoginService将需要一个引用返回到ViewController以调用此方法,因此在LoginService上定义一个公用属性,该属性将保存一个ViewController引用 - 并在实例化LoginService后对其进行设置。

当然,如果您希望LoginService更具可重用性,并且不特别与ViewController绑定,那么委托就是要走的路。 LoginService将使用要在完成时调用的方法来定义LoginServiceDelegate协议。然后ViewController将实现LoginServiceDelegate协议。 LoginService上的公共属性成为LoginServiceDelegate引用,因此LoginService不再需要导入ViewController。这样,ViewController依赖于LoginService,但LoginService不依赖于ViewController。

1

要考虑的两种模式:委托和阻止。代码块更快,我通常更喜欢它代表网络操作。要使用一个块,编写登录服务是这样的:

// LoginService.h 

- (void)login:(NSString *)username completion:(void (^)(NSDictionary *, NSError *))completion; 

这听起来像你在这里使用NSURLConnection的委托模式,所以我会假设。请注意,NSURLConnection还提供了一个很好的one-shot block method来执行请求。

// LoginService.m 

@property (copy, nonatomic) void (^completion)(NSDictionary *, NSError *); 


- (void)login:(NSString *)username completion:(void (^)(NSDictionary *, NSError *))completion { 

    // copy the block when the request begins 
    self.completion = completion; 

    // start your request, as you have it now 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 

    NSDictionary *dictionary = // parse the data you collected into a dictionary 

    // invoke the block with the result 
    self.completion(dictionary, nil); 
    self.completion = nil; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 

    self.completion(nil, error); 
    self.completion = nil; 
} 

这是礼貌处置块(其设置为无)你调用它之后的,所以它不会保留调用上下文的任何部分。

相关问题