ABAddressBookGetPersonCount returns -1 in iOS - objective-c

I am running into a situation where ABAddressBookGetPersonCount is returning -1. The tester assures me there contacts do exist in the address book. All the handsets are running iOS 6.0.1.
Here's the code:
NSMutableDictionary *myAddressBook = [[NSMutableDictionary alloc] init];
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
int numEntries = ABAddressBookGetPersonCount(addressBook);
if (numEntries == 0)
{
NSString *title = NSLocalizedString(#"error", nil);
NSString *description = NSLocalizedString(#"error_empty_contacts", nil);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:description
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
return;
}
NSLog(#"emails: found %d", numEntries);
I am not able to reproduce this on any of my handsets, but the tester has tried on 3 handsets. It works properly on an iPhone 5, but not on a 4 or 3;
I can't find any docs that indicate what a value of -1 means. I'm assuming it's an error of some kind, but what?

Under iOS 6, this code isn't valid. You have to verify that your app has permission to access the address book. Most likely, the -1 is an indication that the app has no permission (or an unknown permission state) on those devices.
From the docs for ABAddressBookRequestAccessCompletionHandler:
CFErrorRef myError = NULL;
ABAddressBookRef myAddressBook = ABAddressBookCreateWithOptions(NULL, &myError);
APLViewController * __weak weakSelf = self; // avoid capturing self in the block
ABAddressBookRequestAccessWithCompletion(myAddressBook,
^(bool granted, CFErrorRef error) {
if (granted) {
NSArray *theSmiths = CFBridgingRelease(
ABAddressBookCopyPeopleWithName(myAddressBook,
CFSTR("Smith")
)
);
weakSelf.numberOfSmiths = [theSmiths count];
} else {
// Handle the error
}
});
CFRelease(myAddressBook);
If you need to support iOS 5.x or 4.x you need to properly check for the existence of the new methods.

Related

Application having trouble when opening with network

I'm building an app that is using the Instagram API to display photos but I'm running into some trouble. The app is crashing when there is no network connection and I have found the code that is causing the problem.
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
self.accessToken = [userDefaults objectForKey:#"accessToken"];
if (self.accessToken == nil) {
[SimpleAuth authorize:#"instagram" options:#{#"scope": #[#"likes"]} completion:^(NSDictionary *responseObject, NSError *error) {
self.accessToken = responseObject[#"credentials"][#"token"];
[userDefaults setObject:self.accessToken forKey:#"accessToken"];
[userDefaults synchronize];
[self refresh];
}];
} else {
[self refresh];
}
I have found that the [self refresh]; is causing the problem in the else block and I tried to replace it with a alert view like this
UIAlertView *networkError = [[UIAlertView alloc] initWithTitle:#"Network Error" message:#"Please connect your device to a network and restart application" delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
[networkError show];
However, with this problem I find that if I open the app with a network connection I still get the alert. Any help would be great because I'm still new to Objective C!
Thank you for the help!
I know this code from Treehouse :).
The thing is that the if (self.accessToken == nil) { /.../ } block will only get execute when the app is not authorized using your Instagram credentials.
Once you logged in successfully, it will always execute the code in the else { /.../ } block. If it has connection to Internet, it will do its work, download, display images etc. If you insert the code to display alert, it will always do that because you actually mean that by that code.
If you want to check if there is some connection, you need to do that before all that code, display an error and return instantly if connection is not available. However, the author tried to keep things simple, assuming there is always Internet connection.
Hope it makes you understand it.
This is the some code you can use for checking if there is connection:
// show some activity indicator
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
// Do something...
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
NSURL *url = [NSURL URLWithString:#"http://www.apple.com/"];
NSString *s = [NSString stringWithContentsOfURL:url
encoding:NSUTF8StringEncoding
error:nil];
dispatch_async(dispatch_get_main_queue(), ^{
// hide the activity indicator
self.connected = (s != nil);
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
if (self.isConnected)
{
NSLog(#"self.connected == YES");
}
else
{
NSLog(#"self.connected == NO");
NSString *alertMessage = #"In order to load images, you need an active Internet connection. Please try again later!";
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Sorry!"
message:alertMessage
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
});
});
You obviously need to add a property to you class. You can insert this code:
#interface LDPhotosViewController ()
#property (nonatomic, copy, getter = isConnected) NSString *connected;
#end
at the top of LDPhotosViewController.m file, before the #implementation line.

Objective C: Detect number of Facebook invites

I'm trying to detect how many invites the user has sent while logged into their Facebook account. For example, I'm giving the user an option to purchase an item by inviting 3 friends to use the iOS application. If they invite 3, they are rewarded with the item. I'm really stuck on this one. Any help would be great and much appreciated!
I actually found code snippet for this after much research. I can't remember if it was on here or not, but here it is.
- (IBAction)inviteFacebookFriendsButton:(id)sender
{
// FBSample logic
// if the session is open, then load the data for our view controller
if (!FBSession.activeSession.isOpen)
{
// if the session is closed, then we open it here, and establish a handler for state changes
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:NO
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
} else if (session.isOpen) {
}
}];
}
MouseInTheHouseAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
if (appDelegate.session.isOpen)
{
NSMutableDictionary *postVariablesDictionary = [[NSMutableDictionary alloc] init];
[postVariablesDictionary setObject:#"Come play Mouse in the House with me!" forKey:#"message"];
[postVariablesDictionary setObject:#"Invite Friends" forKey:#"title"];
[FBWebDialogs presentDialogModallyWithSession:[FBSession activeSession] dialog:#"apprequests" parameters:postVariablesDictionary handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error)
{
if (error)
{
// Case A: Error launching the dialog or sending request.
NSLog(#"Error sending request.");
}
else
{
if (result == FBWebDialogResultDialogNotCompleted)
{
// Case B: User clicked the "x" icon
NSLog(#"User canceled request.");
}
else
{
NSRegularExpression * regex = [NSRegularExpression regularExpressionWithPattern:#"to%5B\\d+%5D=(\\d+)"
options:NSRegularExpressionCaseInsensitive
error:NULL];
NSArray * matches = [regex matchesInString:resultURL.absoluteString
options:0
range:(NSRange){0, resultURL.absoluteString.length}];
NSMutableArray * ids = [NSMutableArray arrayWithCapacity:matches.count];
for (NSTextCheckingResult * match in matches)
{
[ids addObject:[resultURL.absoluteString substringWithRange:[match rangeAtIndex:1]]];
}
NSLog(#"Number of friends invited: %lu", (unsigned long)ids.count);
}
}
}];
}
}

How to directly return to rootViewController? UIStoryboard (or update tableview)

There are some questions I have found but the answers don't work with my code, therefore I ask a question of my own.
My objective is reloading a table view from a detailviewcontroller. I tap a cell, go to the detail and when I return to the table I want it updated. The thing is it doesn't update. So I decided it would be better to go back to the rootviewcontroller when certain thing happens on the detailviewcontroller but it still didn't work.
I am open to suggestions and advice feel free to comment!!
I download a video and when the video is downloaded I update the tableView.
Here is the code I am using:
I use MKNetworkKit btw.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *cachesDirectory = [paths objectAtIndex:0];
NSString *downloadPath = [cachesDirectory stringByAppendingPathComponent:videoName];
self.downloadOperation = [ApplicationDelegate.mainDownloader downloadVideoFrom:finalAddress
toFile:downloadPath];
[self.downloadOperation onDownloadProgressChanged:^(double progress) {
//DLog(#"%.2f", progress*100.0);
//self.downloadProgressBar.progress = progress;
}];
[self.downloadOperation onCompletion:^(MKNetworkOperation* completedRequest) {
//THIS DOES NOT WORK, dismissModalViewControllerAnimated.
[[ApplicationDelegate.window rootViewController] dismissModalViewControllerAnimated:YES];
DLog(#"COMPLETED REQUEST: %#", completedRequest);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Download completed"
message:#"The file is in your photo and video Library"
delegate:nil
cancelButtonTitle:NSLocalizedString(#"Thank you WebSurg!!", #"")
otherButtonTitles:nil];
[alert show];
// THIS IS WHAT I PREVIOUSLY TRIED.
// NSDictionary *tableSecData = ApplicationDelegate.videoLibraryController.tableSectionData;
// NSMutableArray *tempValuesDownloaded = [tableSecData objectForKey:#"Downloaded videos"];
// NSMutableArray *tempValuesUndownloaded = [tableSecData objectForKey:#"Undownloaded videos"];
// for (NSArray *videoArray in tempValuesUndownloaded) {
// if ([[videoArray objectAtIndex:0] isEqualToString:self.videoDetailTitle.text]) {
// [tempValuesUndownloaded removeObject:videoArray];
// [tempValuesDownloaded addObject:videoArray];
// }
// }
// [ApplicationDelegate.videoLibraryController.tableSectionData removeAllObjects];
// ApplicationDelegate.videoLibraryController.tableSectionData = [NSMutableDictionary dictionaryWithObjectsAndKeys:tempValuesDownloaded, #"Downloaded videos", tempValuesUndownloaded, #"Undownloaded videos", nil];
// [ApplicationDelegate.videoLibraryController.mainTableView reloadData];
}
onError:^(NSError* error) {
DLog(#"%#", error);
[[[UIAlertView alloc] initWithTitle:#"Download failed" message:#"The download failed because of a connection error please try again" delegate:nil cancelButtonTitle:NSLocalizedString(#"Dismiss", #"") otherButtonTitles:nil] show];
}];
} else {
UIAlertView *failureAlert=[[UIAlertView alloc] initWithTitle:#"Download status" message:#"Download failed, not enough free space." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil, nil];
[failureAlert show];
}

Upload photo using new iOS Facebook SDK API (3.0)

How can I upload a photo to facebook from an iOS app using their new API/SDK? I've already tried and I'm not getting anywhere, just keep running in circles. Here is the code I currently have:
-(void)dataForFaceboo{
self.postParams =
[[NSMutableDictionary alloc] initWithObjectsAndKeys:
self.uploadPhoto.image, #"picture", nil];
}
-(void)uploadToFacebook{
[self dataForFacebook];
NSLog(#"Going to facebook: %#", self.postParams);
// Hide keyboard if showing when button clicked
if ([self.photoCaption isFirstResponder]) {
[self.photoCaption resignFirstResponder];
}
// Add user message parameter if user filled it in
if (![self.photoCaption.text
isEqualToString:kPlaceholderPostMessage] &&
![self.photoCaption.text isEqualToString:#""])
{
[self.postParams setObject:self.photoCaption.text forKey:#"message"];
}
[FBRequestConnection startWithGraphPath:#"me/feed"
parameters:self.postParams
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error)
{
NSString *alertText;
if (error) {
alertText = [NSString stringWithFormat:
#"error: domain = %#, code = %d",
error.domain, error.code];
} else {
alertText = [NSString stringWithFormat:
#"Posted action, id: %#",
[result objectForKey:#"id"]];
}
// Show the result in an alert
[[[UIAlertView alloc] initWithTitle:#"Result"
message:alertText
delegate:self
cancelButtonTitle:#"OK!"
otherButtonTitles:nil] show];
}];
}
Your code is fine, some slight changes to be done:
add the image to the dictionary in NSData format, like
[params setObject:UIImagePNGRepresentation(_image) forKey:#"picture"];
and change the graph path to "me/photos" instead of "me/feed"
Make these changes, it worked for me.
Remember you need to use "publish_actions" permissions.
"me/photos" is meant for the photo actually be in the "Photo's" list on your Facebook profile. "me/feed" is just a post on the timeline.

how to implement google chat in iphone app

i have searched a lot on the web but can not find the actual sample source code that can help me to get started for google chat implementation , the sample code provided with the xmpp framework also does not tell clearly about it, as it have a sample project of Mac desktop application.
I have been able to show all my friends who are online/ofline/away with the help of sample project(iphoneXmpp) which is provided in the xmppframework, but it also doest tell anything about how to initiate a chat.
Please provide me any sample source code so that i can initialize the google chat in my app.
i am really stuck.
thanks in advance
okey i didnt give up and had some solution after looking into the desktop application of xmpp framework and tried to include it in my iphone app..
here is the code to send message to our chat friend on gmail..
-(void)sendMessage
{
messageStr = [NSString stringWithFormat:#"%#",[msgField text] ];
//messageStr = [NSString stringWithString:#"hello ji....."];
BOOL isEmpty = [ self validateIsEmpty:msgField.text];
if([messageStr length] > 0 && isEmpty == NO )
{
NSXMLElementK *body = [NSXMLElementK elementWithName:#"body"];
[body setStringValue:messageStr];
NSXMLElementK *message = [NSXMLElementK elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:[[user jid] full]];
[message addChild:body];
[[self xmppStream ] sendElement:message];
}
and in didReceiveMessage , i have following code...
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
NSLog(#"---------- xmppStream:didReceiveMessage: ----------");
NSLog(#"--jid---%#", [[user jid] full]);
NSLog(#"--from----%#", [message from]);
//if(![[[user jid] full] isEqual:[message from]]) return;// important when chatting with 2 or more .. and receiving 2 or more messages...
if([message isChatMessageWithBody])
{
NSString *msg = [[message elementForName:#"body"] stringValue];
NSLog(#"mmmmmmmmmmssssssgggg-%#",msg);
[str appendString:[NSString stringWithFormat:#"%#:%#\n\n", [message from], msg]];
[chatBox setText:str];
}
}
i'm able to send/recieve the chat using these two methods but problem is that some times the person's id which i selected from the table view of available online contacts(to whom we can chat with) does'nt receive the message but any other person receives the message..
Cheers!!
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
NSString *msg = [[message elementForName:#"body"] stringValue];
NSString *from = [[message attributeForName:#"from"] stringValue];
if (msg.length==0) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Receiving Message"
message:[NSString stringWithFormat:#"From %#",from]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}
if (msg.length!=0) {
NSMutableDictionary *m = [[NSMutableDictionary alloc] init];
[m setObject:msg forKey:#"msg"];
[m setObject:from forKey:#"sender"];
NSLog(#"message received : %#", m);
[_messageDelegate newMessageReceived:m];
}
}
This works great for you, and it will also give you the alert who is sending the message and who wants to chat with you, However I'm just stuck from where should I implement the Logout for the user through which I logged in to iOS SDK.
This tutorial should do the trick : http://mobile.tutsplus.com/tutorials/iphone/building-a-jabber-client-for-ios-server-setup/