ios Objective C delegate methods - ios

This is my first day of Objective C so I apologise for the lack of knowledge.
I need to import an existing SKD into an App and I done it successfully. Now I need to create the delegate methods and I don't understand how can I do it.
This is the structure of the header file included from the SDK (SDKManager.h):
#protocol SDKManagerDelegate;
#interface SDKManager : NSObject
#property (nonatomic, weak) id<SDKDelegate> delegate;
+(void)initialize:(NSString*)appId withKEY:(NSString*)key;
+(void)setHandler:(id)delegate;
#end
#protocol SDKManagerDelegate <NSObject>
#required
-(void)appDidReceiveTokens:(NSDictionary*)items withResponse:(NSDictionary*)response;
#end
So, from my FirstViewController.m I was able to import the header and call two methods:
#import "FirstViewController.h"
#import "SDKManager.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[SDKManager setHandler:[UIApplication sharedApplication].delegate];
[SDKManager initialize:#"AppId"withKEY:#"1234"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
but I have noticed that I am not able to call the other methods (i.e. appDidReceiveTokens).
Actually the instructions require to create those methods but I have no idea where.
Any help is really appreciated.
Thank you

You do not call delegate methods directly in the files in which you are implementing the delegate methods. Review Apples documentation on the concept of Delegation.
To implement this properly you would adopt the delegate in your class, then implement the delegate methods that are #required and/or #optional.

You've correctly created the delegate protocol and a property to store the SDKManager's delegate.
Your setHandler: and initialize:withKEY: methods are class methods, whereas the delegate property belongs to each instance of SDKManager. Without seeing your implementation file (.m) for SDKManager, it's hard to know why you've set it up this way. You may be attempting to follow a singleton pattern - if so, read up on it, e.g. here.

The reason for that is you have class methods which sets the calls setHandler method and the delegate is property, so where do you assign the delegate and when and how do you call the delegate. I hope you understand what a class and instance is. So, you cannot call the delegate until you create instance of your object.
You have two different class methods which is used to set some attributes to the class, would it make sense to have them as property.
More generic and better way to do this would be like this,
#protocol SDKManagerDelegate <NSObject>
#required
-(void)appDidReceiveTokens:(NSDictionary*)items
withResponse:(NSDictionary*)response;
#end
#protocol SDKManagerDelegate;
#interface SDKManager : NSObject
- (instancetype)initWithAppId:(NSString *)appId
key:(NSString *)key
delegate:(id<SDKManagerDelegate>)delegate;
#end
#interface SDKManager ()
#property (nonatomic, copy, readonly) NSString *appId;
#property (nonatomic, copy, readonly) NSString *key;
#property (nonatomic, weak, readonly) id<SDKManagerDelegate> delegate;
#end
#implementation SDKManager
- (instancetype)initWithAppId:(NSString *)appId
key:(NSString *)key
delegate:(id<SDKManagerDelegate>)delegate
{
if (self = [super init]) {
_appId = [appId copy];
_key = [key copy];
_delegate = delegate;
}
return self;
}
- (void)doSomeNetworkRequestHere
{
[self fetchTokenFromServer:^(NSDictionary *tokens, NSDictionary *response){
[self.delegate appDidReceiveTokens:tokens
withResponse:response];
}];
}
- (void)fetchTokenFromServer:(void(^)(NSDictionary *tokens, NSDictionary *response))completion
{
}
#end

Related

Can blocks be used as replacement for delegates?

I want to write a custom delegate method to receive an event in one of my view controllers from another view controller. Should I use blocks here instead of delegates. Which is the preferred one ?
#protocol MyClassDelegate
-(void)doSomethingInDelegate;
#end
#interface MyClass : NSObject
#property id<MyClassDelegate> delegate;
-(void)doSomething
#end
#implementation MyClass
-(void)doSomething
{
[self.delegate doSomethingInDelegate];
}
#end
#interface MyOtherClass<MyClassDelegate> : NSObject
...
#end
#implementation MyOtherClass
-(void)doSomethingInDelegate
{
NSLog(#"Doing something in delegate");
}
#end
In most cases, if you have a very small number of delegate methods (ideally just 1), then blocks may be a good replacement. If you have several delegate methods, then blocks can become awkward.
UITableView has dozens of delegate methods between UITableViewDelegate and UITableViewDataSource. Configuring that with blocks would be unwieldy and make code reuse very difficult. If a particular way of "being the delegate" may be highly reusable (like in UITableViewController), then delegates are a much more powerful pattern.
On the other hand, if your delegate would wind up having just a single "thisActionFinished:` method, then a delegate is likely overkill and it's better to just pass a block. There are many cases that this is true, and we used to have to need to create a lot of one-method delegate protocols, and it was a bit of a pain. Blocks made that common pattern a lot easier.
But it's not a universal replacement for delegation, and blocks have many other purposes that have nothing to do with callbacks. So it's important to learn both techniques.
Looking to your specific example, there are several mistakes. Let's do it in both delegate and block forms.
Delegate
// Since the protocol needs to know about the class, you need to warn the
// compiler that this class exists.
#class MyClass;
// Declare the delegate protocol. Delegate method names should follow this
// pattern with "did", "should", or "will" in their names. Delegate methods
// should always pass the delegating object as the first parameter. A given
// delegate may be delegating for several instances.
#protocol MyClassDelegate
-(void)myClass:(MyClass *)class didSomething:(id)something;
#end
// Declare the class that has a delegate. Notice that `delegate` should be `weak`
// here. In your example, it's `strong`, and that will almost always lead to a
// retain loop. With rare exceptions, delegates are not retained.
#interface MyClass : NSObject
#property (nonatomic, readwrite, weak) id<MyClassDelegate> delegate;
-(void)doSomething;
#end
// Do the thing
#implementation MyClass
-(void)doSomething {
[self.delegate myClass:self didSomething:#"SOMETHING"];
}
#end
// The delegate object almost always has a strong pointer to the thing it delegates
// for. That's why you want the `delegate` property to be weak.
// Note that your syntax was wrong. "MyOtherClass <MyClassDelegate>". That's
// the new generic syntax, not the protocol syntax. Protocols go at the end.
#interface MyOtherClass : NSObject <MyClassDelegate>
#property (nonatomic, readwrite, strong) MyClass *c;
#end
// And the obvious impl
#implementation MyOtherClass
- (instancetype)init {
self = [super init];
if (self) {
self.c = [MyClass new];
self.c.delegate = self;
}
return self;
}
-(void)myClass:(MyClass *)class didSomething:(id)something {
NSLog(#"Doing something in delegate");
}
#end
Block
Let's do the same thing if this were a block-based API.
// If your callback takes no arguments and returns nothing, then you can
// use dispatch_block_t here. But often you need parameters or return
// something, and for that you should usually make a typealias. Welcome to the
// spiral world of block syntax.
typedef void(^MyClassCallback)(id something);
// Instead of a delegate, we have a callback. We might have several. We might
// have a block that returns the row height. But if you're doing a lot of
// that, just use a delegate. Note that blocks should always be `copy`.
#interface MyClass : NSObject
#property (nonatomic, readwrite, copy) MyClassCallback callback;
-(void)doSomething;
#end
// And here's how you use the block. It's just like a function.
#implementation MyClass
-(void)doSomething {
if (self.callback != nil) {
self.callback(#"SOMETHING");
}
}
#end
// And the delegate.
#interface MyOtherClass : NSObject
#property (nonatomic, readwrite, strong) MyClass *c;
#end
#implementation MyOtherClass
- (instancetype)init {
self = [super init];
if (self) {
self.c = [MyClass new];
// And here's the syntax for creating the block.
self.c.callback = ^(id something) {
NSLog(#"Doing something in delegate");
};
}
return self;
}
#end
Notice we don't need an extra method in the delegate just to hold one line of code, and we don't need to define a protocol. That's the big reason for the move to blocks for lightweight delegation. It keeps related code close together. But when the code gets complicated, "together" gets crazy, and blocks are not longer a good solution. Back to delegates, which do that very well.

Need to develop Custom Delegate for API Calling

I want to develop Custom Connection Class by which I can make API calls using it. I do not want to use any third party apis like afhttprequest or asihttp.
I want to develop my self this type of delegate. I have searched much things but I do not have much idea in CustomDelegates.
I wrote one example of custom delegate.
From ViewController.m we call method with two number for addition of another class (Addition class)
Addition class will add these two number and call delegate method so we can get answer of that two number in ViewController using custom delegate.
Addition.h
#import <Foundation/Foundation.h>
// write protocal for this class
// you can give any name of that protocol
#protocol AdditionDelgate <NSObject>
// delegate method of this delegate
-(void)answerOfTwoNumberAddition:(int)ans;
#end
#interface Addition : NSObject
{
}
// set property of that protocol, so using that we can call that protocol methods (i.e. ansOfYourAns)
#property (nonatomic, weak) id <AdditionDelgate> delegate;
-(void) addThisNumber:(int) firstNumber withSecondNumber:(int)secondNumber;
#end
Addition.m
#import "Addition.h"
#implementation Addition
-(void)addThisNumber:(int)firstNumber withSecondNumber:(int)secondNumber
{
int ans = firstNumber + secondNumber;
// call delegate method of "AdditionDelgate" protocol
// we already set delegate of viewController to this protocol
// so it will call viewController class "answerOfTwoNumberAddition" method
[self.delegate answerOfTwoNumberAddition:ans];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
// import addition class
#import "Addition.h"
// set AdditionDelgate to class
#interface ViewController : UIViewController <AdditionDelgate>
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// creat object of class
Addition * additionObj = [[Addition alloc] init];
// set delegate as self to that so that methods delegate methods will call
additionObj.delegate = self;
// call method
[additionObj addThisNumber:2 withSecondNumber:3];
}
#pragma mark ----- Delegate method of Addition view ----
// this is delegate method of Addition class, it will call from "addThisNumber" method line of code
// ([self.delegate answerOfTwoNumberAddition:ans];)
-(void)answerOfTwoNumberAddition:(int)ans
{
NSLog(#"addition of two number is %d",ans);
}
#end
I hope it will help you

Singleton and Delegation

I read enough information about singleton and delegation. So, I think I understand what is singleton. About delegation I still confuse. I understand conception of delegation, but I need to create my protocol for understanding delegation.
Ok, I create singleton for work with my entities from CoreData. Maybe I wrong and it is not singleton, tell me please about it. My singleton is FetchData.
Fetchdata.h
#import <Foundation/Foundation.h>
#interface FetchData : NSObject <UIApplicationDelegate>
+(FetchData*) fetchData;
-(NSArray*)fetchLogin:(NSString*)name;
-(BOOL)newGroup:(NSString*)group forLogin:(NSString*)login;
-(NSMutableArray*)contactsForGroup:(NSString*)group;
-(BOOL)newContact:(NSString*)name surname:(NSString*)surname withDatas:(NSArray*)array;
//other methods
#end
Fetchdata.m
#import "FetchData.h"
#import "Contact.h"
#import "Login.h"
#import "Group.h"
#import "AppDelegate.h"
#interface FetchData ()
#property (nonatomic, strong) NSEntityDescription *loginEntity;
#property (nonatomic, strong) NSEntityDescription* groupEntity;
#property (nonatomic, strong) NSManagedObjectContext* context;
#property (nonatomic, strong) NSEntityDescription* contactEntity;
#property (nonatomic, strong) AppDelegate* appDelegate;
//other properties
#end
#implementation FetchData
#synthesize //my properties
+(FetchData*) fetchData
{
static FetchData* fetchData = nil;
if (!fetchData)
fetchData = [[super allocWithZone:nil]init];
return fetchData;
}
+(id)allocWithZone:(NSZone *)zone
{
return [self fetchData];
}
//implementation my methods
#end
So, it is very easy to work with CoreData now for me. I need only import FetchData and simply use methods for create/delete/change/add/sort...
SomeClass.m
#import "FetchData.h"
#define fetching [FetchData fetchData]
But I think that I can use for my aim delegation. Or maybe it is the best decesion as compared with singleton. So I want to remake singleton for delegation. And I need help with this question. What I must do?
If I understand correctly I need create protocol with all my methods from FetchData.h, FetchData.m I can leave without changes. And in SomeClass I need import FetchData and add my protocol. Like:
#import <Foundation/Foundation.h>
#protocol FetchingDelegate
//all methods from FetchData.h
#end
#interface FetchData : NSObject
#property (nonatomic, strong) id <FetchingDelegate> delegate;
#end
FetchData.m
#interface FetchData()
//all properties without changing
#end
#implementation FetchData
#synthesize //all properties and delegate
//implementation of methods
#end
SomeClass
#import "FetchData.h"
#interface SomeClass : NSObject <FetchingDelegate>
#end
#implementation SomeClass
-(void)viewDidLoad
{
FetchData* fetching = [FetchData new]
fetching.delegate = self
}
//and now I can use any methods from protocol like [fetching anyMethod]
//such I used with singleton
The idea of a singleton is that your entire app can access this one class. Multiple view controllers may need data coming from your database. In your case, I would change your fetchData method (and maybe change its name as it doesn't really follow convention now):
+(FetchData*) fetchData
{
static FetchData *fetchData;
dispatch_once_t token;
dispatch_once(&token, ^{
if (!fetchData)
fetchData = [super init];
}
return fetchData;
}
Delegates are meant for one-on-one communication, meaning that one object has a delegate and sends any messages to that one particular delegate.
That means that a singleton and delegation don't go well together. The singleton is made to send messages to multiple receivers, while the delegation pattern is meant for one-on-one communication. So you have two options: you could either not use a singleton and use the delegation pattern, or you could use a singleton, and use NSNotificationCenter to notify observers of changes.

Custom delegate issue

I'm working with a custom delegate and protocol functionality.
I implemented my class like follows:
#protocol MyDelegate <NSObject>
#required
- (void)update;
#end
#interface MyHandlerClass : NSObject
{
id <MyDelegate>delegate;
}
#property (nonatomic, weak) id <MyDelegate>delegate;
#end
My implementation class looks like:
#implementation MyHandlerClass
#synthesize delegate = _delegate;
- (void)updateRequired: (id)sender
{
if(delegate)
{
[delegate update];
}
}
#end
And from another class I'm setting it like:
[sharedManager setDelegate:self];
But when the updateRequired is triggered it is showing as nil.
Then I added a setter method like:
- (void)setDelegate:(id<MyDelegate>)aDelegate
{
delegate = aDelegate;
}
Everything works fine !!!
Then I changed the updateRequired method (without custom setter) like:
- (void)updateRequired: (id)sender
{
if(_delegate)
{
[_delegate update];
}
}
It is also working fine !!!
I couldn't find why it is not worked for the first case and why it is worked for the other two cases ?
Please help me to find the issue, Thanks in advance
When you use
if(delegate)
You are pointing to the instance variable "delegate".
However, when you use
[sharedManager setDelegate:self]
This is setting the instance variable "_delegate" to "self".
Try this:
if (self.delegate) {
[self.delegate update];
}
You have inadvertently declared one ivar called delegate
id <MyDelegate>delegate;
and another ivar called _delegate
#synthesize delegate = _delegate;
Some suggestions...
don't declare the iVar separately from your #property declaration
don't #synthesize, since XCode 4.4 you don't have to. The compiler will autosynthesize and autocreate an iVar with leading underscore
always refer to you ivar via it's property, inside and outside of your class. Only exceptions are in init, dealloc and inside custom setters and getters.
So this is how your code should look
#protocol MyDelegate <NSObject>
#required
- (void)update;
#end
#interface MyHandlerClass : NSObject
#property (nonatomic, weak) id <MyDelegate>delegate;
#end
#implementation MyHandlerClass
- (void)updateRequired: (id)sender
{
if(self.delegate)
{
[self.delegate update];
}
}
#end
To access your delegate property in the updateRequired method, you can do it by either using the private variable _delegate or by using self.delegate. Because when you synthesize using delegate = _delegate, setters and getters are automatically created.
This line tells the compiler to create a setter and getter for delegate, and that they should use the ivar called _delegate. Without the = _delegate part, the compiler would assume that the property and ivar have the same name.

Delegate declaration dilemma

I'm confused - I cannot understand what is the delegate is for?
The Application Delegate which is created by default is understandable, but in some cases I've seen something like this:
#interface MyClass : UIViewController <UIScrollViewDelegate> {
UIScrollView *scrollView;
UIPageControl *pageControl;
NSMutableArray *viewControllers;
BOOL pageControlUsed;
}
//...
#end
What is the <UIScrollViewDelegate> for?
How does it work and why is it used?
<UIScrollViewDelegate> is saying that the class conforms to the UIScrollViewDelegate protocol.
What this really means is that the class must implement all of the required methods defined within the UIScrollViewDelegate protocol. Simple as that.
You can conform your class to multiple protocols if you like:
#implementation MyClass : UIViewController <SomeProtocol, SomeOtherProtocol>
The purpose of conforming a class to a protocol is to a) declare the type as a conformant of the protocol, so you can now categorize this type under id <SomeProtocol>, which is better for delegate objects that objects of this class may belong to, and b) It tells the compiler to not warn you that the implemented methods are not declared in the header file, because your class conforms to the protocol.
Here's an example:
Printable.h
#protocol Printable
- (void) print:(Printer *) printer;
#end
Document.h
#import "Printable.h"
#interface Document : NSObject <Printable> {
//ivars omitted for brevity, there are sure to be many of these :)
}
#end
Document.m
#implementation Document
//probably tons of code here..
#pragma mark Printable methods
- (void) print: (Printer *) printer {
//do awesome print job stuff here...
}
#end
You could then have multiple objects that conform to the Printable protocol, which could then be used as an instance variable in, say, a PrintJob object:
#interface PrintJob : NSObject {
id <Printable> target;
Printer *printer;
}
#property (nonatomic, retain) id <Printable> target;
- (id) initWithPrinter:(Printer *) print;
- (void) start;
#end
#implementation PrintJob
#synthesize target;
- (id) initWithPrinter:(Printer *) print andTarget:(id<Printable>) targ {
if((self = [super init])) {
printer = print;
self.target = targ;
}
return self;
}
- (void) start {
[target print:printer]; //invoke print on the target, which we know conforms to Printable
}
- (void) dealloc {
[target release];
[super dealloc];
}
#end
I think you need to understand the Delegate Pattern. It is a core pattern used by iphone/ipad applications and if you don't understand it you will not get far. The link to wikipedia I just used outlines the pattern and gives examples of it's use including Objective C. That would be a good place to get started. Also look at take a look at the Overview tutorial from Apple which is specific to the iPhone and also discusses the Delegate pattern.

Resources