I am developing an application which has a Twitter login. I have integrated MGTwitterEngine for that, and everything is working fine.
My problem is that when the user logs in, I need some details -- whatever info is returned by MGTwitterEngine for that logged-in user.
When I had a look in the library docs, I found the below delegate method which might give some user information, but when I log in ,this method never gets called.
- (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString *)connectionIdentifier {
NSLog(#"User Info Received: %#", userInfo);
}
Can somebody please suggest to me how to get the user's information from MGTwitterEngine or how I should use this method?
_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate:self];
_engine.consumerKey = #"PzkZj9g57ah2bcB58mD4Q";
_engine.consumerSecret = #"OvogWpara8xybjMUDGcLklOeZSF12xnYHLE37rel2g";
UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine: _engine delegate: self];
if (controller)
[self presentModalViewController: controller animated: YES];
else {
tweets = [[NSMutableArray alloc] init];
[self updateStream:nil];
}
I found the answer of my question:-
- (void) OAuthTwitterController: (SA_OAuthTwitterController *) controller authenticatedWithUsername: (NSString *) username {
NSLog(#"Authenticated with user %#", username);
[_engine getUserInformationFor:username];//this line to be added to get userInfo method called
}
Related
I try to use the new iOS 9.0 CNContactPickerViewController to select a contact in objective-C. I set the delegate and implement the CNContactPickerDelegate methods.
#import ContactsUI;
#import Contacts;
//-----------------------------------------------------------------------
- (void) presentContacts
{
CNContactPickerViewController *contactPicker = [[CNContactPickerViewController alloc] init];
contactPicker.delegate = self;
contactPicker.predicateForEnablingContact = [NSPredicate predicateWithFormat:#"familyName LIKE[cd] 'smith'"];
contactPicker.predicateForSelectionOfContact = [NSPredicate predicateWithFormat:#"TRUEPREDICATE"];
[_myViewController presentViewController:contactPicker animated:YES completion:nil];
}
//-----------------------------------------------------------------------
- (void) contactPickerDidCancel: (CNContactPickerViewController *) picker
{
NSLog(#"didCancel");
}
//-----------------------------------------------------------------------
- (void) contactPicker: (CNContactPickerViewController *) picker
didSelectContact: (CNContact *) contact
{
NSLog(#"didSelectContact"):
}
//-----------------------------------------------------------------------
- (void) contactPicker: (CNContactPickerViewController *) picker
didSelectContactProperty: (CNContactProperty *) contactProperty
{
NSLog(#"didSelectProperty");
}
//-----------------------------------------------------------------------
The contacts picker is presented with 'smith' selectable but I get the following message:
[CNUI ERROR] Selection predicates are set but the delegate does not implement contactPicker:didSelectContact: and contactPicker:didSelectContactProperty:. Those predicates will be ignored.
And I never get any log from the delegate methods. It behaves exactly as the line
contactPicker.delegate = self;
is ignored. Even I click on the "cancel" button in the picker, I don't get my "didCancel" message but I get another message:
plugin com.apple.MobileAddressBook.ContactsViewService invalidated
I found in https://forums.developer.apple.com/thread/12275 somebody with the similar problem in swift and he solved it telling us: "So I found that the ContactsPicker I was calling was in the wrong module" but I do not understand how we can get the wrong module and how to call the "right" module.
I have the same problem on the simulator and on a real device (iPad).
Thanks to Joel in my related question With CNContactPickerViewController in iOS 9.0, how to enable/disable single or multiple selection?, I found that I just forgot to store the CNContactPickerViewController in a property that exists the time the user make the selection.
So my code becomes:
- (void) presentContacts
{
_contactPicker = [[CNContactPickerViewController alloc] init];
contactPicker.delegate = self;
...
}
I am facing app extension close issues , please tell me if anyone know what wrong am doing.I am using action extension after preform some action inside extension i need to return response back.
Sample Code
// With Success Case
- (void) completeActionWithItems: (NSString *) response {
NSExtensionItem *extensionItem = [[NSExtensionItem alloc] init];
extensionItem.attachments = #[[[NSItemProvider alloc] response typeIdentifier: (NSString *)kUTTypePlainText]];
[self.extensionContext completeRequestReturningItems: #[extensionItem] completionHandler: nil];
}
// With Error Case
- (void) completeActionWithError: (NSError *) error {
[self.extensionContext cancelRequestWithError: error];
}
With Success Case working fine but some time is not closing,
With Error Case not working above code.
Please let me know what went wrong.Thanks
When you create an action extension, this is the default method which will close the Action Extension View Controller:
- (IBAction)done {
// Return any edited content to the host app.
// This template doesn't do anything, so we just echo the passed in items.
[self.extensionContext completeRequestReturningItems:self.extensionContext.inputItems completionHandler:nil];
}
Since this method is already provided, you should just try calling it from your success method.
// With Success Case
- (void) completeActionWithItems: (NSString *) response {
NSExtensionItem *extensionItem = [[NSExtensionItem alloc] init];
extensionItem.attachments = #[[[NSItemProvider alloc] response typeIdentifier: (NSString *)kUTTypePlainText]];
[self.extensionContext completeRequestReturningItems: #[extensionItem] completionHandler: nil];
// Call to "done" method
[self done];
}
I've never touched threads before, and by the looks of it I might have to delve into them a little, but I was wondering if there was a simpler solution to the problem below.
I'm basically displaying a list of a user's Facebook friends in a UITableView. I have a FacebookWrapper class that contains all my Facebook methods, and a FacebookViewController that has a variety of buttons/options. Finally, there is a FriendsViewController that displays the list of Friends. The user can choose to display a list of male friends, or female friends by pressing the relevant button in the FacebookViewController.
If they hit male friends for example, I use FBL to create a query string which I add to a dictionary and use to return a list of male friends (all in the wrapper).
[facebook requestWithMethodName:#"fql.query" andParams:dictionary andHttpMethod:#"GET" andDelegate:self];
The delegate methods in the wrapper class handle the FBRequest that is returned. I have the following methods to determine what's happening when:
- (void)requestLoading:(FBRequest *)request {
NSLog(#"Loading...");
}
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
NSLog(#"Response received");
}
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error {
NSLog(#"Request failed");
}
- (void)request:(FBRequest *)request didLoadRawResponse:(NSData *)data {
NSLog(#"Request did load raw response");
}
However, when I hit the 'male friends' button for example, I want to wait until the response has been generated before pushing the FriendsViewController and displaying the list. As it stands now, the FriendsVC is pushed before the request has returned the list, and so I get a blank list. I have to wait for "Request did load raw response" before refreshing the table and displaying the results. Currently the method to call and display the friends list in the FacebookViewController looks like this:
- (IBAction)friendsButtonPressed:(id)sender {
int selectionTag = [sender tag];
//Get access to the instance of the wrapper in the app delegate (since it needs to remain refereced after app exits to log in and returns
MiniBfAppDelegate *appDelegate = (MiniBfAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate.facebookWrapper loadListDataFor:selectionTag];
//Initialise the friends view controller
FriendsViewController *friendsViewController = [[FriendsViewController alloc] init];
//NEED TO WAIT UNTIL LISTDATA IS RETURNED?
//Give the friends view controller the list data
friendsViewController.listData = appDelegate.facebookWrapper.friendsList;
//Push the friends view controller
friendsViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:friendsViewController animated:YES];
[friendsViewController release];
}
So ideally, I'd like to display a loading symbol while I wait for the wrapper to return the list, and once it does, push the FriendsViewController so it is populated immediately. So do I need to use threads or is there a simpler way?
Perhaps this is answering my own question, and it might be that I'm failing to grasp a fundamental concept here, but aside from creating an instance of the FriendsVC in my App Delegate, is there a way I can send the current instance a message from the Wrapper class? So I could just tell it to refresh in the wrapper's request: didLoadRawResponse: method, i.e. when the list is generated.
I'm not sure I understand your question, but you may want to look into the NSNotificationCenter. You can use it to send messages to your controllers, here's an example of triggering a notification:
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotificationName"
object:self
userInfo:[NSDictionary dictionaryWithObject:XXXX forKey:#"someObject"]];
As you can see, you can even send parameters to it. And in the target controller you just register an observer to respond to those messages:
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(yourMethodHere:)
name: #"myNotificationName"
object: nil];
Regards!
That's simple. Put your VC loading code into didReceiveResponce method. And show UIAlertView in didFailWithError.
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
NSLog(#"Response received");
//Give the friends view controller the list data
friendsViewController.listData = appDelegate.facebookWrapper.friendsList;
//Push the friends view controller
friendsViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:friendsViewController animated:YES];
[friendsViewController release];
}
when I try to share on twitter I do the following steps
if (!twitterEngine)
{
twitterEngine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate: self];
twitterEngine.consumerKey = kOAuthConsumerKey;
twitterEngine.consumerSecret = kOAuthConsumerSecret;
UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine: twitterEngine delegate: self];
if (controller)
[currentController presentModalViewController: controller animated: YES];
else
[self postTwitterStatus];
}
else {
[self postTwitterStatus];
}
after I got the twitter login view and after I put my pass and user and click add app
I get crash on asembly code, which I don't have an error message, but I saw something weiered also that in the delegates
- (void) OAuthTwitterController: (SA_OAuthTwitterController *) controller authenticatedWithUsername: (NSString *) username {
NSLog(#"Authenicated for %#", username);
[self postTwitterStatus];
}
I got that authintication succeeded but I get that the username == null
how can I solve this issue
Thanks
I did NOT get THIS error, but a similar one using Twitter+OAuth by Ben Gottlieb. If you are using this thing, it is required to use https and not http to connect to twitter.
go to: SA_OAuthTwitterEngine.m and change to:
- (SA_OAuthTwitterEngine *) initOAuthWithDelegate: (NSObject *) delegate {
if (self = (id) [super initWithDelegate: delegate]) {
//CHANGED FROM 'HTTP' TO 'HTTPS':
self.requestTokenURL = [NSURL URLWithString: #"https://twitter.com/oauth/request_token"];
self.accessTokenURL = [NSURL URLWithString: #"https://twitter.com/oauth/access_token"];
self.authorizeURL = [NSURL URLWithString: #"https://twitter.com/oauth/authorize"];
}
return self;
}
give it a try, i'm not sure it's the same as your problem..
Every thing looks fine to me. check with this example and see weather you are getting username in this.
So my Twitter/Facebook implementation in my app has been a learning experience, but I'm almost there and I have one last, probably simple question. Using the MGTwitter engine, I'm calling a method from my viewcontroller in
- (void) setAccessToken: (OAServiceTicket *) ticket withData: (NSData *) data {
The method is firing off, (confirmed by NSLog calls). However, it's not doing what it's supposed to do, which is fade in my logout button for Twitter. I'm still getting my hands around the way Objective-C handles methods and all, I feel like I'm just not pointing my variables to the right place. Any direction is much appreciated, here is the code below:
SA_OAuthTwitterEngine.m -
//
// access token callback
// when twitter sends us an access token this callback will fire
// we store it in our ivar as well as writing it to the keychain
//
- (void) setAccessToken: (OAServiceTicket *) ticket withData: (NSData *) data {
if (!ticket.didSucceed || !data) return;
NSString *dataString = [[[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding] autorelease];
if (!dataString) return;
if (self.pin.length && [dataString rangeOfString: #"oauth_verifier"].location == NSNotFound) dataString = [dataString stringByAppendingFormat: #"&oauth_verifier=%#", self.pin];
NSString *username = [self extractUsernameFromHTTPBody:dataString];
if (username.length > 0) {
[self setUsername: username password: nil];
if ([_delegate respondsToSelector: #selector(storeCachedTwitterOAuthData:forUsername:)]) [(id) _delegate storeCachedTwitterOAuthData: dataString forUsername: username];
}
[_accessToken release];
_accessToken = [[OAToken alloc] initWithHTTPResponseBody:dataString];
//Call twit login from my view controller
MyView *fvController = [[MyView alloc] init];
[MyView twitLogin];
[MyView helper];
NSLog(#"LETS TWEET DIRECTLY AFTER SUCCESSFUL LOG IN!");
}
This is what my helper method is doing in my .m file:
-(void)helper{
NSLog(#"HELPER FUNCTION");
[self fadeIn:twitterLogout withDuration:2 andWait:2.0];
}
This is the method it's calling
//FADE IN FUNCTION ------------------------------//////////////////////
-(void)fadeIn:(UIView*)viewToFadeIn withDuration:(NSTimeInterval)duration
andWait:(NSTimeInterval)wait
{
[UIView beginAnimations: #"Fade In" context:nil];
[UIView setAnimationDelay:wait];
[UIView setAnimationDuration:duration];
viewToFadeIn.alpha = 1;
[UIView commitAnimations];
}
In Objective-C, methods are declared in one of two ways:
- (returnType)methodName;
or
+ (returnType) methodName;
The first type is an "instance" method and the second type is a "class" method.
These lines should be changed:
[MyView twitLogin];
[MyView helper];
Try this instead:
[fvController twitLogin];
[fvController helper];
Additionally, you may be calling your helper method before the delegate returns a value. You should see if the MGTwitterEngine contains a delegate. (I'd be surprised if it didn't.) You should use the available callbacks to call methods only when the login is finished. Simply calling the methods in order won't do what you want.
*Are both the log statements printed?
*Is setAccessToken:withData: being called from the main thread? Try calling the fadeIn method from the main thread i.e. something like this
- (void) helper{
NSLog(#"HELPER FUNCTION");
[self performSelectorOnMainThread:#selector(callFadeIn)];
}
-(void)callFadeIn{
[self fadeIn:twitterLogout withDuration:2 andWait:2.0];
}
See if that helps. It is possible that setAccessToken: (and thus helper and fadeIn) is being called from another thread. All UI operations should happen from the main thread.