Dostaję dane wiersza czasu twitter z niestandardowej klasy NSObject i ta klasa ma wszystkie cale do wywoływania interfejsu API i analizowania danych. Wywołuję tę klasę z kontrolera widoku, który ma widok tabeli i należy wypełnić tabelę danymi pochodzącymi ze strony twitter. Ale z powodu pewnych problemów z dispatch_sync mój kontroler widoku wywołuje klasę twitter i kontrolka wraca do kontrolera widoku, zanim tablica (której używam do zapełnienia widoku tabeli) jest wypełniona danymi.Jak poprawnie używać dispatch_sync?
Oto niektóre kodu:
#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;
}
Klasa ta została nazwana tak:
- (void)viewDidLoad
{
[super viewDidLoad];
TwitterDataLoad * data = [[TwitterDataLoad alloc] init];
[data loadData];
NSArray * temp = dataToDisplay;
}
wiem Wracam wartość w niewłaściwy sposób, ale starałem wpuszczeniem go za pośrednictwem wiadomości loaddata do kontrolera widoku, ale nie działało, więc próbowałem tego. Proszę, nie przejmuj się tym.
Dzięki
Co masz na myśli "kontrola wraca do kontrolera widoku przed tablicą"? Co to jest kontrola? – yeesterbunny
Mam na myśli NSArray * temp = dataToDisplay; linia zostanie wywołana przed wykonaniem całego kodu w klasie twitterDataLoad. – Ashutosh
To dziwne. Czy możesz ustawić punkt przerwania w 'tmpView.dataToDisplay = complete;' i sprawdzić, czy rzeczywiście ma wartość? Jeśli tak, to musisz ustawić punkt przerwania w '[data loadData]' i wkroczyć do niego, aby zobaczyć, jak twoja 'NSArray * temp = dataToDisplay' zostaje wywołana przed' [data loadData] '. – yeesterbunny