NSObject+YYAdd.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. //
  2. // NSObject+YYAdd.h
  3. // YYKit <https://github.com/ibireme/YYKit>
  4. //
  5. // Created by ibireme on 14/10/8.
  6. // Copyright (c) 2015 ibireme.
  7. //
  8. // This source code is licensed under the MIT-style license found in the
  9. // LICENSE file in the root directory of this source tree.
  10. //
  11. #import <Foundation/Foundation.h>
  12. NS_ASSUME_NONNULL_BEGIN
  13. /**
  14. Common tasks for NSObject.
  15. */
  16. @interface NSObject (YYAdd)
  17. #pragma mark - Sending messages with variable parameters
  18. ///=============================================================================
  19. /// @name Sending messages with variable parameters
  20. ///=============================================================================
  21. /**
  22. Sends a specified message to the receiver and returns the result of the message.
  23. @param sel A selector identifying the message to send. If the selector is
  24. NULL or unrecognized, an NSInvalidArgumentException is raised.
  25. @param ... Variable parameter list. Parameters type must correspond to the
  26. selector's method declaration, or unexpected results may occur.
  27. It doesn't support union or struct which is larger than 256 bytes.
  28. @return An object that is the result of the message.
  29. @discussion The selector's return value will be wrap as NSNumber or NSValue
  30. if the selector's `return type` is not object. It always returns nil
  31. if the selector's `return type` is void.
  32. Sample Code:
  33. // no variable args
  34. [view performSelectorWithArgs:@selector(removeFromSuperView)];
  35. // variable arg is not object
  36. [view performSelectorWithArgs:@selector(setCenter:), CGPointMake(0, 0)];
  37. // perform and return object
  38. UIImage *image = [UIImage.class performSelectorWithArgs:@selector(imageWithData:scale:), data, 2.0];
  39. // perform and return wrapped number
  40. NSNumber *lengthValue = [@"hello" performSelectorWithArgs:@selector(length)];
  41. NSUInteger length = lengthValue.unsignedIntegerValue;
  42. // perform and return wrapped struct
  43. NSValue *frameValue = [view performSelectorWithArgs:@selector(frame)];
  44. CGRect frame = frameValue.CGRectValue;
  45. */
  46. - (nullable id)performSelectorWithArgs:(SEL)sel, ...;
  47. /**
  48. Invokes a method of the receiver on the current thread using the default mode after a delay.
  49. @warning It can't cancelled by previous request.
  50. @param sel A selector identifying the message to send. If the selector is
  51. NULL or unrecognized, an NSInvalidArgumentException is raised immediately.
  52. @param delay The minimum time before which the message is sent. Specifying
  53. a delay of 0 does not necessarily cause the selector to be
  54. performed immediately. The selector is still queued on the
  55. thread's run loop and performed as soon as possible.
  56. @param ... Variable parameter list. Parameters type must correspond to the
  57. selector's method declaration, or unexpected results may occur.
  58. It doesn't support union or struct which is larger than 256 bytes.
  59. Sample Code:
  60. // no variable args
  61. [view performSelectorWithArgs:@selector(removeFromSuperView) afterDelay:2.0];
  62. // variable arg is not object
  63. [view performSelectorWithArgs:@selector(setCenter:), afterDelay:0, CGPointMake(0, 0)];
  64. */
  65. - (void)performSelectorWithArgs:(SEL)sel afterDelay:(NSTimeInterval)delay, ...;
  66. /**
  67. Invokes a method of the receiver on the main thread using the default mode.
  68. @param sel A selector identifying the message to send. If the selector is
  69. NULL or unrecognized, an NSInvalidArgumentException is raised.
  70. @param wait A Boolean that specifies whether the current thread blocks until
  71. after the specified selector is performed on the receiver on the
  72. specified thread. Specify YES to block this thread; otherwise,
  73. specify NO to have this method return immediately.
  74. @param ... Variable parameter list. Parameters type must correspond to the
  75. selector's method declaration, or unexpected results may occur.
  76. It doesn't support union or struct which is larger than 256 bytes.
  77. @return While @a wait is YES, it returns object that is the result of
  78. the message. Otherwise return nil;
  79. @discussion The selector's return value will be wrap as NSNumber or NSValue
  80. if the selector's `return type` is not object. It always returns nil
  81. if the selector's `return type` is void, or @a wait is YES.
  82. Sample Code:
  83. // no variable args
  84. [view performSelectorWithArgsOnMainThread:@selector(removeFromSuperView), waitUntilDone:NO];
  85. // variable arg is not object
  86. [view performSelectorWithArgsOnMainThread:@selector(setCenter:), waitUntilDone:NO, CGPointMake(0, 0)];
  87. */
  88. - (nullable id)performSelectorWithArgsOnMainThread:(SEL)sel waitUntilDone:(BOOL)wait, ...;
  89. /**
  90. Invokes a method of the receiver on the specified thread using the default mode.
  91. @param sel A selector identifying the message to send. If the selector is
  92. NULL or unrecognized, an NSInvalidArgumentException is raised.
  93. @param thread The thread on which to execute aSelector.
  94. @param wait A Boolean that specifies whether the current thread blocks until
  95. after the specified selector is performed on the receiver on the
  96. specified thread. Specify YES to block this thread; otherwise,
  97. specify NO to have this method return immediately.
  98. @param ... Variable parameter list. Parameters type must correspond to the
  99. selector's method declaration, or unexpected results may occur.
  100. It doesn't support union or struct which is larger than 256 bytes.
  101. @return While @a wait is YES, it returns object that is the result of
  102. the message. Otherwise return nil;
  103. @discussion The selector's return value will be wrap as NSNumber or NSValue
  104. if the selector's `return type` is not object. It always returns nil
  105. if the selector's `return type` is void, or @a wait is YES.
  106. Sample Code:
  107. [view performSelectorWithArgs:@selector(removeFromSuperView) onThread:mainThread waitUntilDone:NO];
  108. [array performSelectorWithArgs:@selector(sortUsingComparator:)
  109. onThread:backgroundThread
  110. waitUntilDone:NO, ^NSComparisonResult(NSNumber *num1, NSNumber *num2) {
  111. return [num2 compare:num2];
  112. }];
  113. */
  114. - (nullable id)performSelectorWithArgs:(SEL)sel onThread:(NSThread *)thread waitUntilDone:(BOOL)wait, ...;
  115. /**
  116. Invokes a method of the receiver on a new background thread.
  117. @param sel A selector identifying the message to send. If the selector is
  118. NULL or unrecognized, an NSInvalidArgumentException is raised.
  119. @param ... Variable parameter list. Parameters type must correspond to the
  120. selector's method declaration, or unexpected results may occur.
  121. It doesn't support union or struct which is larger than 256 bytes.
  122. @discussion This method creates a new thread in your application, putting
  123. your application into multithreaded mode if it was not already.
  124. The method represented by sel must set up the thread environment
  125. just as you would for any other new thread in your program.
  126. Sample Code:
  127. [array performSelectorWithArgsInBackground:@selector(sortUsingComparator:),
  128. ^NSComparisonResult(NSNumber *num1, NSNumber *num2) {
  129. return [num2 compare:num2];
  130. }];
  131. */
  132. - (void)performSelectorWithArgsInBackground:(SEL)sel, ...;
  133. /**
  134. Invokes a method of the receiver on the current thread after a delay.
  135. @warning arc-performSelector-leaks
  136. @param sel A selector that identifies the method to invoke. The method should
  137. not have a significant return value and should take no argument.
  138. If the selector is NULL or unrecognized,
  139. an NSInvalidArgumentException is raised after the delay.
  140. @param delay The minimum time before which the message is sent. Specifying a
  141. delay of 0 does not necessarily cause the selector to be performed
  142. immediately. The selector is still queued on the thread's run loop
  143. and performed as soon as possible.
  144. @discussion This method sets up a timer to perform the aSelector message on
  145. the current thread's run loop. The timer is configured to run in
  146. the default mode (NSDefaultRunLoopMode). When the timer fires, the
  147. thread attempts to dequeue the message from the run loop and
  148. perform the selector. It succeeds if the run loop is running and
  149. in the default mode; otherwise, the timer waits until the run loop
  150. is in the default mode.
  151. */
  152. - (void)performSelector:(SEL)sel afterDelay:(NSTimeInterval)delay;
  153. #pragma mark - Swap method (Swizzling)
  154. ///=============================================================================
  155. /// @name Swap method (Swizzling)
  156. ///=============================================================================
  157. /**
  158. Swap two instance method's implementation in one class. Dangerous, be careful.
  159. @param originalSel Selector 1.
  160. @param newSel Selector 2.
  161. @return YES if swizzling succeed; otherwise, NO.
  162. */
  163. + (BOOL)swizzleInstanceMethod:(SEL)originalSel with:(SEL)newSel;
  164. /**
  165. Swap two class method's implementation in one class. Dangerous, be careful.
  166. @param originalSel Selector 1.
  167. @param newSel Selector 2.
  168. @return YES if swizzling succeed; otherwise, NO.
  169. */
  170. + (BOOL)swizzleClassMethod:(SEL)originalSel with:(SEL)newSel;
  171. #pragma mark - Associate value
  172. ///=============================================================================
  173. /// @name Associate value
  174. ///=============================================================================
  175. /**
  176. Associate one object to `self`, as if it was a strong property (strong, nonatomic).
  177. @param value The object to associate.
  178. @param key The pointer to get value from `self`.
  179. */
  180. - (void)setAssociateValue:(nullable id)value withKey:(void *)key;
  181. /**
  182. Associate one object to `self`, as if it was a weak property (week, nonatomic).
  183. @param value The object to associate.
  184. @param key The pointer to get value from `self`.
  185. */
  186. - (void)setAssociateWeakValue:(nullable id)value withKey:(void *)key;
  187. /**
  188. Get the associated value from `self`.
  189. @param key The pointer to get value from `self`.
  190. */
  191. - (nullable id)getAssociatedValueForKey:(void *)key;
  192. /**
  193. Remove all associated values.
  194. */
  195. - (void)removeAssociatedValues;
  196. #pragma mark - Others
  197. ///=============================================================================
  198. /// @name Others
  199. ///=============================================================================
  200. /**
  201. Returns the class name in NSString.
  202. */
  203. + (NSString *)className;
  204. /**
  205. Returns the class name in NSString.
  206. @discussion Apple has implemented this method in NSObject(NSLayoutConstraintCallsThis),
  207. but did not make it public.
  208. */
  209. - (NSString *)className;
  210. /**
  211. Returns a copy of the instance with `NSKeyedArchiver` and ``NSKeyedUnarchiver``.
  212. Returns nil if an error occurs.
  213. */
  214. - (nullable id)deepCopy;
  215. /**
  216. Returns a copy of the instance use archiver and unarchiver.
  217. Returns nil if an error occurs.
  218. @param archiver NSKeyedArchiver class or any class inherited.
  219. @param unarchiver NSKeyedUnarchiver clsas or any class inherited.
  220. */
  221. - (nullable id)deepCopyWithArchiver:(Class)archiver unarchiver:(Class)unarchiver;
  222. @end
  223. NS_ASSUME_NONNULL_END