单击按钮时从另一个类返回NSDictionary

时间:2013-10-30 23:14:39

标签: ios iphone objective-c nsdictionary

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

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

单击/触摸按钮后,ViewController会调用另一个名为LoginService的类中的方法。现在LoginService处理与网站的连接。我没有问题连接到网站并从中获取数据,但我将问题(现在作为NSDictionary处理)返回到ViewController时出现问题。

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

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

希望有人可以帮助我。我非常感激。

3 个答案:

答案 0 :(得分:1)

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

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

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

在调用它之后处理该块(将其设置为nil)是礼貌的,因此它不会保留调用上下文的任何部分。

答案 2 :(得分:1)

由于danh已经解释了执行此操作的块模式,我将尝试解释委托模式。使这项工作的步骤:

LoginService.h

在LoginService中创建协议定义,如下所示:

    @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

将LoginService的委托分配给LoginViewController

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

将协议方法实现为:

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

    }

希望这有帮助。