Reputation: 177
EDITED TO INCLUDE CODE.
Is it possible in Objective C, to have class A be a delegate to class B, while class B is being a delegate to class A?
I have the first delegate (call it A to B) working fine. I then implement it the other way around and it can’t find the delegate method, with the classic warning: Method 'audioCueHasMovedDelegateMethod' in protocol 'SoundpaperViewControllerDelegate' not implemented.
Before I take the time to upload the code, please let me know if this is possible and I’m just doing something wrong, or if it can’t work in the first place and I need to use another technique such as NSNotification. I’ve done my Googling but can’t find this issued addressed.
If this is legal in theory then I'll upload my code.
Thank you.
Is it possible, in Objective C, to have method A be delegate to method B, while method B is being a delate to method A?
I have the first delegate (call it A to B) working fine. I then implement it the other way around and it can’t find the delegate method, with the classic warning:
Method 'audioCueHasMovedDelegateMethod' in protocol 'SoundpaperViewControllerDelegate' not implemented.
Before I take the time to upload the code, please let me know if this is possible and I’m just doing something wrong, or if it can’t work in the first place and I need to use another technique such as NSNotification. I’ve done my Googling but can’t find this issued addressed. Thank you. THIS IS CLASS A: Class A AudioOperations, this calls a method in Class B, SoundpaperViewController, called setupAudioPlayerControls. This is because the view controller is what talks to the screen (using Storyboards). While I want to separate the audio player into a separate class and separate files for cleanliness. This works just fine
AudioOperations.h
. . .
@class AudioOperations;
@class SoundPaperViewController;
@protocol AudioOperationsDelegate <NSObject>
- (void) setupAudioPlayerControls; // THIS is called on Class B and works fine
@end
@interface AudioOperations : NSObject
@property (nonatomic, weak) IBOutlet id <AudioOperationsDelegate> delegate;
. . .
@end
Simplified AudioOperations.mm
@interface AudioOperations () <AVAudioPlayerDelegate>
@end
- (void) audioPlayback // simplified to show what is important
{
NSLog(@"Entering audioPlayback");
self.audioPlayer.delegate = self;
NSLog(@"calling setupaudioplayercontrols from audioPlayback");
[self.delegate setupAudioPlayerControls]; // delegated to soundpaperviewcontroller and works just fine
NSLog(@"Exiting audioPlayback");
}
. . . (various other code)
- (void) audioCueHasMovedDelegateMethod // THIS IS THE method that should be called from Class B but can’t be found (where the warning comes from)
{
// User has released the cue while inside the control - update the player…
NSLog(@"in delegate audioCueHasMoved");
[self.audioPlayer setCurrentTime: self.delegate.audioCueSlider.value];
if (self.audioPlayer.isPlaying == NO)
{
[self.audioPlayer play];
}
// … and go back to updating the control.
self.audioTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1
target: self
selector: @selector(updateAudioTime:)
userInfo: nil
repeats: YES];
}
THIS IS CLASS B (again simplified)
SoundpaperViewController.h
. . .
@class LabelProcessor;
@class AudioOperations;
@class SpotterGraphicsView;
@protocol SoundpaperViewControllerDelegate <NSObject>
- (void) audioCueHasMovedDelegateMethod; // this is the method that should be called but isn’t found
@end
@interface SoundPaperViewController : UIViewController<QLPreviewControllerDataSource, QLPreviewControllerDelegate>
@property (nonatomic, weak) IBOutlet id <SoundpaperViewControllerDelegate> delegate;
. . .
@end
SoundpaperViewController.mm
. . . (bunch of #imports etc)
@interface SoundPaperViewController () <AVCaptureVideoDataOutputSampleBufferDelegate
,AVCaptureMetadataOutputObjectsDelegate
,LabelProcessorDelegate
,AudioOperationsDelegate
,SettingsObserver
,CEGuideArrowDelegate
,SoundpaperViewControllerDelegate // NOT SURE THIS IS RIGHT, but I’ve tried it with and without it
>
. . . (bunch of @properties, etc.)
@implementation SoundPaperViewController // WARNING IS HERE that the method audioCueHasMovedDelegateMethod can’t be found
- (id) initWithCoder: (NSCoder*) inDecoder
{
if ((self = [super initWithCoder: inDecoder]) != nil)
{
NSLog(@"new latestImageCond created NEW");
self.latestImageCondition = [NSCondition new];
NSLog(@"initWithCoder spvc thread: %@", [NSThread currentThread]);
}
self.delegate = self; // NOTE this
return self;
}
// This is the delegate method called from CLASS A (AudioOperations) and works just fine:
- (void) setupAudioPlayerControls
{
NSLog(@"setupAudioPlayerControls");
// hide the playbutton
[self.playButton setEnabled:NO];
[self.playButton setTintColor: [UIColor clearColor]]; // hides it
. . . etc.
}
As near as I can tell I’ve done everything identically in both classes (with the one exception that I’m not sure of whether to use this SoundpaperViewControllerDelegate in the interface.
Thank you for working through this mess of code. I’m sure I’m missing something obvious!
Upvotes: 0
Views: 123
Reputation: 177
With the help of a friend I was able to get this to work. For those who might have a similar problem, it was a matter of getting the .h files set up correctly:
In the SoundpaperViewController.h:
@class LabelProcessor;
@class AudioOperations;
@class SoundPaperViewController;
@interface SoundPaperViewController : UIViewController < QLPreviewControllerDataSource, QLPreviewControllerDelegate> // note no audioOperationsDelegate in this line
- (void) setupAudioPlayerControls;
@property (nonatomic, strong) AudioOperations * SPVdelegate;
In the AudioOperations Class:
@class AudioOperations;
@class SoundPaperViewController;
@interface AudioOperations : NSObject // note no SoundpaperViewControllerDelegate here
@property (nonatomic, weak) SoundPaperViewController * audioDelegate;
- (void) audioCueHasMovedDelegateMethod;
And in the Soundpaper class .m file:
_myAudio = [[AudioOperations alloc] init];
_myAudio.audioDelegate = self;
self.SPVdelegate = _myAudio;
It was enlightening to me that I didn't need to include the delegate in the @interface (for instance @interface SoundpaperViewController ) Getting rid of that and simply declaring the @property was all that was needed.
Upvotes: 0
Reputation: 1352
Yes, this can be done. Be sure each one has a weak reference to the other so that you don't end up with a retain cycle.
Upvotes: 2