Ios 带有+;(NSArray)
我正在创建一个NSObject来加载时间线twitter 代码: …可以…但我必须添加一个帐户(另一个视图)。由于它是一个+(NSArray*),所以它不能识别my(ACAccount)或同步性之外的任何对象 在开始讨论您要问的问题之前,非常值得详细讨论@Martin提到的内容:方法Ios 带有+;(NSArray),ios,cocoa-touch,nsarray,nsobject,Ios,Cocoa Touch,Nsarray,Nsobject,我正在创建一个NSObject来加载时间线twitter 代码: …可以…但我必须添加一个帐户(另一个视图)。由于它是一个+(NSArray*),所以它不能识别my(ACAccount)或同步性之外的任何对象 在开始讨论您要问的问题之前,非常值得详细讨论@Martin提到的内容:方法-[account performRequestWithHandler::是异步的 从正在执行代码的线程调用方法会导致某些活动在第二个后台启动。同时,在第一个线程上继续执行(执行performRequestWithH
-[account performRequestWithHandler::
是异步的
从正在执行代码的线程调用方法会导致某些活动在第二个后台启动。同时,在第一个线程上继续执行(执行performRequestWithHandler:
和executeTweetRequest
的线程)。调用executeTweetRequest
后的某个不确定时间段,调用作为唯一参数传递给-[account performRequestWithHandler:
的块
因此,您将无法从executeTweetRequest
同步返回tweet数组
最时髦的方法是将方法更改为基于块:
+ (void)fetchTweetsWithCompletion:(void (^)(NSArray *, NSError *))block
{
NSURL *getTweetUrl = [NSURL URLWithString:@"http://api.twitter.com/1.1/statuses/home_timeline.json"];
SLRequest *tweetRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodGET
URL:getTweetUrl
parameters:nil];
tweetRequest.account = //...this will be addressed in a moment
[tweetRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
NSError *jsonParsingError = nil;
NSArray *fetchedTweets = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&jsonParsingError];
block(fetchedTweets, jsonParsingError);
}
}];
}
当从第二个UITableViewController
子类调用fetchTweetsWithCompletion:
时,您将传入一个块,可能类似于以下内容:
- (void)viewDidLoad
{
//...
[TwitterWrapper fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
}
此代码的结果是,一旦后台队列上的tweets获取完成,表视图控制器的属性tweets
将设置为获取的结果,并且其表视图将重新加载其数据
范围(解决问题)
你所描述的问题
因为它是一个+(NSArray*),所以它不能识别my(ACAccount)或外部的任何对象
就是你不能从你的类方法+[TwitterWrapper ExecuteTweetFeetFetch]
中访问你的类的任何实例的实例变量(为了方便,我称它为TwitterWrapper
)。这里的问题是其中之一。(因此,多亏了,问题还在于内存管理。)
我们的目标是将ACAccount
的实例隐藏在第一个表视图控制器的某个位置,并从第二个表视图控制器访问该实例
有几种方法可以做到这一点:
使用全局变量
最糟糕的是使用可怕的:
在TwitterWrapper.h中,您将声明twitter的extern
帐户:
//TwitterWrapper.h
extern ACAccount *twitterAccount;
@interface TwitterWrapper : executeTweetFetch
+ (void)fetchTweetsWithCompletion:(void (^)(NSArray *, NSError *))block;
@end
在TwitterWrapper.m
中,您将定义twitterAccount
,使其具有全局范围(例如,在@实现之前
块:
ACAccount *twitterAccount;
@implementation TwitterWrapper
//...
@end
在类方法的定义中,您应该
+ (void)fetchTweetsWithCompletion:(void (^)(NSArray *, NSError *))block
{
//...
tweetRequest.account = twitterAccount;
//...
}
注意:这种方法非常不时尚,更不用说完全危险了。在这种情况下,避免这种方法当然是可能的
接下来的两种方法都涉及将
fetchTweetsWithCompletion:
更改为实例方法,并将acacaccount
属性添加到TwitterWrapper
@interface TwitterWrapper : NSObject
@property (nonatomic) ACAccount *account;
- (void)fetchTweetsWithCompletion:(void (^)(NSArray *, NSError *))block;
@end
@implementation TwitterWrapper
- (void)fetchTweetsWithCompletion:(void (^)(NSArray *, NSError *))block
{
//...
twitterRequest.account = self.account;
//...
}
@end
@实现
如下所示
@interface TwitterWrapper : NSObject
@property (nonatomic) ACAccount *account;
- (void)fetchTweetsWithCompletion:(void (^)(NSArray *, NSError *))block;
@end
@implementation TwitterWrapper
- (void)fetchTweetsWithCompletion:(void (^)(NSArray *, NSError *))block
{
//...
twitterRequest.account = self.account;
//...
}
@end
使用共享实例
在这种情况下,第二种最糟糕的方法是使用TwitterWrapper的共享实例。这涉及到向类中添加一个类方法(称为类似于+SharedRapper
)的聪明方法:
@interface TwitterWrapper : NSObject
+ (TwitterWrapper *)sharedWrapper;
@property (nonatomic) ACAccount *account;
- (void)fetchTweetsWithCompletion:(void (^)(NSArray *, NSError *))block;
@end
并使用的来初始化:
此时,您有了一个TwitterWrapper的实例,您可以将第一个表视图控制器中的ACAccount的实例存储到该实例中,并从第二个表视图控制器中使用(通过self.account
在-fetchTweetsWithCompletion:
的实现中使用):
在第一个UITableViewController
子类中的某个地方
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
[[TwitterWrapper sharedWrapper] setAccount:theAccount];
//...
//...
[[TwitterWrapper sharedWrapper] fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
TwitterWrapper *theTwitterWrapper = [[TwitterWrapper alloc] init];
twitterWrapper.account = theAccount;
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.twitterWrapper = theTwitterWrapper;
//...
//...
[self.twitterWrapper fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = ////this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.account = theAccount;
//...
//...
[TwitterWrapper fetchTweetsWithAccount:self.account completion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
然后,在第二个UITableViewController
子类中(可能在-viewDidLoad
中),您将
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
[[TwitterWrapper sharedWrapper] setAccount:theAccount];
//...
//...
[[TwitterWrapper sharedWrapper] fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
TwitterWrapper *theTwitterWrapper = [[TwitterWrapper alloc] init];
twitterWrapper.account = theAccount;
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.twitterWrapper = theTwitterWrapper;
//...
//...
[self.twitterWrapper fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = ////this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.account = theAccount;
//...
//...
[TwitterWrapper fetchTweetsWithAccount:self.account completion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
但是,此解决方案与使用全局变量非常相似(区别在于全局变量的创建是线程安全的)
传递TwitterWrapper的实例
更好的解决方案是将TwitterWrapper
的实例从第一个表视图控制器传递到第二个表视图控制器
注意:为简洁起见,我假设在用户选择第一个表视图控制器中的帐户行后,第二个表视图控制器立即变为活动状态
为此,您需要添加一个属性
@property (nonatomic) TwitterWrapper *twitterWrapper;
到第二个UITableViewController
子类
在第一个表视图控制器中的某个位置
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
[[TwitterWrapper sharedWrapper] setAccount:theAccount];
//...
//...
[[TwitterWrapper sharedWrapper] fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
TwitterWrapper *theTwitterWrapper = [[TwitterWrapper alloc] init];
twitterWrapper.account = theAccount;
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.twitterWrapper = theTwitterWrapper;
//...
//...
[self.twitterWrapper fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = ////this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.account = theAccount;
//...
//...
[TwitterWrapper fetchTweetsWithAccount:self.account completion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
然后,在第二个UITableViewController
子类中(可能在-viewDidLoad
中),您将
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
[[TwitterWrapper sharedWrapper] setAccount:theAccount];
//...
//...
[[TwitterWrapper sharedWrapper] fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
TwitterWrapper *theTwitterWrapper = [[TwitterWrapper alloc] init];
twitterWrapper.account = theAccount;
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.twitterWrapper = theTwitterWrapper;
//...
//...
[self.twitterWrapper fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = ////this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.account = theAccount;
//...
//...
[TwitterWrapper fetchTweetsWithAccount:self.account completion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
传递account的一个实例
与其在第二个UITableViewController
子类实例上存储TwitterWrapper
的实例,最好的解决方案是存储acacaccount
的实例,并更改TwitterWrapper
的接口以再次获取tweet
在这种情况下,我们希望fetch方法再次成为类方法。正如@MartinR所建议的,向fetch方法添加account参数:
+ (void)fetchTweetsWithAccount:(ACAccount *)theAccount completion:(void (^)(NSArray *, NSError *))block
{
NSURL *getTweetUrl = [NSURL URLWithString:@"http://api.twitter.com/1.1/statuses/home_timeline.json"];
SLRequest *tweetRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodGET
URL:getTweetUrl
parameters:nil];
tweetRequest.account = theAccount;
[tweetRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
NSError *jsonParsingError = nil;
NSArray *fetchedTweets = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&jsonParsingError];
block(fetchedTweets, jsonParsingError);
}
}];
}
接下来,将类型为ACAccount
的属性添加到第二个UITableViewController
子类:
@property (nonatomic) ACAccount *account;
然后,在第一个表视图控制器中的某个地方
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
[[TwitterWrapper sharedWrapper] setAccount:theAccount];
//...
//...
[[TwitterWrapper sharedWrapper] fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
TwitterWrapper *theTwitterWrapper = [[TwitterWrapper alloc] init];
twitterWrapper.account = theAccount;
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.twitterWrapper = theTwitterWrapper;
//...
//...
[self.twitterWrapper fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = ////this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.account = theAccount;
//...
//...
[TwitterWrapper fetchTweetsWithAccount:self.account completion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
然后,在第二个UITableViewController
子类中(可能在-viewDidLoad
中),您将
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
[[TwitterWrapper sharedWrapper] setAccount:theAccount];
//...
//...
[[TwitterWrapper sharedWrapper] fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = //this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
TwitterWrapper *theTwitterWrapper = [[TwitterWrapper alloc] init];
twitterWrapper.account = theAccount;
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.twitterWrapper = theTwitterWrapper;
//...
//...
[self.twitterWrapper fetchTweetsWithCompletion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
//...
ACAccount *theAccount = ////this is initialized somehow within this class (the first UITableViewController subclass), probably by the selection of a row
SecondTableViewController *tweetsTableViewController = //initialize the table view controller
tweetsTableViewController.account = theAccount;
//...
//...
[TwitterWrapper fetchTweetsWithAccount:self.account completion:^(NSArray *tweets, NSError *error) {
if (tweets) {
self.tweets = tweets;
[self.tableView reloadData];
} else if (error) {
//present a UIAlertView, perhaps...
}
}];
//...
“我必须添加一个ACAccount(另一个视图)”是什么意思?编辑…用户在其他视图(TableView)中选择一个帐户为什么不添加另一个参数:+(NSArray*)executeweetfetchforaccount:(ACAccount*)account
?-但是