【问题标题】:iOS - How to control block execution order when the block always get data after assigning variables?iOS - 当块在分配变量后总是获取数据时如何控制块执行顺序?
【发布时间】:2016-05-26 09:20:07
【问题描述】:

我是 iOS 编程新手,我敢肯定很多其他人都遇到过同样的问题。

问题是,我使用 AFNetworking 来处理我的 http 请求。

我正在尝试在我的 init 方法中获取一些数据,我想用 ViewDidLoad() 中的这些数据分配一个变量。

似乎AFNetworking 发送带有块的get 请求**(可能是异步的,但我还没有了解线程)**。

当我分配时,我试图获取的数据还没有返回。

我搜索过类似的答案

The execution of block is always delayed

block execution iOS and assigning variable

Variable returning null after block execution

但没有找到解决办法。

不知道是不是多线程机制的原因,请问如何解决?


代码

HomeController.m

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    NSInteger cateid = indexPath.row + 1;
    HomeTabCategoryController* categoryController = [[HomeTabCategoryController alloc] initWithCategoryId:cateid andCategoryName:[_categories objectForKey: [@(indexPath.row + 1) stringValue]]];
    [self.navigationController pushViewController:categoryController animated:YES];
}

CategoryController.m

-(instancetype)initWithCategoryId:(NSInteger)categoryId andCategoryName:(NSString*)categoryName{
    self = [super init];
    if (!self) {
        return nil;
    }
[ProductModel getProductsIdOfCategory:_categoryId success:^(BOOL result, NSString* message, NSArray* productIds){
        if (!result) {
            _productIds = productIds;
        }else{
            [self toast:message];
        }
    }failure:^(NSError* error){
        NSLog(@"%@", error);
    }];
    return self;
}

-(void)viewDidLoad{
    NSLog(@"loading view");
    [super viewDidLoad];
    self.title = _categoryName;

    [self getData];
}

- (void)getData{

for (NSNumber* proId in _productIds) {
    [ProductModel getProductWithId:[proId integerValue] success:^(BOOL result, NSString* message, ProductEntity* product){
        if (!result) {
            [_products addObject:product];
        }else{
            [self toast:message];
        }
    }failure:^(NSError* error){
        NSLog(@"%@", error);
    }];
}
}

getData被执行时,_productIds仍然是nil(我在success块中赋值)。

【问题讨论】:

  • 你能分享更多细节吗?为什么需要调用 INIT ?我相信这可以通过 GCD 串行队列来实现。
  • 这是因为我在HomeController 中有一个UITableView,当我选择某一行时,我想显示一个新视图。实际上我以前从未了解过GCD。如果是GCD 的问题,我一定会自己去拿一些文档并学习使用它。但问题是,我什至不知道问题到底是什么(我的意思是我想要更多关于事情在我的代码中是如何工作的细节)。你能给点建议吗?块中是否创建了线程?该块何时实际执行?预先感谢。 :)

标签: ios objective-c multithreading afnetworking block


【解决方案1】:

当你有响应(productIds)时,你不能像 i-e 那样调用你的 init 方法吗?这是有道理的。

> -(instancetype)initWithCategoryId:(NSInteger)categoryId andCategoryName:(NSString*)categoryName{
>     self = [super init];
>     if (!self) {
>         return nil;
>     } [ProductModel getProductsIdOfCategory:_categoryId success:^(BOOL result, NSString* message, NSArray* productIds){
>         if (!result) {
>             _productIds = productIds;
             **[self getData];**
>         }else{
>             [self toast:message];
>         }
>     }failure:^(NSError* error){
>         NSLog(@"%@", error);
>     }];
>     return self; }

【讨论】:

  • 是的,它有效。但是我仍然不明白里面的东西,这可能会导致将来出现同样的问题。你能给个提示吗?我会自己谷歌了解详细信息。非常感谢!
  • 请接受答案。如果它对您有用并解决了问题,那么访问者可以从中受益。
  • 不会的。原因是,您现在正在调用仅在填充该 ARRAY 时才使用该 ARRAY 的方法。应该是这样的。块就像 ASYNC 调用。只有当您收到响应时才会调用完成。数组为空的唯一原因是,ViewDidLoad 在块响应之前被调用。
【解决方案2】:

如果你想要的话,一旦我从 API 调用中得到响应,而不是调用另一个 API 或方法。比使用下面的 GCD 串行队列

> dispatch_queue_t serialQueue =
> dispatch_queue_create("com.xyzapp.queue", DISPATCH_QUEUE_SERIAL);
>     
>     dispatch_async(serialQueue, ^{
> 
> [ProductModel getProductsIdOfCategory:_categoryId success:^(BOOL
> result, NSString* message, NSArray* productIds){
>         if (!result) {
>             _productIds = productIds;
>         }else{
>             [self toast:message];
>         }
>     }failure:^(NSError* error){
>         NSLog(@"%@", error);
>     }];
> 
>     });
>     
>     dispatch_async(serialQueue, ^{
>         
>         [self getData];
>     });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    相关资源
    最近更新 更多