Accounts.framework简介
帮助用户访问和管理他们的外部帐户,而不需要他们进入账户的登录认证。
Accounts framework 提供了 专门用来存储 帐户数据库中并提供访问方法。
帐户存储特定服务的登录凭据,如可以用作服务的身份验证的特定服务的登录凭据。
比如twiter经过认证,就不需要登录用户名和密码就可以获得fans的数量
如果在用户的帐户数据库中不存在某个特定服务的帐户,您可以让他们在应用程序中创建和保存一个帐户。
acaccount
一个acaccount对象封装的信息存储在用户帐户的帐户数据库。您可以创建和使用一个acaccountstore对象检索帐户。的acaccountstore对象提供了持续的帐户数据库接口。对于每个用户,所有帐户对象属于一个单一的acaccountstore对象。
一个acaccount对象封装的信息存储在用户帐户的帐户数据库。您可以创建和使用一个acaccountstore对象检索帐户。的acaccountstore对象提供了持续的帐户数据库接口。对于每个用户,所有帐户对象属于一个单一的acaccountstore对象。
acaccountcredential
一个acaccountcredential对象封装需要验证用户信息。
acaccountstore
acaccountstore类提供一个接口,用于访问、操纵和存储账户。创建和帐户数据库检索帐户,您必须创建一个acaccountstore对象。每个acaccount对象属于一个acaccountstore对象。
acaccounttype
#import <UIKit/UIKit.h>
#import "IDZAvatarDownloader.h"
@class DetailViewController;
@interface IDZTwitterFollowersViewController : UITableViewController<IDZAvatarDownloader>
@property (strong, nonatomic) DetailViewController *detailViewController;
@end
#import "IDZTwitterFollowersViewController.h"
#import <Accounts/Accounts.h>
#import <Social/Social.h>
#import "IDZAvatarDownloader.h"
@interface IDZTwitterFollowersViewController () {
NSMutableArray *_objects;
NSMutableDictionary* mImageCache;
NSMutableDictionary* mDownloaders;
}
@end
@implementation IDZTwitterFollowersViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(@"Followers", @"Followers");
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
}
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ACAccountStore* accountStore = [[ACAccountStore alloc] init];
ACAccountType* accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
/*
* It's not clear from Apple's documentation whether this call will succeed if access has not
* been granted.
*/
NSArray* twitterAccounts = [accountStore accountsWithAccountType:accountType];
if(twitterAccounts.count == 0)
{
NSLog(@"No accounts set up?.");
}
/*
* On the simulator, if there are no twitter accounts set, this request will always return access denied.
*/
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError* error)
{
if(granted)
{
NSLog(@"Access granted. account=%@", accountStore);
[self accessGranted:accountStore];
}
else
{
NSLog(@"Access denied. error=%@ localizedDescripton=%@", error, [error localizedDescription]);
}
}
];
}
- (void)accessGranted:(ACAccountStore *)accountStore
{
ACAccountType* accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
NSArray* accounts = [accountStore accountsWithAccountType:accountType];
NSLog(@"accounts=%@", accounts);
if(accounts.count > 0)
{
//[self postStatusesUpdateForAccount:[accounts lastObject] status:@"Sammy De Beer is on twitter. (Test)."];
ACAccount* account = [accounts lastObject];
[self getFollowersListForAccount:account];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _objects.count;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
/*
* Remember:
* UITableViewCellStyleDefault has image, but no subtitle.
* UITableViewCellStyleSubtitle
*/
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
NSDictionary *object = _objects[indexPath.row];
cell.textLabel.text = [object objectForKey:@"name"];
cell.detailTextLabel.text = @"detail";
id profileImageURL = [object objectForKey:@"profile_image_url"];
NSURL* url = [NSURL URLWithString:profileImageURL];
cell.imageView.image = [mImageCache objectForKey:url];
if(!cell.imageView.image && ![mDownloaders objectForKey:indexPath])
{
IDZAvatarDownloader* downloader = [[IDZAvatarDownloader alloc] initWithURL:url delegate:self context:indexPath];
[downloader startDownload];
[mDownloaders setObject:downloader forKey:indexPath];
}
else
{
NSLog(@"Cache hit");
}
NSLog(@"picture=%@ %@", [profileImageURL class], profileImageURL);
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/**
* https://dev.twitter.com/docs/api/1.1/get/followers/list
*/
- (void)getFollowersListForAccount:(ACAccount*)account
{
NSURL* url = [NSURL URLWithString:@"https://api.twitter.com/1.1/followers/list.json"];
SLRequest* getRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:url parameters:nil];
getRequest.account = account;
[getRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
[self followersListCompletedWithData:responseData response:urlResponse error:error];
}
];
}
/**
* @brief Callback for completed SLRequest
*
*/
- (void)followersListCompletedWithData:(NSData*)data response:(NSHTTPURLResponse*)response error:(NSError*)error
{
dispatch_async(dispatch_get_main_queue(), ^{
[self mainFollowersListCompletedWithData:data response:response error:error];
});
}
- (void)mainFollowersListCompletedWithData:(NSData*)data response:(NSHTTPURLResponse*)response error:(NSError*)error
{
NSLog(@"urlResponse.statusCode=%d", response.statusCode);
if(error)
{
NSLog(@"requestCompletedWithError = %@", error);
}
else
{
// NSString *dataAsString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSDictionary* jsonSerialization = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableLeaves
error:&error];
_objects = [jsonSerialization objectForKey:@"users"];
[self.tableView reloadData];
}
}
// MARK: -
- (void)downloader:(IDZAvatarDownloader*)downloader didDownloadAvatar:(UIImage*)avatar context:(id)context
{
NSLog(@"Download complete for index path %@ url=%@", context, [downloader.response.URL absoluteString]);
NSURL* url = downloader.response.URL;
NSIndexPath* indexPath = (NSIndexPath*)context;
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.imageView.image = avatar;
[cell layoutSubviews];
[mImageCache setObject:avatar forKey:url];
[mDownloaders removeObjectForKey:indexPath];
}
- (void)downloader:(IDZAvatarDownloader*)downloader didFailWithError:(NSError*)error context:(id)context
{
NSLog(@"%s", __PRETTY_FUNCTION__);
}
@end
运行结果
每一个bundleID只会运行一次