Facebook iOS SDK - Custom Delegate - ios

I am working on a new project with facebook integration. The app has to make different requests to facebook. The SDK provides one delegate that handles every request the same. Now i need to have a custom delegate to handle certain request different. Could somebody give me a hint on how to accomplish this?

The Facebook class exposes numerous method which return FBRequest* objects, and each of those methods have an argument for a delegate, which can be any object you like, so long as it conforms to the FBRequestDelegate protocol.
Therefore either, just have a custom class which implements the protocol for each type of request. Or, have one class, which implements the protocol, and inside those methods, you'll need to inspect the FBRequest that you receive to determine what to do. So, for example, if you're calling:
Facebook *fb = [[Facebook alloc] initWithAppId:kYourFacebookAppId];
[params setObject:[NSNumber numberWithBool:YES] forKey:#"PostComment"];
[fb requestWithParams:params andDelegate:delegate];
[fb release];
then in the delegate, you could do something like:
- (void)request:(FBRequest *)request didLoad:(id)result {
// Make a decision based on the request
if ([[request.params objectForKey:#"PostComment"] boolValue]) {
// Here we should post a comment.
}
}
However, I personally wouldn't do that, as it'll be much harder to maintain. Much better would be to write separate classes for each Facebook related task. These classes could inherit from a base FBDelegate class which does common things like error handling.

Related

When to use respondsToSelector vs objc_getClass

if respondsToSelector("UIAlertController"){
//do something
}
if objc_getClass("UIAlertController") != nil{
//do something
}
These both have the same results overall. Is there a case when one is better than the other one? Or should only one of them be used and the other forgotten?
respondsToSelector : This is basically used for to check if object reference, can call perticular method or not. For example, object has inherited from some base class or implemented by some protocols, then it is better to check whether object is able to respond to that method or not, then only call it.
Otherwise it will throw runtime error, method not found type.
if([obj respondsToSelector:#selector(anyMethod)]) {
[obj fizzyWizzle];
}
else {
// do something
}
objc_getClass : The Class object for the named class, or nil if the class is not registered with the Objective-C runtime. It means, are you able to access this class or not, if that class does not exist then it will return 'nil'. So,
if objc_getClass("UIAlertController") != nil{
// it means, these class is available in SDK, hence its iOS version is 8.x
// here you can alloc - init and use UIAlertController functionality
}
else {
// class could not be found
// iOS version is < 8.0
// here that class is not available hence use UIAlertView which is supported by iOS 7 and earlier.
}
Hope this helps.
For checking the class existence you must use objc_getClass. (For Class compatibility with iOS versions)
For checking whether a class implemented a method or a method is available or not you need to use respondsToSelector (For method availability with versions)
These two methods do not have the same result overall.
Responds to Selector
The first case respondsToSelector is a part of the NSObject protocol and will simply indicate if an object is capable of responding to a message with the given signature, at the time of calling. It can be used for a number of cases:
Polymorphism. Ie, informal protocols, or particularly in conjunction with conformsToProtocol for checking if an instance (of any class) responds to the part of a protocol under the #optional directive.
For deciding whether to forward a message to another target.
For instrumenting an object with additional functionality at runtime, for example putting transaction/rollback capability on a persistent model object.
In publish/subscribe type scenarios.
Get Class
The second method is a low-level member of the Objective-C runtime. It is used to simply check the kind of class an object is presenting itself as. (It will check the isa pointer). There are methods on the NSObject protocol that can do the same thing, and it would be generally recommended to use these, unless you have a specific reason to fall back to the lower level APIs. These methods are [an instance class] and [anInstance isKindOfClass].
Replace instanceof with Polymorphism
While there are a great deal of valid uses for querying an object's class, in a typical application it is often a design flaw. There's a refactoring pattern called "replace instanceof with polymorphism". By that we mean, instead of asking an object what kind of class it is, then doing something, instead specific based on that, instead create a protocol and have each of the possible classes implement the method of that protocol in their specific way. Example:
if ([foo isKindOfClass:[Holiday class]]) {
//evaluate if approved
} else if ([foo isKindOfClass:[SickLeave class]]) {
//evaluate if approved
}
Instead do . .
id<Leave> leave;
[leave approveOrDecline]

Custom Methods now defined by the cocoa library

I was asked this question during a technical discussion and can't seem to find answer anywhere.
The problem:
If I wrote methods by extending a core class (Lets say NSArray) which didn't exists in iOS 5 but were introduced in iOS 6.
What would happen to my application in the app store when the user upgrades to iOS 6? Would it crash? Would it be refer to foundation class? Would the runtime point to my function and everything will continue to work same?
Eg.
iOS 5.0
PGMyArray : NSArray
- (NSString) info; // convert and concatenate each object of the array into a string.
Now in iOS 6.0, Apple introduced the method publicly as part NSArray
NSArray
- (NSString) info; // Does exactly same as my method
What would happen when user upgrades to iOS 6.0 and my application calls
PGMyArray *myArray = [[NSArray alloc] init];
[myArray info];
My intelligent guess is, it would still be calling to PGMyArray-> info (after looking up from virtual table). However, I wasn't told the right answer and its bothering me for weeks now.
Any explanation / help is appreciated.
As you know any subclass can override an existing method. Even here you will end up with calling your method. i.e. Overriding it.
That's why you shouldn't call it "info". You should use a three letter prefix (two letter prefixes are reserved by Apple), like abcInfo.
You are extending the NSArray class, it means that if you implement a info method, YOUR method will be called, because you are ovveriding the default info method.
It is the same when you implement some methods like the viewDidLoad method. You have to implement it like this:
- (void)viewDidLoad {
[super viewDidLoad];
// Your initialization
}
You have to call the super method because you are overriding it, meaning that the super class viewDidLoad method is not called anymore.

Delegate Methods in TwitPic API

Can anyone explain about delegate methods in TwitPic API and tell me the architecture of those delegate methods, I mean which method calls first,second like that.
In my code I have added TwitterRequest external classes and implemented. When I build my app I am getting message "No response from Delegate". Anyone help me regarding this.
Thanks in advance.
From the code sample in the tutorial you followed, it looks like this message is logged when delegate you passed in doesn't implement the callback selector you also passed in when you made the call to the TwitterRequest class.
For example, suppose we were making a request to update status:
TwitterRequest *request = [[TwitterRequest alloc] init];
[request statuses_update:#"My status" delegate:self requestSelector:#selector(didUpdateStatus)];
This code would log the message you're seeing unless self implemented the callback didUpdateStatus. (Where self might be a view controller or similar.)
I would need to have implemented a method in my view controller something like this:
- (void)didUpdateStatus {
NSLog(#"Updated status successfully");
}
Check that you've assigned and implemented such a method. Note that this looks to be optional - if you don't want to know if your request succeeded you can either ignore this message, or implement an empty callback such as I have in this example.

iOS - in a view controller, where is the most logical place to put user-session management code?

I am an iOS newbie and I am trying to understand some of the "good practice" ways of doing things in an iOS app.
I have a ViewController which I made to be the controller that is called when the app starts. In it I saw a function called viewDidLoad and I tried to modify it to check if the user has had a user_id and then call a function that would eventually make an asynchronous request to manage that user in a remote db. Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
EmailUtil *email = [EmailUtil alloc];
email = [email init];
// This is just a test call to the function that would make a remote server request
[email setEmail: #"test" andBody: #"hello"];
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
if([standardUserDefaults objectForKey:#"user_id"] == nil)
{
NSLog(#"First time");
[standardUserDefaults setBool:YES forKey:#"user_id"];
}
else
{
NSString *subject = #"subject";
NSString *body = #"bod";
NSLog(#"Not first time");
}
}
So there are a few things I am unsure with here. Can the fact that I am calling a function to make a remote call from viewDidLoad cause problems in that function? Currently its not sending the remote request.
Also, should I deallocate memory for the objects I create right at the end of this function?
Or should I just move this code to another spot in the class where it would make more sense to have that code there?
I call the email object like this:
[email setEmail: #"test" andBody: #"hello"];
and here is the code for the EmailUtil class:
//
// EmailUtil.m
//
#import "EmailUtil.h"
#implementation EmailUtil
-(void) setEmail: (NSString *) subject andBody: (NSString *) body
{
NSString *final_url = [NSString stringWithFormat:#"http://www.my_url.com?subject=%#&body=%#",subject, body];
NSURL *url = [NSURL URLWithString:final_url];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url ];
// TODO: ok I dont really understand what this is
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
NSLog(#"On return");
NSLog(#"This is data: %#" , data);
NSLog(#"This is response: %#" , response);
NSLog(#"This is error: %#" , error);
NSLog(#"OK");
}];
}
#end
Thank you!
You said:
So there are a few things I am unsure with here. Can the fact that I
am calling a function to make a remote call from viewDidLoad cause
problems in that function? Currently its not sending the remote
request.
Feel free to make whatever calls you want in viewDidLoad. Just make sure to not doing anything that will block the UI (e.g. some long, complicated method). Any long-running, non-UI related task would be done asynchronously in a separate queue, but that's for another day, in the distant future.
Whether you do this here, or in application:didFinishLaunchingWithOptions:, is a function of what your UI is going to do. We'd need a better sense of your app's flow to answer that question. And we need to understand what how the EmailUtil presents itself (often these sorts of classes use a modal presentation, which makes sense to do from another view controller and not from application:didFinishLaunchingWithOptions:).
But, bottom line, I personally have application:didFinishLaunchingWithOptions: always take me to what will be the app's "main" or "home" page, and if I have something that I want to present on first time usage, but not have that be the main page, then I'll invoke this from my main view controller's viewDidLoad. Other guys will customize application:didFinishLaunchingWithOptions: with the "first time used" logic. It's a matter of personal preference.
Also, should I deallocate memory for the objects I create right at the end of this function?
The first rule of memory management is that you always should deallocate anything you own (generally anything you create) and only the things you own. But, if you're using ARC (which I highly encourage you to do), this is taken care of for you (objects are deallocated as they fall out of scope).
Or should I just move this code to another spot in the class where it
would make more sense to have that code there?
Personally, I'm not crazy about having an app send an email just because the main view controller appeared, as I assume this was just an example and not a real app. But if you were contemplating putting this in a different place, the "send email" function is more logically hooked to the user tapping on a "send email" button, rather than running off and doing it itself.
On other points:
This code is curious, though, because you're creating EmailUtil, a local var, setting setting some its properties, but then not doing anything with it, and then letting it fall out of scope. I presume you'd want some method to make this EmailUtil do its stuff, e.g. [email sendMessage], or whatever the appropriate method is.
You're also creating two local vars, subject and body, and not using them and letting them fall out of scope. I presume you wanted to update your email object's properties accordingly but have not gotten to that.
Is there a reason you're writing your own EmailUtil class rather than using MessageUI.framework? Hopefully EmailUtil is just a nice wrapper for the MessageUI.framework, or doing something completely different, but not replicating functionality that Apple already provides.
You said that the app will "make an asynchronous request to manage that user in a remote db". Wow. I do that sort of stuff all the time, now, but I wouldn't suggest asynchronous coordination with a server as a good first-time project. Hopefully when you said "eventually" you meant "a couple of months from now" and not "in the next week or two." Looks like you're still getting your sea legs on basic view controller and memory management stuff. You might want to see if you can constrain the functionality of your initial version of the app to something a little less ambitious. If you don't have some basic skills yet and try to do something complicated, you can end up with a real mess on your hands that you'll find yourself completely rewriting later. So, no offense, but see if you can come up with something a little simpler for your first real project. Or do a couple of test apps first. Just a thought.
Lvsti is quite right that the typical object creation construct is [[EmailUtil alloc] init]. What you have is equivalent, but non-standard.
I know it's a work in progress, but it looks like your setEmail:andBody: is setting properties and sending the message. I'd suggest (a) having #property entries for subject and body (which will automatically generate setSubject and setBody methods, as well as let you do stuff like email.subject = #"This is the subject of the email";); (b) if you want, have an init convenience method, e.g., initWithSubject:body: which will do the init your object and set these two properties; and (c) have a separate method that actually sends the message. It's not a good practice to have something that looks like a setter, is sort of a setter, but also does more material stuff, all in a single method. Methods that begin with the word "set" are generally standard setters and iOS conventions will lead other programmers to misread your code (as I just did). By following some standard iOS conventions, it will be easier if you ever get iOS programmers involved in reviewing and revising code.
You should move this code to the application:didFinishLaunchingWithOptions: method of your appdelegate.
From iOS-Dev-Center
You should use this method to initialize your application and prepare
it for running. It is called after your application has been launched
and its main nib file has been loaded. At the time this method is
called, your application is in the inactive state.
And if you are not using arc, only thing you should release is EmailUtil, no reason to deallocate something by hand

setDelegate explanation

Hi i am new to iphone developement, can any one explain me why setDelegate is used, where we should use it.
[request setDelegate:sender];
thanks in advance.
Delegates are simply a design pattern; there is no special syntax or language support.
A delegate is just an object that another object sends messages to when certain things happen, so that the delegate can handle application-specific details the original object wasn't designed for. It's a way of customizing behavior without subclassing.
Some classes, for example NSSpeechSynthesizer, include delegate support. Unlike a protocol, failure to provide a delegate method does not provoke an error: the class always provides a method, but calls yours instead, if it exists.
For example, NSSpeechSynthesizer has a method
-(void) speechSynthesizer:(NSSpeechSynthesizer*)sender
didFinishSpeaking:(BOOL)complete;
If you provide an identically declared method, in class Fred, it will be called instead of the synthesiser's own method, provided you have earlier done, in that class,
speech = [[NSSpeechSynthesizer alloc] initWithVoice:#"com.apple.speech.synthesis.voice.Albert"];
[speech setDelegate:self];
This will work, though the compiler will warn if you did not announce yourself as a delegate by
#interface Fred : NSObject <NSSpeechSynthesizerDelegate>, in that
{
. . .
(This example is adapted from Cocoa Programming... by Hillegass).

Resources