Posted By

zingo on 09/26/08


Tagged

cocoa debug osx objc


Versions (?)

Parse Header File for Outlets and makes sure that they are set at Runtime


 / Published in: Objective C
 

URL: http://www.potionfactory.com/blog/2008/06/15/f-nil-outlets

  1. // -------------------------
  2. // header file
  3. // -------------------------
  4. #ifndef RELEASE
  5. #define PFValidateOutlets(obj) PFValidateOutlets_(obj, [NSString stringWithFormat:@"%s", __FILE__], nil)
  6. #define PFValidateOutletsInFile(obj, header) PFValidateOutlets_(obj, [NSString stringWithFormat:@"%s", __FILE__], header)
  7. #else
  8. #define PFValidateOutlets(obj)
  9. #define PFValidateOutletsInFile(obj, header)
  10. #endif
  11.  
  12. // -------------------------
  13. // .m file
  14. // -------------------------
  15. #import <objc/runtime.h>
  16.  
  17. void PFValidateOutlets_(id obj, NSString *filepath, NSString *headerFilename)
  18. {
  19. #ifndef RELEASE
  20. if (headerFilename) {
  21. filepath = [[filepath stringByDeletingLastPathComponent] stringByAppendingPathComponent:headerFilename];
  22. }
  23. if (![filepath hasSuffix:@".h"]) {
  24. filepath = [NSString stringWithFormat:@"%@.h", [filepath stringByDeletingPathExtension]];
  25. }
  26.  
  27. // Parse the outlets
  28. if ([[NSFileManager defaultManager] fileExistsAtPath:filepath]) {
  29. NSString *source = [NSString stringWithContentsOfFile:filepath];
  30. NSArray *classes = [source componentsSeparatedByString:@"@interface"];
  31.  
  32. NSCharacterSet *spacesSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
  33. NSCharacterSet *wordTokenizingSet = [NSCharacterSet characterSetWithCharactersInString:@" \t\n\r{}*:;"];
  34. NSCharacterSet *statementTokenizingSet = [NSCharacterSet characterSetWithCharactersInString:@"{}:;/"];
  35. NSCharacterSet *lineSeparatingSet = [NSCharacterSet characterSetWithCharactersInString:@"\n\r"];
  36.  
  37. for (NSString *classSource in classes) {
  38. NSScanner *scanner = [NSScanner scannerWithString:classSource];
  39. [scanner scanCharactersFromSet:spacesSet intoString:nil];
  40.  
  41. NSString *className;
  42.  
  43. // Proceed if the parsed class matches the object's class
  44. if ([scanner scanUpToCharactersFromSet:wordTokenizingSet intoString:&className] &&
  45. [className isEqualToString:NSStringFromClass([obj class])]) {
  46.  
  47. NSArray *lines = [classSource componentsSeparatedByCharactersInSet:lineSeparatingSet];
  48.  
  49. for (NSString *line in lines) {
  50. // Skip comment lines
  51. if ([[line stringByTrimmingCharactersInSet:spacesSet] hasPrefix:@"//"]) continue;
  52.  
  53. NSArray *statements = [line componentsSeparatedByCharactersInSet:statementTokenizingSet];
  54. for (NSString *statement in statements) {
  55. if ([[statement stringByTrimmingCharactersInSet:spacesSet] hasPrefix:@"IBOutlet"]) {
  56. NSString *outletName = [[statement componentsSeparatedByCharactersInSet:wordTokenizingSet] lastObject];
  57. Ivar outletIvar = class_getInstanceVariable([obj class], [outletName UTF8String]);
  58. id outletValue = object_getIvar(obj, outletIvar);
  59. if (outletValue == nil)
  60. NSLog(@"WARNING -- %@'s outlet %@ is nil", className, outletName, outletValue);
  61. }
  62. }
  63. }
  64. }
  65. }
  66. }
  67. #endif
  68. }
  69.  
  70. // -------------------------
  71. // usage
  72. // -------------------------
  73. - (void)awakeFromNib
  74. {
  75. PFValidateOutlets(self);
  76. // Rest of the code
  77. }

Report this snippet  

You need to login to post a comment.