ios - 如何正确使用dispatch_sync?

标签 ios objective-c objective-c-blocks grand-central-dispatch

我正在从自定义 NSObject 类获取 Twitter 时间线数据,并且此类具有调用 API 和解析数据的所有 coe。 我从我的 View Controller 调用此类,它有一个 TableView ,需要用来自 Twitter 的数据填充 TableView 。但是由于 dispatch_sync 的一些问题,我的 View Controller 调用了 twitter 类,并且在数组(我用来填充 TableView )填充数据之前控制权返回到 View Controller 。

这是一些代码:

#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 ,但它也不起作用,所以我只是尝试这样做。请不要关心这个。

谢谢

最佳答案

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

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

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

关于ios - 如何正确使用dispatch_sync?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13224344/

相关文章:

iphone - 如果我有嵌套的 dispatch_async 调用会发生什么?

ios - fatal error : Array index out of range, map 应用

iphone - 将 JSON 映射到核心数据对象

ios - 使用 SwiftUI 接收 APNS 后显示 View

objective-c - 如何在 Objective-C 中使用 block 进行结构化编程

ios - 在 iOS 编程中是否必须使用 release 进行内存管理?

ios - Xcode 8 - 删除了一些按钮边框

objective-c - 遵守协议(protocol)有什么好处,如果父类(super class)这样做,我是否需要声明它?

ios - 程序暗恋 [order setPrice :price] break point at @synthesize name

iphone - 在bannerViewActionDidFinish : Bug or Not?之后AdBannerView移动到 super View 的顶部