GTMMethodCheck.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. //
  2. // GTMMethodCheck.h
  3. //
  4. // Copyright 2006-2016 Google Inc.
  5. //
  6. // Licensed under the Apache License, Version 2.0 (the "License"); you may not
  7. // use this file except in compliance with the License. You may obtain a copy
  8. // of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  14. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  15. // License for the specific language governing permissions and limitations under
  16. // the License.
  17. //
  18. #import <Foundation/Foundation.h>
  19. #import <stdio.h>
  20. #import <sysexits.h>
  21. /// A macro for enforcing debug time checks to make sure all required methods are linked in
  22. //
  23. // When using categories, it can be very easy to forget to include the
  24. // implementation of a category.
  25. // Let's say you had a class foo that depended on method bar of class baz, and
  26. // method bar was implemented as a member of a category.
  27. // You could add the following code:
  28. //
  29. // GTM_METHOD_CHECK(baz, bar)
  30. //
  31. // and the code would check to make sure baz was implemented just before main
  32. // was called. This works for both dynamic libraries, and executables.
  33. //
  34. //
  35. // This is not compiled into release builds.
  36. #ifdef DEBUG
  37. // This is the "magic".
  38. // A) we need a multi layer define here so that the preprocessor expands
  39. // __LINE__ the way we want it. We need __LINE__ so that each of our
  40. // GTM_METHOD_CHECKs generates a unique function name.
  41. #define GTM_METHOD_CHECK(class, method) GTM_METHOD_CHECK_INNER(class, method, __LINE__)
  42. #define GTM_METHOD_CHECK_INNER(class, method, line) \
  43. GTM_METHOD_CHECK_INNER_INNER(class, method, line)
  44. // B) define a function that is called at startup to check that |class| has an
  45. // implementation for |method| (either a class method or an instance method).
  46. #define GTM_METHOD_CHECK_INNER_INNER(class, method, line) \
  47. __attribute__ ((constructor, visibility("hidden"))) \
  48. static void xxGTMMethodCheckMethod ## class ## line () { \
  49. @autoreleasepool { \
  50. if (![class instancesRespondToSelector:@selector(method)] \
  51. && ![class respondsToSelector:@selector(method)]) { \
  52. fprintf(stderr, "%s:%d: error: We need method '%s' to be linked in for class '%s'\n", \
  53. __FILE__, line, #method, #class); \
  54. exit(EX_SOFTWARE); \
  55. } \
  56. } \
  57. }
  58. #else // DEBUG
  59. // Do nothing in release.
  60. #define GTM_METHOD_CHECK(class, method)
  61. #endif // DEBUG