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