如何使用 AFNetworking 修改另一个类中的实例 - 创建 API 客户端

Posted

技术标签:

【中文标题】如何使用 AFNetworking 修改另一个类中的实例 - 创建 API 客户端【英文标题】:How to Modify an Instance in Another Class with AFNetworking - Creating API Client 【发布时间】:2015-07-06 22:28:32 【问题描述】:

有这个问题,因为我正在尝试开发我的代码。之前,我在类中使用 AFNetworking 方法,但我得到了其中的 4 个。我想要 APIClient,而不是那个重复序列,它有方法。我实现了一些方法,但我的问题只是其中两个。

所以,在 APIClient.m 我有以下内容:

+(void)GetCurrencyInformationFrom:(NSString *)URLString to:(NSArray *) array inThe:(UITableView *) tableView
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // User informations.
    NSString *accessToken = [defaults objectForKey:@"accessToken"];

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    [manager.requestSerializer setValue:accessToken forHTTPHeaderField:@"Token"];

    NSLog(@"access token: %@", accessToken);
    NSLog(@"id: %@", [defaults objectForKey:@"ID"]);

    [manager GET:URLString parameters:nil  success:^(AFHTTPRequestOperation *operation, id responseObject) 
        [self update:array withDictionary:responseObject inThe:tableView];
     failure:^(AFHTTPRequestOperation *operation, NSError *error) 
        NSLog(@"Error 2: %@", error);
    ];


+(void)update:(NSArray *)array withDictionary:(NSDictionary *)dictionary inThe:(UITableView *) tableView
    NSLog(@"Data Count: %lu", [dictionary[@"Data"] count]);
    array = [[NSMutableArray alloc] initWithArray:dictionary[@"Data"]];
    NSLog(@"Array Count: %lu", [array count]);
    [tableView reloadData];

这些方法在表视图类中调用。例如,我在viewload 中调用的一个类:

NSString *URL = @"http://api-dvzalt.azurewebsites.net/api/Currency/Doviz";

[APIClient GetCurrencyInformationFrom:URL to:currencyArray inThe: tableView];

为了调试,我正在打印数据计数和数组计数(两者都可以在 update:withDictionary:inThe: 方法中找到)和行数(在表类中)。开始时行数为零是正常的,因为它是异步的,但是,在我重新加载我的 tableView 之后,即在一切都完成之后(参见 update:withDictionary:inThe 方法中的 [tableView reloatData])行数保持为零,其中 Data 和 Array 的计数为 20。当然,如果行数为零,则表上没有任何内容。所以,基本上我的问题是我给方法的 currencyArray 在它再次返回 tableView 后并没有改变,即使它在 APIClient 类中发生了变化。

我觉得这是一个简单的错误,但我看不出它在哪里。很高兴你能帮我找到它。

谢谢!

【问题讨论】:

你真的应该遵守可可编码约定 我没有正确使用什么? 可能你没有正确使用苹果的文档。 你能说得更具体些吗? 好吧,无论他反对谁很容易,解释是困难的部分。这个问题问得很好。你可能会告诉我它有什么问题。 【参考方案1】:

您是否确保您的UITableView 具有正确的数据源集?

您的-numberOfSectionsInTableView:-tableView:numberOfRowsInSection: 方法是什么样的?

【讨论】:

numberOfSectionsInTableView 我做了一个,因为我需要一个。而tableView:numberOfRowsInSection 依赖于currencyArray,我打算通过调用APIClient 的get 方法来改变它 -tableView:numberOfRowsInSection: 返回 20? 我有这个问题,没有。 array 在更新方法中变成了 20,但不幸的是,当它进入 table 时,它​​并没有保持 20。我不能把它带到tableView。【参考方案2】:

我真的不喜欢回答我的问题。但是在这种情况下,我敢打赌周围有太多新手,并且正在寻找与我相同的问题。我找不到任何解决方案 4 天。一直在网上搜索并在这里询问,但我没有找到我需要的解决方案。也许对你来说不是这样,但如果是第一次,肯定至少需要 1 天。所以,我会尝试让像我这样的初学者深入了解。

首先,创建并拥有一个像 APIClient 这样的类通常是一个好主意。当您要从 Internet 获取数据时,它只是一个可以轻松使用的类。但是,对于初学者来说,事情变得越来越复杂,因为我们大多习惯于同步执行。

如果您正在尝试修改任何类中的任何实例,那么您所要做的就是不要将该实例提供给像我这样的 APIClient(或具有块的类),而是尝试获取任何需要的信息来自 APIClient。就像,如果我们能实现从APIClient传来的信息,就很容易将那个实例放在实例自己的类中。例如。将currencyArray 提供给APIClient,并尝试更新APIClient 中的数组很困难。另一方面,很容易从 APIClient 获取响应对象,这正是来自您拥有的 URL 的 JSON 数据。

长话短说,通过这种方式,我将 APIClient.m 中的代码更改为:

+(void)GetCurrencyInformationFrom:(NSString *)URLString to:(NSArray *) array inThe:(UITableView *) tableView
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // User informations.
    NSString *accessToken = [defaults objectForKey:@"accessToken"];

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    [manager.requestSerializer setValue:accessToken forHTTPHeaderField:@"Token"];

    NSLog(@"access token: %@", accessToken);
    NSLog(@"id: %@", [defaults objectForKey:@"ID"]);

    [manager GET:URLString parameters:nil      success:^(AFHTTPRequestOperation *operation, id responseObject) 
        if(success) success(operation, responseObject)
     failure:^(AFHTTPRequestOperation *operation, NSError *error) 
        if(failure) failure(operation, error)
    ];

请注意,我不再有 update:withDictionary:inThe: 方法,因为计划将信息带到实例的类,并在那里更新。不在这里。

为了更新的目的,让我们调用实例类的viewLoad。因此,该方法将如下所示:

[APIClient GetCurrencyInformationFrom:URL
                              success:^(AFHTTPRequestOperation *operation, id responseObject) 
                                   [self updateCurrencyArrayWithDictionary:responseObject];
                             
                              failure:^(AFHTTPRequestOperation *operation, NSError *error) 
                                   NSLog(@"Error 2: %@", error);
    ];

再次出于更新的目的,我在这里也添加了更新方法,而不是 APIClient,这实际上并不是必需的;相反,我们会有块类型实例。

-(void)updateCurrencyArrayWithDictionary:(NSDictionary *)dictionary
    currencyArray= [[NSMutableArray alloc] initWithArray:dictionary[@"Data"]];
    [tableView reloadData];

请注意,dictionary[@"Data"]]; 行可能会根据您的数据而改变。

所以,就是这样。这只是一个简单的示例,说明如何为我们的应用程序的网络目的创建 API 客户端。

希望,我以后可以通过这篇文章帮助某人。

【讨论】:

原始解决方案不起作用的原因是要修改 APIClient 类中 NSArray 的值,您需要通过引用传递它。在你的方法中设置“array”变量只会改变它在该方法中的值,这就是为什么 table view 控制器上的 array 属性没有被更新。块和单一职责绝对是更好的解决方案。

以上是关于如何使用 AFNetworking 修改另一个类中的实例 - 创建 API 客户端的主要内容,如果未能解决你的问题,请参考以下文章

如何使用另一个类中的对象的特定变量?

AFNetworking 2.0 - 如何从子类 AFHTTPSessionManager 成功将响应传递给另一个类

MFC 如何在一个类中使用另一个类中定义的变量

如何通过 AFNetworking API 调用使用 gzip 解压?

如何防止修改类中的私有字段?

Tkinter - 在类中使用Button命令从另一个类调用函数