0

I am building a command dispatch table in Objective-C using ARC. Does the form I use below look good or is there a better alternative?

For example:

    self.commandTable = [@{
                         @"command1" : ^(id value) { return [self runCommand1:value]; },
                         @"command2" : ^(id value) { return [self runCommand2:value]; },
                      } mutableCopy];
}
Boon
  • 40,656
  • 60
  • 209
  • 315

1 Answers1

1

I see at least two problems with your code.

First, stack based blocks (like the two you define in your code) won't be retained automatically when you pass them to the collection. So most likely when you will want to execute the block, your app will crash. This is very nicely explained in the answer of the question pointed out by @Josh in the comments: Block gets released whilst in NSDictionary (ARC). You should use the copy method on the block to create a heap based copy that can be retained by ARC.

Second, after you inserted the copy methods, you will have a retain cycle. Your object "self" retains the commandTable dictionary, the dictionary will retain your blocks (that's your intention, you don't want your blocks go away), and as you use the same object "self" in the blocks, your blocks will retain your "self" object. To avoid this define a __weak local variable to your "self" object as also described in the Working with blocks chapter of the documentation:

MyClass* __weak weakSelf = self;
self.commandTable = [@{
                     @"command1" : ^(id value) { return [weakSelf runCommand1:value]; },
                     @"command2" : ^(id value) { return [weakSelf runCommand2:value]; },
                  } mutableCopy];

Otherwise your pattern might do the work well.

Community
  • 1
  • 1
MrTJ
  • 13,064
  • 4
  • 41
  • 63
  • 2
    According to the specification of CLang, "instancetype is a contextual keyword that is only permitted in the result type of an Objective-C method" (source: http://clang.llvm.org/docs/LanguageExtensions.html#objective-c-features) I don't know whether some compilers are more tolerant in this question allowing you to use instancetype also other places, but I would not rely on it too much. – MrTJ Feb 20 '14 at 21:11
  • You are correct - it would appear that they changed the behavior of the keyword since it was first introduced. My mistake, these things move so fast. – Richard J. Ross III Feb 20 '14 at 21:12
  • @MrTJ If the block above is saved to property (nonatomic, copy) id (^cmd)(id value); can I use self.cmd in the dictionary or do I still need [self.cmd copy]? – Boon Feb 20 '14 at 21:25
  • A copy property will do the "copy" for you so you don't need to copy it one more time. Still keep attention on the reference cycle, it's a quite sure way to leak memory. – MrTJ Feb 20 '14 at 21:34