Question

Title itself is enough for my question I guess. However I will explain further here, consider I have a two view controller A and B. A is base and it is pushing B, In one situation I want the A to be intimated from B when one button is clicked in View (B). Objective C is allowing to call directly A view if I have that instance. I think it is not a good practice to do that. How this case should be handled..

thanks for your suggestions.

Was it helpful?

Solution

IF by 'A intimated from B' you mean you want to invoke the A that was initially responsible for pushing B, you just go back to A using the 'back' button, or in code:

[self.navigationController popViewController animated:YES];

B doesn't need a pointer to A, the Navigation Controller has that, and B has a pointer to the Nav Controller because the Nav Controller sets B's navigationController property when it creates B.

If you need to set a property in A based on some action in B, you should use a delegate to do that.

In B, you make a property called delegate.

In A, when you create B, set it's delegate to A:

ViewControllerB* vcB = [[ViewControllerB alloc] init];
vcB.delegate = self;
[self.navigationController pushViewController:vcB];

Then in B you can call back to A via the delegate before the pop:

[self.delegate sendMessageWithValue:someValue];
[self.navigationController popViewController animated:YES];

If you want to be extra-cautious, you can enclose the message-passing with:

if ([self.delegate respondsToSelector:@selector(sendMessageWithValue:)]) { ... }

To make this work without B knowing anything about A, other than that it is the delegate, B should declare a delegate protocol in the header (above @interface)

@protocol BDelegateProtocol
- (void) sendMessageWithValue:(int)someValue;
@end

When you declare the delegate property in B's @interface, specify the protocol it is expected to follow:

@property (nonatomic, weak) id <BDelegateProtocol> delegate;

And in A's @interface header, advertise that you follow that protocol:

#import BViewController;

@interface AViewController:UIViewController <BDelegateProtocol>

This is the loose coupling you are after. B doesn't have to import A's header. It needs to know nothing about A other than that it conforms to B's protocol specification.

B does hold a pointer to A but it is a weak pointer. This is very important. If the delegate property was strong, B would increase the retain count of it's delegate by 1. If the delegate also holds a strong pointer to B, then neither of them can ever get deallocated. B will always have a retain count of at least 1 while A exists, and likewise A will always have a retain count of 1 while B exists: neither can be destroyed.

In this particular case that may not happen - A doesn't need to retain B as it's Nav Controller does - but it is a situation that can arise frequently as a delegate is very often the object that creates and owns the delegator. See "Use Weak References to Avoid Retain Cycles" in Apple's Practical Memory Management

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top