5

我正在從一個自定義的NSObject類獲取twitter時間線數據,並且此類具有調用API並解析數據的所有係數。 我從我的視圖控制器調用這個類,它有一個表視圖,並需要使用來自twitter的數據填充tableview。但由於dispatch_sync的一些問題,我的視圖控制器調用twitter類,並且在數組填充數據(我用來填充tableview)之前,控件返回到視圖控制器。如何正確使用dispatch_sync?

下面是一些代碼:

#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; 
} 

這個類被稱爲是這樣的:

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

我知道我在一個錯誤的方式返回值,但我想通過loadData消息返回它本身的視圖控制器,但它也沒有工作,所以我只是想這個。請不要在意這一點。

感謝

+0

你是什麼意思「控制回到視圖控制器之前陣列」?什麼是控制? – yeesterbunny

+0

我的意思是NSArray * temp = dataToDisplay;在整個代碼在twitterDataLoad類中運行之前調用這一行。 – Ashutosh

+0

這很奇怪。你可以在'tmpView.dataToDisplay = complete;'中設置斷點,看它是否真的有值嗎?如果是這樣,那麼你需要在'[data loadData]'中設置斷點,然後進入它,以查看在'[data loadData]'之前如何調用'NSArray * temp = dataToDisplay''。 – yeesterbunny

回答

2

好吧,我想出了這個問題。 dispatch_sync是做什麼是應該做的問題是與其他兩個語句在其下dispatch_sync是被稱爲(其它塊)

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

所以這是一個異步調用和調度同步被調用的程序時控制返回到主隊列,因爲我們將它定義爲:dispatch_sync(dispatch_get_main_queue()) 並且該方法在控制返回主隊列之前返回,因此該數組沒有得到任何值。 所以爲了解決這個問題,我在我的調用類中寫了一個塊,一旦這個數據調用結束,就會返回調用。給我發電子郵件,如果你想要整個代碼@ ghostsmitm @ gmail.com

0

請立即撥打您UITableView一旦數據已經加載reloadData。您可以在致電loadData後執行此操作。

+0

之後我就是這樣做的,但是在整個twitter的事情發生之前就已經被調用了。 – Ashutosh