0

I'm new to Objective-C (from java background), so apologies if this question is too trivial.

Suppose i have two classes, where one holds a reference to another, as such:

@interface PostOffice
@property (nonatomic, strong) MailGuy *mailGuy;
@end

@implementation PostOffice
-(void)getMailmanToSendMail {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        self.mailGuy = [[MailGuy alloc] init];
        [self.mailGuy sendMail];
    }
}
@end

and for MailGuy:

@interface MailGuy () <MFMailComposeViewControllerDelegate>

@end

@implementation MailGuy
-(void)sendMail {
    NSLog(@"send mail");
    [self.viewController presentViewController:mailViewController animated:YES completion:nil];
}
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
    // upon dismissal, how do i get the PostOffice instance to release this MailGuy instance?
}
@end

How do i get the PostOffice to release the MailGuy?? i only know when it should be free based on the callback. but i don't want to store a reference to the PostOffice? or do i ? and does it matter that i'm instantiating the MailGuy from a background thread?

any help would be appreciated. thanks!

David T.
  • 22,301
  • 23
  • 71
  • 123
  • 3
    Side note - you have a problem. You are calling `sendMail` from a background thread yet `sendMail` updates the UI. UI updates must be done on the main thread. – rmaddy Sep 05 '14 at 19:43

1 Answers1

3

The usual way to do so is to use protocol and delegates.

So in your MailGuy.h you should add a protocol

@protocol MailGuyDelegate
  - (void) didPostHisLetter;
@end

And still in the .h file but this time INSIDE the @interface you would add a delegate reference

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

This adds a delegate property to your MailGuy and it says that the delegate must implement the given protocol (which has the method).

Then in your mail guy implementation code here's what you would do

- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
    if (self.delegate) {
        [self.delegate didPostHisLetter];
    }
}

This tells his delegate "Hey I finished my job". So all you have to do now is implement the delegate in your PostOffice class

In your .m file of PostOffice, add a private property

@interface PostOffice() <MailGuyDelegate>
@end

Then when you invoke your mail guy, you associate it's delegate to self. Notice that I remove the async dispatch as it is not used and may cause problems as mentioned in comments

-(void)getMailmanToSendMail {
        self.mailGuy = [[MailGuy alloc] init];
        self.mailGuy.delegate = self;
        [self.mailGuy sendMail];
}

And all is left to do is implement the protocol's method (still in postoffice implementation)

- (void) didPostHisLetter {
    self.mailGuy = nil;
}
  • 1
    Only thing I would add is to follow standard protocol and name your delegate method to include the sender. For example: - (void)mailGuyDidPostLetter:(MailGuy *)mailGuy. Though likely you actually want something more like - (void)mailGuy:(MailGuy *)mailGuy didFinishPostingLetterWithSuccess:(BOOL)success – colinbrash Sep 05 '14 at 20:08