0

Actually I have three view controllers named in my app. I am navigating from A to B and then B to C. I am calling delegate method from C which is implemented in A. here is my code for

A.h

#import "A.h"
#import "C.h"

In A.m I have

@interface A()<delegateName>
-(void)delegateMethod
{
  NSLog(@"delegate");
}
-(void)moveToB
{
  C *instanceOfC=[C alloc] init];
  instanceOfC.delegate=self;                //line 1
}

In B.h

#"import C.h"

In B.m

-(void)moveToC
{
  A *instanceOfA=[[A alloc] init];
  C *instanceOfC=[[C alloc] init];      
  instanceOfC.delegate= instanceOfA;            //line 2
}

In C.h

@protocal delegateName <NSObject>
-(void)delegateMethod;
@end
@interface C
@property(nonatomic,weak) id<delegateName>  delegate;
@end

In C.m

@synthesize delegate;
-(void)inSomeMethod
{
 [delegate delegateMethod];
}

if I put <delegateName> in A.h instead of A.m then it says undeclared delegate.

jaymala
  • 39
  • 8
  • -(void)moveToB { C *instanceOfC=[C alloc] init]; instanceOfC.delegate=self; } I think you need to make instance of class B here – Vishal Sonawane Jan 05 '17 at 13:40
  • to move to next viewController by pushViewController i created instance of b also but when i debug [delegate delegateMethod]; @ this line delegate is nil so i assigned that instance in between page also – jaymala Jan 05 '17 at 13:46
  • Try this. In A -(void)moveToB { B *instanceOfB=[B alloc] init]; instanceOfB.delegate=self; } . And in B -(void)moveToC { C *instanceOfC=[[C alloc] init]; instanceOfC.delegate= self.delegate; } – Arjuna Jan 05 '17 at 13:47
  • but B isn't having delegate – jaymala Jan 05 '17 at 13:48
  • try to make delegate as strong: @property(nonatomic,strong) id delegate; – Vishal Sonawane Jan 05 '17 at 13:51
  • try calling `[delegate delegateMethod];` on main thread. – Mohammad Zaid Pathan Jan 05 '17 at 13:53
  • You need to have instanceOfA or delegate property in B or else you can access uinavigationcontroller.viewControllers to get the instance of A. But this is not recommended and won't work if order of view controllers change or if you change from push to present. – Arjuna Jan 05 '17 at 14:01
  • when i debug code @ line 1 and 2 it the delegate is not nil,but its when i actually access it – jaymala Jan 05 '17 at 14:04
  • You need to have instanceOfA or delegate property in B or else you can access uinavigationcontroller.viewControllers to get the instance of A. But this is not recommended and won't work if order of view controllers change or if you change from push to present. – Arjuna Jan 05 '17 at 14:12
  • All of the view controllers being allocated in the code are immediately discarded by ARC. Please read about segue's and `prepareForSegue` where you can get the view controller about to be presented. See the segue section here: http://stackoverflow.com/a/9736559/294949 – danh Jan 05 '17 at 18:40

2 Answers2

0

In moveToC you are assigning instanceOfA to the delegate property of instanceOfC. At the end of moveToC both instances are deallocated, as you do not keep a strong reference to instanceOfC, e.g. assign it to a property.

You can fix this by adding a @property (strong, nonatomic) C *cInstance; to your B.m class and assign it when instantiating instanceOfC:

-(void)moveToC {
    A *instanceOfA=[[A alloc] init];
    self.cInstance = [[C alloc] init];
    self.cInstance.delegate= instanceOfA;
}

That said, the design looks wrong to me. I would rename delegateProtocol to somthing else, like DirtyJobHandler and introduce a custom init method in class C:

- (instanceType)initWithDirtyJobHandler:id<DirtyJobHandler> dirtyJobHandler {
    self = [super init];
    if (self) {
        self.dirtyJobHandler = dirtyJobHandler //previous knonw as self.delegate
    }
}

which is able to inject this dependency:

[[C alloc] initWithDirtyJobHandler:instanceOfA];
shallowThought
  • 19,212
  • 9
  • 65
  • 112
  • Add the mentioned property `cInstance ` in `B.m`, which you can then assign `self.cInstance = ...` to hold a strong reference to `instanceOfC`. I recommend the second approach though. – shallowThought Jan 05 '17 at 14:15
0

I think problem is in the line

A *instanceOfA=[[A alloc] init]; 

in the function

-(void)moveToC
{
 A *instanceOfA=[[A alloc] init];
 C *instanceOfC=[[C alloc] init];
 instanceOfC.delegate= instanceOfA;
 }

Replace the first line with

  A *instanceofA = self.navigationController.viewControllers[indexofA]

In B viewcontroller you are again allocate new memory for A viewcontroller and set the delegate to it. Instead of that you need to set the delegate which is previously in the memory and that can be find in two ways

(i) Get it from navigation controller (ii) Create a object of A viewcontroller in B viewcontroller.

Gour
  • 50
  • 8
  • This is right, that the allocation of new view controllers is a mistake. Not really right in it's prescription, though. – danh Jan 05 '17 at 18:41
  • i replaced Gour's given line and made delegate property strong and its woking. Thanks vishal, arjuna, danh, shallowThought and every body... Its working – jaymala Jan 06 '17 at 05:56