5

我从一个自定义的 NSObject 类获取 twitter 时间线数据,这个类具有调用 API 和解析数据的所有核心。我从我的视图控制器调用这个类,它有一个表视图,需要用来自 twitter 的数据填充表视图。但是由于 dispatch_sync 的一些问题,我的视图控制器调用了 twitter 类,并且控制在 Array(我用来填充 tableview)填充数据之前返回到视图控制器。

这是一些代码:

#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 消息本身将它返回到视图控制器,但它也不起作用,所以我只是在尝试这个。请不要在意那个。

谢谢

4

2 回答 2

2

好吧,我发现了这个问题。dispatch_sync 正在做它应该做的问题是与调用 dispatch_sync 的其他两个语句(其他块)

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

所以这是一个异步调用,当程序控制回到主队列时调用调度同步,因为我们定义它是这样的:dispatch_sync(dispatch_get_main_queue()) 并且该方法在控制返回到主队列之前返回,因此该数组没有任何价值。所以为了解决这个问题,我在我的调用类中写了一个块,一旦这个数据调用结束,它就会得到返回调用。如果您想要整个代码,请给我发电子邮件@ghostsmitm@gmail.com

于 2012-11-09T15:38:48.077 回答
0

加载数据后,您应该调用reloadData您的。UITableView您可以在调用后执行此操作loadData

于 2012-11-05T00:14:57.670 回答