2015-03-19 13 views
5

tôi khá mới để Objective-C & có để tự động thay đổi giá trị của

@property (strong, nonatomic) NSMutableArray *allCategories

từ bên trong AFHTTPRequestOperationManager trong success khối.
[self.allCategories addObject:tempObject];
không thay đổi giá trị allCategories khi lặp lại trong vòng lặp.

Biến đã được khởi tạo là
self.allCategories = [[NSMutableArray alloc]init];
trong chế độ xemDidLoad.Làm cách nào để sửa đổi biến không phải cục bộ (toàn cục) từ bên trong khối?

Tôi cũng đã thử tạo biến tạm thời là __block NSMutableArray *tempCategories = [[NSMutableArray alloc]init]; trước khi bắt đầu đối tượng AFHTTPRequestOperationManager. tempCategories thậm chí không giữ lại giá trị của nó.

Không thể hiểu được điều gì đang xảy ra.

Sửa
Xin lỗi vì sự bất tiện
viewDidLoad có đoạn mã sau
self.allCategories = [[NSMutableArray alloc]init];
[self loadData];

Dưới đây là đoạn code

-(NSMutableArray *)loadData 
{ 
    __block NSMutableArray *tempCategories = [[NSMutableArray alloc]init]; 

    manager = [AFHTTPRequestOperationManager manager]; 

    [manager GET:kAPICategoryList 
     parameters:nil 
     success:^(AFHTTPRequestOperation *operation, id responseObject) { 

      // downcast id to NSMutableDictionary 
      NSMutableDictionary *json = (NSMutableDictionary *)responseObject; 

      // check if dictionary is non nil has at least 1 element 
      if (json != nil && [json count] >= 1) { 

       // NSLog(@"json:\t%@", json); 

       // check json is non nil & has success message 
       if ([json objectForKey:kAPIKeyCategoryRoot] != nil) { 

        NSArray *arrCategoriesRoot = [json objectForKey:kAPIKeyCategoryRoot]; 

        // check categories has some data 
        if (arrCategoriesRoot.count >= 1) { 

         for (int i = 0; i < arrCategoriesRoot.count; i++) { 

          SomeModel *pCategory; 

          NSDictionary *dctCategorySingle = [arrCategoriesRoot objectAtIndex:i]; 

          // check category has sub category 
          if ([dctCategorySingle objectForKey:kAPIKeyCategorySubCategory] != nil) { 
           // create category with sub category 
           pCategory = [[SomeModel alloc]initWithSubCategorisedCategoryID:[dctCategorySingle objectForKey:kAPIKeyCategoryID] 
                           name:[dctCategorySingle objectForKey:kAPIKeyCategoryName] 
                          image:kIMGCategoryDefault 
                         subCategory:[dctCategorySingle objectForKey:kAPIKeyCategorySubCategory]]; 
          } else{ 
           // create just a category 
           pCategory = [[SomeModel alloc]initWithCategoryID:[dctCategorySingle objectForKey:kAPIKeyCategoryID] 
                       name:[dctCategorySingle objectForKey:kAPIKeyCategoryName] 
                       image:kIMGCategoryDefault]; 
          } // else just 
          [tempCategories addObject:pCategory]; 
          [_allCategories addObject:pCategory]; 
         } // for 
         NSLog(@"categories count %lu", [self.allCategories count]); 
        } // if count >= 1 
       } 
       else if ([json objectForKey:kAPIRespMsgCategoryFetchErrKey] != nil) { 
        [Utility showAlertWithTitle:kAPIRespMsgCategoryFetchErrKey 
             message:[json objectForKey:kAPIRespMsgCategoryFetchErrVal] 
              button:kMsgButtonOkayTtl]; 
       } 
      } else { 
       // error in login => enable login 
       NSLog(@"%@", kMsgNetworkEmptyJSON); 
      } 
     } 
    // network error 
     failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
      NSLog(@"error %@", [error localizedDescription]); 
     }]; 
    NSLog(@"tempCategories count %lu", [tempCategories count]); 
    return tempCategories; 
} 

Dưới đây là hình thức đầu ra NSLog:

2015/03/19 18: 27: 17,845 MyProject [4011 : 121268] viewDidLoad
2015-03-19 18: 27: 18.133 MyProject [4011: 121268] tempCác danh mục đếm 0
2015-03-19 18: 27: 18.136 MyProject [4011: 121268] numberOfRowsInSection count 0
2015/03/19 18: 27: 18,137 MyProject [4011: 121.268] numberOfRowsInSection đếm 0
2015/03/19 18: 27: 19,019 MyProject [4011: 121.268] danh mục đếm 20

khi loadData thúc allCategories có không dữ liệu trong đó (nil).

+0

Bạn có thể xin vui lòng gửi mã? – jakedunc

+0

Bạn chưa cung cấp đủ thông tin. Điều gì khiến bạn nghĩ rằng nó không thay đổi giá trị? Đăng mã thực hiện cuộc gọi đến AFHTTPRequestOperationManager của bạn, cộng với mã nơi bạn kết luận rằng lệnh gọi hàm addObject không làm bất cứ điều gì. Tôi đoán là bạn không hiểu cách khối hoàn thành không đồng bộ hoạt động như thế nào và đang mong đợi giá trị được thay đổi ngay sau khi bạn thực hiện cuộc gọi. –

+0

Hãy cẩn thận. Bạn không thể chắc chắn những gì thread khối hoàn thành của bạn là trở lại từ, có nghĩa là bạn có thể cần phải bằng cách nào đó làm cho mảng truy cập của bạn an toàn. Đây là một trong những lý do tại sao các biến toàn cầu trong một ứng dụng async không phải là lý tưởng. – damian

Trả lời

0

Hãy thử điều này:

dispatch_async(dispatch_get_main_queue(), ^{ 
[self.allCategories addObject:tempObject]; 
}); 
0

tôi đã cùng một vấn đề cách đây vài ngày. Vấn đề của tôi là mảng của tôi có vẻ như không, phân bổ mảng trong phương thức viewdidload có thể là yêu cầu của bạn chạy trước viewDidLoad. Kiểm tra nó với gỡ lỗi nếu bạn thấy mảng là nill sau đó phân bổ mảng vị trí khác nhau. P.S: Tôi không phải chuyên gia nhưng có thể là vấn đề tương tự với tôi.

0

Xác định NSMutableArray bằng dòng sau.

@property (nonatomic, strong) NSMutableArray * arrData; 

initialize trong viewDidLoad

- (void)viewDidLoad { 

    [super viewDidLoad]; 

    self.arrData = [NSMutableArray array]; 
} 

gọi phương thức với bất kỳ UIButton action cho thấy output OR working behavior

- (void) TestMethod { 

    dispatch_queue_t queue = dispatch_queue_create("myQueue", 0); 

    dispatch_async(queue, ^{ 
     AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL urlWithEncoding:@"https://www.google.co.in/?gws_rd=ssl"]]; 
     [httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]]; 
     [httpClient setDefaultHeader:@"Accept" value:@"application/json"]; 
     [httpClient setParameterEncoding:AFJSONParameterEncoding]; 
     NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET" path:@"" parameters:nil]; 
     [request setTimeoutInterval:180]; 
     [AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:@"text/html"]]; 
     dispatch_semaphore_t sema = dispatch_semaphore_create(0); 

     AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) 
              { 
               [self.arrData addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"test",@"t3da",@"adsf",@"afds", nil]]; 
               dispatch_semaphore_signal(sema); 
              } failure:^ (NSURLRequest *request, NSURLResponse *response, NSError *error, id json){ 

               [self.arrData addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"test",@"t3da",@"adsf",@"afds", nil]]; 
               dispatch_semaphore_signal(sema); 
              }]; 

     [operation start]; 

     dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
     DLog(@"arrData = %@",self.arrData); 
    }); 
} 
+0

'GlobalManager' là gì – Smarto

4

Theo như tôi biết điều đó nên làm việc theo cách đó sau .. bạn có chắc thành công của bạn chặn được gọi trước khi bạn kiểm tra nội dung của allCategories?

Một tác phẩm thành công khối không đồng bộ, có nghĩa là nó sẽ được thực hiện chỉ khi RequestOperation được hoàn thành (có thể mất nhiều thời gian nếu bạn đang tải một cái gì đó lớn)

Nếu bạn đang cố gắng để có được giá trị của allCategoriestrước khi khối thành công được thực hiện, bạn sẽ không nhận được những gì bạn đang mong đợi. Tôi khuyên bạn nên sử dụng breakpoints hoặc NSLog trên khối thành công của bạn để xem liệu nó có được thực thi khi bạn nghĩ rằng nó đang thực hiện nó hay không.

ví dụ

... 
successBlock:^(AFHTTPRequestOperation *operation, id responseObject) 
{ 
    NSLog(@"Success"); 
    [self.allCategories addObject:tempObject] 
    }]; //End of request 

[operation start]; //Begin executing the AFHTTPOperation 

NSLog("%@",self.allCategories.description); //probably nil or empty 
//since the success block hasn't been called yet 

EDIT:

Như tôi mặc dù, bạn đang trở về giá trị trước khi được được thiết lập bởi các hoạt động async, để trở về một giá trị từ một hoạt động async tôi sẽ đề nghị xem xét vào số answerthis một. Ngoài ra, bạn nên đọc một chút về cách hoạt động của tác vụ async.

Về cơ bản những gì bạn muốn làm với các hoạt động/tác vụ không đồng bộ là đảm bảo giá trị sẽ khả dụng khi bạn muốn sử dụng. Vấn đề chính với điều đó là bạn không biết khi giá trị sẽ được đặt, nhưng bạn có thể đảm bảo những gì bạn muốn làm bất cứ khi nào được đặt.

Để làm điều đó bạn có thể tạo ra một phương pháp đơn giản với một kết thúc khối tùy chỉnh

- (void)myCustomMethodWithCompletionBlock: (void (^)(NSArray *))completion { 
    //Do your request 
    //... 
    successBlock:^(AFHTTPRequestOperation *operation, id responseObject) 
    { 
     NSLog(@"Success"); 
     completionBlock(allCategories); 
    }]; //End of request 
} 

Trong khi đó trong phương pháp chính của bạn, bạn gọi

[self myCustomMethodWithCompletionBlock:^(NSArray *allCategories) { 
    self.allCategories = allCategories; 
    //Do other stuff you need to with that variable since now you are 
    //sure the value will be set unless the operation failed 
    }]; 
Các vấn đề liên quan