3

I have a class method that gets called by a view controller. I want the view controller to be aware of when the class method has finished its tasks (it has threads on it).
I think I should use delegation, but I need an id delegate, and I can't call it by self.delegate, because there is no self in a class method.

How should I do this?
Thanks!

David
  • 99
  • 2
  • 11
  • Why does it have to be a class method, rather than a normal object method? – trojanfoe May 12 '12 at 09:29
  • @trojanfoe Because it's a "helper" class with methods that can be executed without needing more than themselves. I also need to call them in many places, so this way I don't have to create instances of it everywhere. – David May 12 '12 at 09:37

1 Answers1

3

You can store a delegate at class-level (even separate from an object-level delegate), but it sounds a bit fishy to me. Here's how you'd do it:

In your header file:

@interface SomeClass : SomeBaseClass
{
...
}

...
+ (id<SomeDelegateProtocol>)classDelegate
+ (void)setClassDelegate(id<SomeDelegateProtocol>) delegate
+ (void)myCleanupClassMethod

@end

In your implementation file:

@implementation SomeClass
...

static id<SomeDelegateProtocol> _classDelegate = nil;

+ (id<SomeDelegateProtocol>)classDelegate
{
    return _classDelegate;
}

+ (void)setClassDelegate(id<SomeDelegateProtocol> delegate
{
    _classDelegate = delegate;
}

+ (void)myCleanupClassMethod
{
    if ([_classDelegate respondsToSelector:@selector(theDelegateMethod:)])
    {
        [_classDelegate theDelegateMethod:something];
    }
}

@end

To actually use this code, you simply set the class-level delegate like an object-level delegate and wait for it to be called (you need to decide when myCleanupClassMethod is invoked):

// Somewhere else in the project
[SomeClass setClassDelegate:self];
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • Yeah, I had thought this solution, but it also sounds weird to me. Besides, if the delegate is static, it would maybe lead to some problems, by being used various times, I'm not sure... Is there any other workaround to do this? Or I have to switch to instance methods? – David May 12 '12 at 09:48
  • @David If you can ensure you always call `[SomeClass setClassDelegate:nil]` when the class conforming to the delegate protocol is destroyed then I don't think you'll have a problem. Object-level delegates are more natural, but you will need to have some class-level counter to know when call the delegate anyway. I think it might be best to avoid this solution, as it's fishy. – trojanfoe May 12 '12 at 09:54
  • Sorry, I think I didn't understand the last point. So, you say better to use instance methods, but I'll have to use a counter? Why? :S – David May 12 '12 at 10:07
  • @David I understood you want to call this delegate method when some threads had finished their tasks, so I assume you need to keep a count of how many tasks had completed. This counter need not be class-level however, it depends on how things are created etc. – trojanfoe May 12 '12 at 10:11
  • Oh ok! The code isn't that complicated though, so I think I can skip that counter. I'll switch to instance methods and hope it'll work fine. Thanks a lot for your help! :) – David May 12 '12 at 10:18