5

Tôi nhận được dữ liệu dòng thời gian twitter từ một lớp NSObject tùy chỉnh và lớp này có tất cả các coe để gọi API và phân tích cú pháp dữ liệu. Tôi đang gọi lớp này từ bộ điều khiển xem của tôi có chế độ xem bảng và cần điền vào bảng nhìn cùng với dữ liệu đến từ twitter. Nhưng do một số vấn đề với dispatch_sync trình điều khiển xem của tôi gọi lớp twitter và điều khiển quay trở lại bộ điều khiển xem trước khi mảng (mà tôi đang sử dụng để điền bảng) được điền dữ liệu.Cách sử dụng dispatch_sync chính xác?

Dưới đây là một số mã:

#import <UIKit/UIKit.h> 
#import "SecondViewController.h" 
#import "SpinnerController.h" 
#import "proAlertView.h" 
#import "SBJson.h" 
#import <Accounts/Accounts.h> 
#import <Twitter/Twitter.h> 

@interface TwitterDataLoad : NSObject<UIAlertViewDelegate> 
{ 
    NSMutableData * receivedData; 
    NSArray * results; 
    NSArray * cellContent; 
    NSMutableArray * totalContent; 
    SpinnerController * spinner; 
    proAlertView * av; 
    NSString *json_string; 
    NSDictionary * jsonResults; 
    SBJsonParser * parser; 
    NSMutableArray * dataForTable; 

} 
@property(nonatomic, strong) ACAccount * account; 
@property(nonatomic, strong) NSArray * accounts; 
@property(nonatomic, strong) ACAccountStore * accountStore; 
@property (nonatomic ,retain) SecondViewController * tbView; 

- (void)loadData; 

@end 

#import "TwitterDataLoad.h" 


@interface TwitterDataLoad() 

@end 

@implementation TwitterDataLoad 
@synthesize tbView; 


-(id) init { 
    self = [super init]; 
    if (self) { 
     [self loadData]; 
    } 
    return self; 
} 

- (void)loadData 
{ 
    dataForTable = [[NSMutableArray alloc]init]; 
    //Twitter new code 

    if (_accounts == nil) { 
     if (_accountStore == nil) { 
      _accountStore = [[ACAccountStore alloc] init]; 
     } 
     ACAccountType *accountTypeTwitter = 
     [_accountStore 
     accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter]; 
     [_accountStore requestAccessToAccountsWithType:accountTypeTwitter 
            withCompletionHandler:^(BOOL granted, NSError *error) { 
             if(granted) { 
              dispatch_sync(dispatch_get_main_queue(), ^{ 
               _accounts = [_accountStore 
                    accountsWithAccountType:accountTypeTwitter]; 

               [self sendRequest]; 
              }); 
             } 
            }]; 
    } 
} 

-(void) sendRequest { 

    totalContent = [[NSMutableArray alloc]init]; 
    _account = [_accounts objectAtIndex:0]; 

    TWRequest *postRequest = [[TWRequest alloc] 
           initWithURL: 
           [NSURL URLWithString:@"https://api.twitter.com/1/statuses/user_timeline.json?screen_name=test&count=20"] 
           parameters:nil 
           requestMethod:TWRequestMethodGET]; 

    av = [[proAlertView alloc]initWithTitle:nil message:@"Getting latest news..." delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil]; 
    UIActivityIndicatorView * indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; 
    indicator.frame = CGRectMake(120, 55, 35, 35); 
    [av addSubview:indicator]; 
    [indicator startAnimating]; 
    [av setBackgroundColor:[UIColor clearColor] withStrokeColor:[UIColor blackColor]]; 
    [av show]; 


    [postRequest setAccount:_account]; 
    [postRequest performRequestWithHandler:^(NSData *responseData, 
              NSHTTPURLResponse *urlResponse, 
              NSError *error) { 
     if ([urlResponse statusCode] == 200) { 
      NSError *jsonError = nil; 
      results = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&jsonError]; 

      dispatch_sync(dispatch_get_main_queue(), ^{ 
       [av dismissAlert]; 
       [self parseJson]; 
      }); 
     } 
     else { 
      [self showMessage]; 
     } 
    }]; 

} 

-(void)showMessage { 

    av = [[proAlertView alloc]initWithTitle:@"Connection Problem" message:@"Please confirm the device is connected to the Internet." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; 
    [av setBackgroundColor:[UIColor clearColor] withStrokeColor:[UIColor blackColor]]; 
    [av show]; 
} 

-(void)parseJson { 

    NSMutableArray * complete = [[NSMutableArray alloc]init]; 
    for (NSDictionary * tweets in results) 
     { 
     NSString * status = [tweets objectForKey:@"text"]; 
     NSString * date = [tweets objectForKey:@"created_at"]; 
     NSDictionary * user = [tweets objectForKey:@"user"]; 
     NSString * artistName = [user objectForKey:@"name"]; 
     NSString * screenName = [user objectForKey:@"screen_name"]; 
     NSString * artistImage = [user objectForKey:@"profile_image_url"]; 
     cellContent = [NSArray arrayWithObjects:status,date,artistName,screenName,artistImage, nil]; 
     [complete addObject:cellContent]; 
     } 

     SecondViewController * tmpView = [[SecondViewController alloc]initWithNibName:@"SecondViewController_iPhone" bundle:nil]; 
      tmpView.dataToDisplay = complete; 
} 

lớp này đã được gọi là như thế này:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    TwitterDataLoad * data = [[TwitterDataLoad alloc] init]; 
    [data loadData]; 
    NSArray * temp = dataToDisplay; 
} 

Tôi biết tôi đang trở về giá trị trong một cách sai lầm, nhưng tôi đã cố gắng trở về nó thông qua thông điệp loadData chính nó cho bộ điều khiển xem nhưng nó không hoạt động hoặc vì vậy tôi đã chỉ cố gắng này. Xin đừng quan tâm về điều đó.

Cảm ơn

+0

Ý của bạn là "điều khiển quay lại bộ điều khiển xem trước Array"? Kiểm soát là gì? – yeesterbunny

+0

Tôi có nghĩa là NSArray * temp = dataToDisplay; dòng này được gọi trước khi toàn bộ mã được thực hiện chạy trong lớp twitterDataLoad. – Ashutosh

+0

Điều đó thật kỳ lạ. Bạn có thể đặt breakpoint tại 'tmpView.dataToDisplay = complete;' và xem nó có thực sự có giá trị không? Nếu có, thì bạn cần đặt breakpoint tại '[data loadData]' và bước vào nó để xem cách 'NSArray * temp = dataToDisplay' của bạn được gọi trước' [data loadData] '. – yeesterbunny

Trả lời

2

Được rồi tôi đã tìm ra vấn đề với điều này. dispatch_sync là làm những gì nó là vụ phải làm vấn đề là với hai báo cáo khác theo đó dispatch_sync được được gọi là (các khối khác)

[_accountStore requestAccessToAccountsWithType:accountTypeTwitter 
             withCompletionHandler:^(BOOL granted, NSError *error) 

vì vậy đây là một cuộc gọi không đồng bộ và đồng bộ hóa công văn được gọi khi chương trình kiểm soát được trở lại trên hàng đợi chính như chúng tôi đã xác định như thế này: dispatch_sync (dispatch_get_main_queue()) và phương thức trả về trước khi điều khiển được trở lại trên hàng đợi chính và do đó mảng không nhận được bất kỳ giá trị nào. Vì vậy, để giải quyết điều này tôi đã viết một khối trong lớp gọi điện thoại của tôi mà được gọi trở lại sau khi cuộc gọi dữ liệu này là hơn. gửi email cho tôi nếu bạn muốn toàn bộ mã @ ghostsmitm @ gmail.com

0

Bạn nên gọi reloadData trên UITableView một khi dữ liệu đã được tải của bạn. Bạn có thể thực hiện việc này sau khi gọi số loadData.

+0

Tôi đang làm điều đó sau đó nhưng đó là nhận được gọi trước khi điều này toàn bộ twitter. – Ashutosh

Các vấn đề liên quan