I often do something like:
CoolViewController *coolViewController = [[CoolViewController alloc] init];
[self.navigationController pushViewController:coolViewController animated:YES];
[coolViewController release];
How would I, in a category of UINavigationController
, override forwardInvocation:
so that I could just instead do:
[self.navigationController pushCoolViewControllerAnimated:YES];
Please include the relevant code in your answer, not just an explanation. Thank you!
Feel free to comment on whether this is good practice. I'm also asking this for educational purposes, but it seems to me that in this case, the simplification in code may outweight the unnoticeable (correct?) cost in processing time & memory usage. Also, I come from a Ruby background and love to use dynamic programming to simplify things, e.g., dynamic finders (e.g.,
find_by_name
) in Rails.Bonus points if you could implement
pushCoolViewControllerAnimated:withBlock
and invoke the block after initializing the view controller, allowing me to set certain instance variables on the view controller created.
UPDATE: I just remembered that ARC is coming soon. So this specific example may not be so helpful then, but still a great exercise/example that could be used in other cases, e.g., dynamic finders for Core Data & passing a block to configure the NSFetchRequest
.
Use the dynamic method resolution mechanism described in the Objective-C Runtime Programming Guide, specifically,
+[NSObject resolveInstanceMethod:]
:Of course, if
UINavigationController
already uses+resolveInstanceMethod:
, you've now broken it. Doing this in a subclass ofUINavigationController
, or using method swizzling to enable invoking the original implementation, would solve that problem.The version accepting a post-creation block is a straightforward extension (change the block parameters, change the type encoding, change the selector name pattern and how you extract the intended class name).