5

カスタム NSObject クラスから Twitter タイムライン データを取得しています。このクラスには、API を呼び出してデータを解析するためのすべての coe があります。テーブルビューを持ち、テーブルビューにtwitterからのデータを入力する必要があるビューコントローラーからこのクラスを呼び出しています。しかし、dispatch_sync のいくつかの問題により、ビュー コントローラーが twitter クラスを呼び出し、配列 (テーブルビューの入力に使用しています) にデータが入力される前に、コントロールがビュー コントローラーに戻ります。

ここにいくつかのコードがあります:

#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メッセージ自体を介してView Controllerに返そうとしましたが、どちらも機能しなかったので、これを試してみました. 気にしないでください。

ありがとう

4

2 に答える 2

2

さて、私はこれで問題を理解しました。dispatch_sync は本来の処理を行っています。問題は、dispatch_sync が呼び出された他の 2 つのステートメント (他のブロック) にあります。

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

したがって、これは非同期呼び出しであり、次のように定義されているため、プログラム コントロールがメイン キューに戻ったときにディスパッチ同期が呼び出されます。配列は値を取得しません。これを解決するために、このデータ呼び出しが終了するとリターン呼び出しを取得する呼び出しクラスにブロックを作成しました。コード全体が必要な場合は、私にメールしてください @ghostsmitm@gmail.com

于 2012-11-09T15:38:48.077 に答える
0

データがロードされreloadDataたら、を呼び出す必要があります。UITableViewこれは、 を呼び出した後に行うことができますloadData

于 2012-11-05T00:14:57.670 に答える