I'd like to fetch (in iOS using Objective-C) only the contacts that have a phone number, but how can I do that? I'm trying to form the predicate as in the code below, but obviously that doesn't work.
contacts = [contactStore unifiedContactsMatchingPredicate:[NSPredicate predicateWithFormat:#"phoneNumbers <> nil"] keysToFetch:KEYS error:nil];
So, what is the correct way of doing this? Thanks for any help!
#import <Contacts/Contacts.h>
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES) {
//keys with fetching properties
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey, CNContactEmailAddressesKey];
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
request.sortOrder = CNContactSortOrderGivenName;
request.unifyResults = YES;
NSError *error;
__block NSString* email;
BOOL success = [store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * __nonnull contact, BOOL * __nonnull stop)
{
if (error) {
NSLog(#"error fetching contacts %#", error);
} else {
NSString *fullName;
NSString* phone;
// for (CNContact *contact in cnContacts) {
DeviceContact *aContact = [DeviceContact new];
// copy data to my custom Contacts class.
NSString *firstName = contact.givenName;
NSString *lastName = contact.familyName;
if (lastName == nil) {
fullName=[NSString stringWithFormat:#"%#",firstName];
}else if (firstName == nil){
fullName=[NSString stringWithFormat:#"%#",lastName];
}
else{
fullName=[NSString stringWithFormat:#"%# %#",firstName,lastName];
}
if ([firstName trim].length > 0) {
aContact.nameForSorting = firstName; // 141116
}else if ([lastName trim].length>0 && aContact.nameForSorting.length<=0) {
aContact.nameForSorting = lastName; // 141116
}
aContact.name = fullName;
if (contact.phoneNumbers!=nil && [contact.phoneNumbers count]>0) {
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [CommonUtils removeAllSpecialCharactersFromPhoneNumber:[label.value stringValue]];
if ([phone length] > 0) {
[aContact.phoneNumber addObject:phone];
}
}
}
////Get all E-Mail addresses from contacts
/// if ([CommonUtils checkIsNullObject:[contact emailAddresses]] && [[contact emailAddresses] count]>0) {
for (CNLabeledValue *label in contact.emailAddresses) {
email = label.value;
if ([email length] > 0)
{
[aContact.email addObject:email];
}
}
// }
// 141116
if ([aContact.name trim].length <= 0) {
if (aContact.email.count>0) {
aContact.name = [aContact.email objectAtIndex:0];
}else if (aContact.phoneNumber.count>0){
aContact.name = [aContact.phoneNumber objectAtIndex:0];
}
}
if ([aContact.nameForSorting trim].length <= 0){
if (aContact.email.count>0) {
aContact.nameForSorting = [aContact.email objectAtIndex:0];
}else if (aContact.phoneNumber.count>0){
aContact.nameForSorting = [aContact.phoneNumber objectAtIndex:0];
}
}
[self.arrAllContacts addObject:aContact];
}
}];
if(success){
dispatch_async(dispatch_get_main_queue(), ^{
[CommonUtils hideLoader];
completionhandler(self.arrAllContacts);
});
}
}
else
{
// [CommonUtils showAlertMessageWithMessage:#"fdfdggfsgfdgfd" withDelegate:self withCancelTitle:OKAY isOtherButton:NO withOtherButtonTitle:nil withTag:0];
[CommonUtils hideLoader];
}
}];
use following method and import
#import <AddressBook/AddressBook.h>
#import <Contacts/Contacts.h>
-(void)contactsDetailsFromPhoneContactBook{
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES) {
//keys with fetching properties
NSArray *keys = #[CNContactFamilyNameKey,CNContactGivenNameKey];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error) {
NSLog(#"error fetching contacts %#", error);
} else {
NSString *fullName;
NSString *firstName;
NSString *lastName;
for (CNContact *contact in cnContacts) {
// copy data to my custom Contacts class.
firstName = contact.givenName;
lastName = contact.familyName;
if (lastName == nil) {
fullName=[NSString stringWithFormat:#"%#",firstName];
}else if (firstName == nil){
fullName=[NSString stringWithFormat:#"%#",lastName];
}
else{
fullName=[NSString stringWithFormat:#"%# %#",firstName,lastName];
}
[self.contactsArray addObject:fullName];
NSLog(#"working or not %#",self.contactsArray);
}
}
}
}];
}
Filtering out the contacts that don't have a phone number (or some other property) is not possible. In the docs we read:
CNContact Predicates
Predicates to match contacts. You can only use these predicates
with CNContactStore and CNContactFetchRequest.
predicateForContactsMatchingName: Returns a predicate to find the contacts matching the specified name.
predicateForContactsWithIdentifiers: Returns a predicate to find the contacts matching the specified identifiers.
predicateForContactsInGroupWithIdentifier: Returns a predicate to find the contacts that are members in the specified group.
predicateForContactsInContainerWithIdentifier: Returns a predicate to find the contacts in the specified container.
And additionally:
Compound predicates are not supported.
So, the only way to do the filtering would be to omit adding to the result array the contacts with no phone numbers. That could be done, for example, in the block of the enumerateContactsWithFetchRequest.
Related
I am fetching the mobile contacts by using below method
-(void)fetchContactsandAuthorization
{
// Request authorization to Contacts
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES)
{
//make sure that you have added the necessary properties
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey, CNContactPostalAddressesKey];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
NSLog(#"new %#",cnContacts);
if (error)
{
NSLog(#"error fetching contacts %#", error);
}
else
{
NSString *phone;
NSString *fullName;
NSString *firstName;
NSString *lastName;
NSString *companyName;
NSString *departmentName;
NSString *jobTitleName;
NSString *address;
NSString *iden;
NSString *emailAddress;
UIImage *profileImage;
NSMutableArray *contactNumbersArray = [[NSMutableArray alloc]init];
NSMutableArray *addressArray = [[NSMutableArray alloc]init];
NSMutableArray *emailAddressArray = [[NSMutableArray alloc]init];
for (CNContact *contact in cnContacts) {
// copy data to my custom Contacts class.
firstName = contact.givenName;
lastName = contact.familyName;
iden = contact.identifier;
if (lastName == nil) {
fullName=[NSString stringWithFormat:#"%#",firstName];
}else if (firstName == nil){
fullName=[NSString stringWithFormat:#"%#",lastName];
}
else{
fullName=[NSString stringWithFormat:#"%# %#",firstName,lastName];
}
UIImage *image = [UIImage imageWithData:contact.imageData];
NSLog(#"imgold %#",image);
if (image != nil) {
profileImage = image;
}else{
profileImage = [UIImage imageNamed:#"person-icon.png"];
}
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
if ([phone length] > 0) {
[contactNumbersArray addObject:phone];
}
}
NSLog(#"PhonenumberArray %#",contactNumbersArray);
User *user = [User new];
user.fullName=fullName;
user.image= profileImage;
user.phone= phone;
user.idUser= iden;
[contacts addObject:user];
}
dispatch_async(dispatch_get_main_queue(), ^{
[_selectContactListTblView reloadData];
});
}
}
}];
}
I am able to get all phone numbers associated with the contact and able to store in an array.
PhonenumberArray (
"98708\U00a001224",
"98920\U00a077702",
"93240\U00a077702",
1,
2,
3,
4,
5,
5,
6,
7,
8,
9
)
Now i want to differentiate the phonenumbers in array like home,mobile,fax,pager etc. Any help will be really appreciated.
The CNLabeledValue label property will return a string that represents home, mobile etc. Then call [CNLabeledValue localizedStringForLabel:labelString] to get a localized human readable string.
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
labelString = label.label;
if ([phone length] > 0) {
[contactNumbersArray addObject:phone];
[contactNumbersLabelsArray addObject:labelString];
}
}
Check this blog https://genericswift.wordpress.com/, It will fetch all contacts from contact store and will differentiate it with home,mobile,fax,pager etc.
Code is in this Github link https://github.com/VinupriyaArivazhagan/AVContactPickerController
Just need a line of code to pesent view controller with all fetched contacts
AVContactPickerController.present(title: "Contact", maximumContactCount: nil, updateDesign: nil)
and can update design as well
AVContactPickerController.present(title: "Contact", maximumContactCount: 2, updateDesign: { controller in
controller.checkImage = #imageLiteral(resourceName: "Clicked")
controller.uncheckImage = #imageLiteral(resourceName: "Click")
controller.closeButton.setTitleColor(UIColor.red, for: .normal)
})
I'm implementing a logic to check whether a contact exists or not in the contacts list and based upon this result I'm inserting the contact. My progress so far:
__block NSString *strPhoneNumber = #"1093874652";
if ([CNContactStore class]) {
CNContactStore *addressBook = [[CNContactStore alloc] init];
NSArray *keysToFetch =#[CNContactPhoneNumbersKey];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSError *error = nil;
CNContactFetchRequest *fetchRequest =[[CNContactFetchRequest alloc] initWithKeysToFetch:keysToFetch];
__block BOOL isExists = NO;
[addressBook enumerateContactsWithFetchRequest:fetchRequest error:&error usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
NSArray *phoneNumbers =[[contact.phoneNumbers valueForKey:#"value"] valueForKey:#"digits"];
if ([phoneNumbers containsObject:strPhoneNumber]) {
isExists = YES;
*stop = YES;
}
else
isExists = NO;
}];
dispatch_async(dispatch_get_main_queue(), ^{
if (isExists == NO) {
//This is the method for saving the contacts. I'm not implementing here.
[self saveContactWithName:#"John Doe" withContactEmail:#"johndoe#abc.com#" withContactPhone:str];
}
});
});
}
Now, the problem is after enumerating, the code under if (isExists == NO) fires several times and saving the contact multiple times.How do I stop it? My only need is if the contact exits then don't save it otherwise save it only one time. Any help will be appreciated.
replace the below part in your code,
NSArray *phoneNumbers = [[contact.phoneNumbers valueForKey:#"value"] valueForKey:#"digits"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self == [c] %#", strPhoneNumber];
NSArray *filtered = [phoneNumbers filteredArrayUsingPredicate:predicate];
if ([filtered count] > 0) {
isExists = YES;
*stop = YES;
}
else
isExists = NO;
}];
I am working on app where I need to import contacts into NSMutableDictionary, but sometimes people not filling all contact details. So leaving just number or company name. Do I need to go through all contacts detail to check what field will be my "display name". In Android I know there is displayName variable. But how it is in Swift or Objective C?
My code:
BOOL success = [addressBook
enumerateContactsWithFetchRequest:request
error:&contactError
usingBlock:^(CNContact *contact, BOOL *stop){
NSString * contactId = contact.identifier;
NSString * firstName = contact.givenName;
NSString * lastName = contact.familyName;
}];
Use CNContactFormatter to build the display name. When specifying the keys for the request, use descriptorForRequiredKeysForStyle to make sure you requested the appropriate fields.
In Swift, it would be:
let store = CNContactStore()
store.requestAccess(for: .contacts) { granted, error in
guard granted else {
print(error?.localizedDescription ?? "Unknown error")
return
}
let request = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey as CNKeyDescriptor, CNContactFormatter.descriptorForRequiredKeys(for: .fullName)])
let formatter = CNContactFormatter()
formatter.style = .fullName
do {
try store.enumerateContacts(with: request) { contact, stop in
if let name = formatter.string(from: contact) {
print(name)
}
}
} catch let fetchError {
print(fetchError)
}
}
You suggested that you have situations where there is neither name nor company, but just phone number. Well, then, you'd have to manually handle that yourself:
let request = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey as CNKeyDescriptor, CNContactPhoneNumbersKey as CNKeyDescriptor, CNContactFormatter.descriptorForRequiredKeys(for: .fullName)])
do {
try store.enumerateContacts(with: request) { contact, stop in
if let name = formatter.string(from: contact) {
print(name)
} else if let firstPhone = contact.phoneNumbers.first?.value {
print(firstPhone.stringValue)
} else {
print("no name; no number")
}
}
} catch let fetchError {
print(fetchError)
}
For Swift 2, see previous revision of this answer.
You can fetch contact name from your phone book using this code:-
- (void) fetchContacts
{
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusDenied) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:#"This app previously was refused permissions to contacts; Please go to settings and grant permission to this app so it can use contacts" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:TRUE completion:nil];
return;
}
CNContactStore *store = [[CNContactStore alloc] init]; [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
// make sure the user granted us access
if (!granted) {
dispatch_async(dispatch_get_main_queue(), ^{
// user didn't grant access;
// so, again, tell user here why app needs permissions in order to do it's job;
// this is dispatched to the main queue because this request could be running on background thread
});
return;
}
// build array of contacts
NSMutableArray *contacts = [NSMutableArray array];
NSError *fetchError;
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:#[CNContactIdentifierKey, [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]]];
BOOL success = [store enumerateContactsWithFetchRequest:request error:&fetchError usingBlock:^(CNContact *contact, BOOL *stop) {
[contacts addObject:contact];
}];
if (!success) {
NSLog(#"error = %#", fetchError);
}
// you can now do something with the list of contacts, for example, to show the names
CNContactFormatter *formatter = [[CNContactFormatter alloc] init];
for (CNContact *contact in contacts) {
if (!_contacts) {
_contacts = [[NSMutableArray alloc] init];
}
NSString *string = [formatter stringFromContact:contact];
NSLog(#"contact = %#", string);
[_contacts addObject:string];
}
[_contactatableview reloadData];
}];
}
#import <Contacts/Contacts.h>
#import <ContactsUI/ContactsUI.h>
- (IBAction)displayContact:(id)sender {
id keysToFetch = #[[CNContactViewController descriptorForRequiredKeys]];
CNContact *contact = [self.store unifiedContactWithIdentifier:self.contactIdentifier keysToFetch:keysToFetch error:nil];
self.controller = [[CNContactViewController alloc] init];
[self.controller.view setFrameSize:NSMakeSize(500, 500)];
[self presentViewController:self.controller asPopoverRelativeToRect:self.view.bounds ofView: self.view preferredEdge: NSMaxXEdge behavior:NSPopoverBehaviorTransient];
self.controller.contact = contact;
}
To fetch contacts from devices
if (isIOS9) { //checking iOS version of Device
CNContactStore *store = [[CNContactStore alloc] init];
//keys with fetching properties
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactEmailAddressesKey,CNContactPostalAddressesKey, CNLabelWork, CNLabelDateAnniversary];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
DLOG(#"cnContacts %lu",(unsigned long)cnContacts.count);
if (error) {
//error
} else {
for (CNContact *contact in cnContacts) {
//iterate over cnContacts to get details
}
}
} else {
//for below iOS 9
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef arrPersons = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex count = ABAddressBookGetPersonCount(addressBook);
NSLog(#"cnContacts %lu",(unsigned long)count);
for (int i = 0; i < count; i++) {
ABRecordRef record = CFArrayGetValueAtIndex(arrPersons,i);
//use kABPersonBirthdayProperty to get b’day
NSString *birthDay = (__bridge NSString *)(ABRecordCopyValue(record, kABPersonBirthdayProperty));
NSLog(#“B’day %#”, birthDay);
}
}
I am trying to fetch multiple phone numbers from the contacts of device.
It's working fine if the contact have only one number, but it's f***** when they have multiple numbers (which means that I'm getting "\U00a" in between the numbers).
I tried every solution I could think of, but it's still not working.
ABMultiValueRef phonesRef = ABRecordCopyValue(person, kABPersonPhoneProperty);
for (int i = 0; i < ABMultiValueGetCount(phonesRef); i++) {
CFStringRef currentPhoneLabel = ABMultiValueCopyLabelAtIndex(phonesRef, i);
CFStringRef currentPhoneValue = ABMultiValueCopyValueAtIndex(phonesRef, i);
if (CFStringCompare(currentPhoneLabel, kABPersonPhoneMobileLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *) currentPhoneValue forKey:#"mobileNumber"];
}
else if (CFStringCompare(currentPhoneLabel, kABHomeLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *) currentPhoneValue forKey:#"homeNumber"];
}
CFRelease(currentPhoneLabel);
CFRelease(currentPhoneValue);
}
You can use Contacts Framework. Hope this will provide you direct solution for contacts.
#import <Contacts/Contacts.h>
-(void)getContact{
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
// make sure the user granted us access
if (!granted) {
dispatch_async(dispatch_get_main_queue(), ^{
// user didn't grant access;
// so, again, tell user here why app needs permissions in order to do it's job;
// this is dispatched to the main queue because this request could be running on background thread
});
return;
}
// build array of contacts
NSMutableArray *contacts = [NSMutableArray array];
NSError *fetchError;
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:#[CNContactEmailAddressesKey, CNContactPhoneNumbersKey, CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPostalAddressesKey]];
BOOL success = [store enumerateContactsWithFetchRequest:request error:&fetchError usingBlock:^(CNContact *contact, BOOL *stop) {
[contacts addObject:contact];
}];
if (!success) {
CTLog(#"error = %#", fetchError);
}
__weak typeof(self)weakSelf = self;
[weakSelf parseContactWithContact:contacts];
}];
- (void)parseContactWithContact :(NSMutableArray* )contacts{
for (CNContact *contact in contacts)
{
NSString * firstName = contact.givenName;
NSString * lastName = contact.familyName;
NSString *StrContactName = [NSString stringWithFormat:#"%# %#",firstName,lastName];
NSArray * arryPhone = [[contact.phoneNumbers valueForKey:#"value"] valueForKey:#"digits"];
for (int i=0; i<[arryPhone count]; i++)
{
NSMutableDictionary *mDictValue = [[NSMutableDictionary alloc]init];
[mDictValue setValue:firstName forKey:#"firstName"];
[mDictValue setValue:lastName forKey:#"lastName"];
[mDictValue setValue:StrContactName forKey:#"contactName"];
[mDictValue setValue:[arryPhone objectAtIndex:i] forKey:#"Phone"];
[arrayOfContacts addObject:mDictValue];
}
}
I am trying to create a profile inside my application to show only his twitter profile. So far I do have the time line working but I don't have the number counter for the tweets,followers and following. I'm pretty sure I can use something what my code looks like but just don't know how, any help? Thanks
Code:
STTwitterAPI *twitter = [STTwitterAPI twitterAPIAppOnlyWithConsumerKey:#"ConsumerKey"
consumerSecret:#"consumerSecret"];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *bearerToken) {
[twitter getUserTimelineWithScreenName:#"MikesiOSHelp"
successBlock:^(NSArray *statuses) {
self.twitterFeed = [NSMutableArray arrayWithArray:statuses];
[self->tableView reloadData];
} errorBlock:^(NSError *error) {
NSLog(#"%#", error.debugDescription);
}];
} errorBlock:^(NSError *error) {
NSLog(#"%#", error.debugDescription);
}];
You should check out their demo application.
Your request for finding the followers of a user is explicitly covered in the CLI demo:
typedef void (^AllFollowersBlock_t)(NSArray *allFollowers);
void getFollowers(STTwitterAPI *twitter,
NSString *screenName,
NSMutableArray *followers,
NSString *cursor,
AllFollowersBlock_t allFollowersBlock) {
if(followers == nil) followers = [NSMutableArray array];
NSMutableDictionary *md = [NSMutableDictionary dictionary];
md[#"screen_name"] = screenName;
if(cursor) md[#"cursor"] = cursor;
md[#"skip_status"] = #"1";
md[#"include_user_entities"] = #"0";
[twitter getResource:#"followers/list.json"
baseURLString:kBaseURLStringAPI_1_1
parameters:md
downloadProgressBlock:^(id json) {
//
} successBlock:^(NSDictionary *rateLimits, id response) {
NSArray *users = nil;
NSString *previousCursor = nil;
NSString *nextCursor = nil;
if([response isKindOfClass:[NSDictionary class]]) {
users = [response valueForKey:#"users"];
previousCursor = [response valueForKey:#"previous_cursor_str"];
nextCursor = [response valueForKey:#"next_cursor_str"];
}
NSLog(#"-- users: %#", #([users count]));
NSLog(#"-- previousCursor: %#", previousCursor);
NSLog(#"-- nextCursor: %#", nextCursor);
[followers addObjectsFromArray:users];
if([nextCursor integerValue] == 0) {
allFollowersBlock(followers);
return;
}
/**/
NSString *remainingString = [rateLimits objectForKey:#"x-rate-limit-remaining"];
NSString *resetString = [rateLimits objectForKey:#"x-rate-limit-reset"];
NSInteger remainingInteger = [remainingString integerValue];
NSInteger resetInteger = [resetString integerValue];
NSTimeInterval timeInterval = 0;
if(remainingInteger == 0) {
NSDate *resetDate = [[NSDate alloc] initWithTimeIntervalSince1970:resetInteger];
timeInterval = [resetDate timeIntervalSinceDate:[NSDate date]] + 5;
}
NSLog(#"-- wait for %# seconds", #(timeInterval));
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
getFollowers(twitter, screenName, followers, nextCursor, allFollowersBlock);
});
} errorBlock:^(NSError *error) {
NSLog(#"-- error: %#", error);
}];
}