首先感谢祖国,可以无忧无虑的码代码 ~
If I have seen further, it is by standing on the shoudlers of giants.
1. Category
OC
中的分类允许通过给一个类添加方法来进行扩充,并且不需要访问类中的代码就可以做到,但是通过分类不能添加新的实例变量
Category
是一个指向objc_category
结构体的指针
/// An opaque type that represents a category.
typedef struct objc_category *Category;
struct objc_category {
// 分类名
char * _Nonnull category_name OBJC2_UNAVAILABLE;
// 分类所属类名
char * _Nonnull class_name OBJC2_UNAVAILABLE;
// 分类实例方法列表,是 objc_class 中方法列表的子集
struct objc_method_list * _Nullable instance_methods OBJC2_UNAVAILABLE;
// 分类类方法列表,是元类的 方法列表的子集
struct objc_method_list * _Nullable class_methods OBJC2_UNAVAILABLE;
// 分类所实现的协议列表
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE;
在<objc/runtime.h>
没有关于category
的操作函数,因为分类中的信息都包含在objc_class
中,比如可以获取objc_class
的方法列表来获取分类的方法,看栗子
@implementation FFBaseViewController (statistics)
- (void)baseVcCategoryMethod {
NSLog(@"%s", __func__);
}
@end
@implementation FFBaseViewController
- (void)viewDidLoad {
[super viewDidLoad];
unsigned int outcount = 0;
Method *methodList = class_copyMethodList(self.class, &outcount);
for (int i = 0; i < outcount; i ++) {
Method method = methodList[i];
const char *name = sel_getName(method_getName(method));
NSLog(@"FFBaseViewController ---> %s", name);
if (strcmp(name, sel_getName(@selector(baseVcCategoryMethod))) == 0) {
NSLog(@"FFBaseViewController 分类的方法在 objc_class 方法列表中 ---> %s", name);
}
}
}
@end
// 2018-04-06 15:00:04.050 runtime[2810:172396] FFBaseViewController ---> baseVcCategoryMethod
// 2018-04-06 15:00:04.050 runtime[2810:172396] FFBaseViewController 分类的方法在 objc_class 方法列表中 ---> baseVcCategoryMethod
// 2018-04-06 15:00:04.050 runtime[2810:172396] FFBaseViewController ---> ff_viewWillAppear:
// 2018-04-06 15:00:04.050 runtime[2810:172396] FFBaseViewController ---> baseVcShowSomething
// 2018-04-06 15:00:04.051 runtime[2810:172396] FFBaseViewController ---> viewWillAppear:
// 2018-04-06 15:00:04.051 runtime[2810:172396] FFBaseViewController ---> viewDidLoad
2. Protocol
OC
中的协议是普遍存在的接口定义形式,在一个类中通过@protocol
定义接口,在另外的类中实现接口,这种定义接口的形式也称作delegate模式
,@protocol
声明了可以被其他任何类实现的方法,协议仅仅是定义了一个接口,而有其他去负责实现
protocol
是一个对象的结构体
#ifdef __OBJC__
@class Protocol;
#else
typedef struct objc_object Protocol;
#endif
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
运行时提供了一系列的函数,用来操作protocol
-
objc_getProtocol
返回指定的协议,如果仅仅是声明了一个协议,而未在任何类中实现,返回nil
/**
* Returns a specified protocol.
*
* @param name The name of a protocol.
*
* @return The protocol named \e name, or \c NULL if no protocol named \e name could be found.
*
* @note This function acquires the runtime lock.
*/
OBJC_EXPORT Protocol * _Nullable
objc_getProtocol(const char * _Nonnull name)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
objc_copyProtocolList
获取运行时所知道的所有协议的数组,使用后需要free()
/**
* Returns an array of all the protocols known to the runtime.
*
* @param outCount Upon return, contains the number of protocols in the returned array.
*
* @return A C array of all the protocols known to the runtime. The array contains \c *outCount
* pointers followed by a \c NULL terminator. You must free the list with \c free().
*
* @note This function acquires the runtime lock.
*/
OBJC_EXPORT Protocol * __unsafe_unretained _Nonnull * _Nullable
objc_copyProtocolList(unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
protocol_conformsToProtocol
查看协议是否实现了另一协议
/**
* Returns a Boolean value that indicates whether one protocol conforms to another protocol.
*
* @param proto A protocol.
* @param other A protocol.
*
* @return \c YES if \e proto conforms to \e other, otherwise \c NO.
*
* @note One protocol can incorporate other protocols using the same syntax
* that classes use to adopt a protocol:
* \code
* @protocol ProtocolName < protocol list >
* \endcode
* All the protocols listed between angle brackets are considered part of the ProtocolName protocol.
*/
OBJC_EXPORT BOOL
protocol_conformsToProtocol(Protocol * _Nullable proto,
Protocol * _Nullable other)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
protocol_isEqual
两个协议是否相等
/**
* Returns a Boolean value that indicates whether two protocols are equal.
*
* @param proto A protocol.
* @param other A protocol.
*
* @return \c YES if \e proto is the same as \e other, otherwise \c NO.
*/
OBJC_EXPORT BOOL
protocol_isEqual(Protocol * _Nullable proto, Protocol * _Nullable other)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
protocol_getName
获取协议名称
/**
* Returns the name of a protocol.
*
* @param p A protocol.
*
* @return The name of the protocol \e p as a C string.
*/
OBJC_EXPORT const char * _Nonnull
protocol_getName(Protocol * _Nonnull proto)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
protocol_getMethodDescription
获取协议中指定的方法描述
/**
* Returns a method description structure for a specified method of a given protocol.
*
* @param p A protocol.
* @param aSel A selector.
* @param isRequiredMethod A Boolean value that indicates whether aSel is a required method.
* @param isInstanceMethod A Boolean value that indicates whether aSel is an instance method.
*
* @return An \c objc_method_description structure that describes the method specified by \e aSel,
* \e isRequiredMethod, and \e isInstanceMethod for the protocol \e p.
* If the protocol does not contain the specified method, returns an \c objc_method_description structure
* with the value \c {NULL, \c NULL}.
*
* @note This function recursively searches any protocols that this protocol conforms to.
*/
OBJC_EXPORT struct objc_method_description
protocol_getMethodDescription(Protocol * _Nonnull proto, SEL _Nonnull aSel,
BOOL isRequiredMethod, BOOL isInstanceMethod)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
protocol_copyMethodDescriptionList
获取协议中指定条件的方法的方法描述数组
/**
* Returns an array of method descriptions of methods meeting a given specification for a given protocol.
*
* @param p A protocol.
* @param isRequiredMethod A Boolean value that indicates whether returned methods should
* be required methods (pass YES to specify required methods).
* @param isInstanceMethod A Boolean value that indicates whether returned methods should
* be instance methods (pass YES to specify instance methods).
* @param outCount Upon return, contains the number of method description structures in the returned array.
*
* @return A C array of \c objc_method_description structures containing the names and types of \e p's methods
* specified by \e isRequiredMethod and \e isInstanceMethod. The array contains \c *outCount pointers followed
* by a \c NULL terminator. You must free the list with \c free().
* If the protocol declares no methods that meet the specification, \c NULL is returned and \c *outCount is 0.
*
* @note Methods in other protocols adopted by this protocol are not included.
*/
OBJC_EXPORT struct objc_method_description * _Nullable
protocol_copyMethodDescriptionList(Protocol * _Nonnull proto,
BOOL isRequiredMethod,
BOOL isInstanceMethod,
unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
protocol_getProperty
获取协议指定的属性
/**
* Returns the specified property of a given protocol.
*
* @param proto A protocol.
* @param name The name of a property.
* @param isRequiredProperty \c YES searches for a required property, \c NO searches for an optional property.
* @param isInstanceProperty \c YES searches for an instance property, \c NO searches for a class property.
*
* @return The property specified by \e name, \e isRequiredProperty, and \e isInstanceProperty for \e proto,
* or \c NULL if none of \e proto's properties meets the specification.
*/
OBJC_EXPORT objc_property_t _Nullable
protocol_getProperty(Protocol * _Nonnull proto,
const char * _Nonnull name,
BOOL isRequiredProperty, BOOL isInstanceProperty)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
protocol_copyPropertyList
获取协议中的属性列表
/**
* Returns an array of the required instance properties declared by a protocol.
*
* @note Identical to
* \code
* protocol_copyPropertyList2(proto, outCount, YES, YES);
* \endcode
*/
OBJC_EXPORT objc_property_t _Nonnull * _Nullable
protocol_copyPropertyList(Protocol * _Nonnull proto,
unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
protocol_copyPropertyList2
/**
* Returns an array of properties declared by a protocol.
*
* @param proto A protocol.
* @param outCount Upon return, contains the number of elements in the returned array.
* @param isRequiredProperty \c YES returns required properties, \c NO returns optional properties.
* @param isInstanceProperty \c YES returns instance properties, \c NO returns class properties.
*
* @return A C array of pointers of type \c objc_property_t describing the properties declared by \e proto.
* Any properties declared by other protocols adopted by this protocol are not included. The array contains
* \c *outCount pointers followed by a \c NULL terminator. You must free the array with \c free().
* If the protocol declares no matching properties, \c NULL is returned and \c *outCount is \c 0.
*/
OBJC_EXPORT objc_property_t _Nonnull * _Nullable
protocol_copyPropertyList2(Protocol * _Nonnull proto,
unsigned int * _Nullable outCount,
BOOL isRequiredProperty, BOOL isInstanceProperty)
OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
-
protocol_copyProtocolList
获取协议采用的协议
/**
* Returns an array of the protocols adopted by a protocol.
*
* @param proto A protocol.
* @param outCount Upon return, contains the number of elements in the returned array.
*
* @return A C array of protocols adopted by \e proto. The array contains \e *outCount pointers
* followed by a \c NULL terminator. You must free the array with \c free().
* If the protocol declares no properties, \c NULL is returned and \c *outCount is \c 0.
*/
OBJC_EXPORT Protocol * __unsafe_unretained _Nonnull * _Nullable
protocol_copyProtocolList(Protocol * _Nonnull proto,
unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
objc_allocateProtocol
创建新的协议实例,如果已经存在同名协议返回nil
/**
* Creates a new protocol instance that cannot be used until registered with
* \c objc_registerProtocol()
*
* @param name The name of the protocol to create.
*
* @return The Protocol instance on success, \c nil if a protocol
* with the same name already exists.
* @note There is no dispose method for this.
*/
OBJC_EXPORT Protocol * _Nullable
objc_allocateProtocol(const char * _Nonnull name)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
-
objc_registerProtocol
在运行时注册新的协议,创建一个新的协议后,必须在运行时调用该函数进行注册,注册以后即可使用,但是不能再修改,即注册完成后不能再修改,即无法通过protocol_addMethodDescription
、protocol_addProtocol
、protocol_addProperty
向协议中添加
/**
* Registers a newly constructed protocol with the runtime. The protocol
* will be ready for use and is immutable after this.
*
* @param proto The protocol you want to register.
*/
OBJC_EXPORT void
objc_registerProtocol(Protocol * _Nonnull proto)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
-
protocol_addMethodDescription
为协议添加方法
/**
* Adds a method to a protocol. The protocol must be under construction.
*
* @param proto The protocol to add a method to.
* @param name The name of the method to add.
* @param types A C string that represents the method signature.
* @param isRequiredMethod YES if the method is not an optional method.
* @param isInstanceMethod YES if the method is an instance method.
*/
OBJC_EXPORT void
protocol_addMethodDescription(Protocol * _Nonnull proto, SEL _Nonnull name,
const char * _Nullable types,
BOOL isRequiredMethod, BOOL isInstanceMethod)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
-
protocol_addProtocol
添加一个已经注册的协议到协议中
/**
* Adds an incorporated protocol to another protocol. The protocol being
* added to must still be under construction, while the additional protocol
* must be already constructed.
*
* @param proto The protocol you want to add to, it must be under construction.
* @param addition The protocol you want to incorporate into \e proto, it must be registered.
*/
OBJC_EXPORT void
protocol_addProtocol(Protocol * _Nonnull proto, Protocol * _Nonnull addition)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
-
protocol_addProperty
为协议添加属性
/**
* Adds a property to a protocol. The protocol must be under construction.
*
* @param proto The protocol to add a property to.
* @param name The name of the property.
* @param attributes An array of property attributes.
* @param attributeCount The number of attributes in \e attributes.
* @param isRequiredProperty YES if the property (accessor methods) is not optional.
* @param isInstanceProperty YES if the property (accessor methods) are instance methods.
* This is the only case allowed fo a property, as a result, setting this to NO will
* not add the property to the protocol at all.
*/
OBJC_EXPORT void
protocol_addProperty(Protocol * _Nonnull proto, const char * _Nonnull name,
const objc_property_attribute_t * _Nullable attributes,
unsigned int attributeCount,
BOOL isRequiredProperty, BOOL isInstanceProperty)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
3. super
在OC
中,如果需要在类的方法中调用父类的方法的时候,通常会用到super
,而super
与self
不同,self
是一个隐藏参数,每个方法实现的第一个参数就是self
,而super
并不是隐藏参数,而是一个“编译器标示符”,负责告诉编译器,在这里需要调用父类的方法,而不是本类中的方法,而实际上与self
指向相同的消息接收者
定义在<objc/message.h>
中
/// Specifies the superclass of an instance.
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained _Nonnull id receiver;
/// Specifies the particular superclass of the instance to message.
#if !defined(__cplusplus) && !__OBJC2__
/* For compatibility with old objc-runtime.h header */
__unsafe_unretained _Nonnull Class class;
#else
__unsafe_unretained _Nonnull Class super_class;
#endif
/* super_class is the first class to search */
};
#endif
这个结构体有两个成员
-
receiver
消息的实际接收者 -
super_class
指向当前类的父类
/* Basic Messaging Primitives
*
* On some architectures, use objc_msgSend_stret for some struct return types.
* On some architectures, use objc_msgSend_fpret for some float return types.
* On some architectures, use objc_msgSend_fp2ret for some float return types.
*
* These functions must be cast to an appropriate function pointer type
* before being called.
*/
#if !OBJC_OLD_DISPATCH_PROTOTYPES
OBJC_EXPORT void
objc_msgSend(void /* id self, SEL op, ... */ )
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
OBJC_EXPORT void
objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
#else
/**
* Sends a message with a simple return value to an instance of a class.
*
* @param self A pointer to the instance of the class that is to receive the message.
* @param op The selector of the method that handles the message.
* @param ...
* A variable argument list containing the arguments to the method.
*
* @return The return value of the method.
*
* @note When it encounters a method call, the compiler generates a call to one of the
* functions \c objc_msgSend, \c objc_msgSend_stret, \c objc_msgSendSuper, or \c objc_msgSendSuper_stret.
* Messages sent to an object’s superclass (using the \c super keyword) are sent using \c objc_msgSendSuper;
* other messages are sent using \c objc_msgSend. Methods that have data structures as return values
* are sent using \c objc_msgSendSuper_stret and \c objc_msgSend_stret.
*/
OBJC_EXPORT id _Nullable
objc_msgSend(id _Nullable self, SEL _Nonnull op, ...)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
/**
* Sends a message with a simple return value to the superclass of an instance of a class.
*
* @param super A pointer to an \c objc_super data structure. Pass values identifying the
* context the message was sent to, including the instance of the class that is to receive the
* message and the superclass at which to start searching for the method implementation.
* @param op A pointer of type SEL. Pass the selector of the method that will handle the message.
* @param ...
* A variable argument list containing the arguments to the method.
*
* @return The return value of the method identified by \e op.
*
* @see objc_msgSend
*/
OBJC_EXPORT id _Nullable
objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
#endif
当使用super
来接收消息的时候,编译器会生成objc_super
结构体,这个结构体的receiver
是当前类对象,与self
一致,而super_class
指向其父类
而发送消息时候,不是调用的的objc_msgSend
函数,而是调用的
objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
该函数第一个参数即objc_super
结构体,第二个参数是方法的SEL
以在vc
中的viewDidLoad
中调用[super viewDidLoad]
为例,
函数objc_msgSendSuper
的实际操作为,
从objc_super
结构体指向的superClass
的方法列表开始查找viewDidLoad
的selector
,
找到后以objc->receiver
去调用这个selector
,
相当于objc_msgSend(objc_super->receiver, @selector(viewDidLoad))
,
由于objc_super->receiver
是self
本身,
所以该方法实际与objc_msgSend(self, @selector(viewDidload))
相同
来验证
@implementation FFBaseViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"self.class ---> %@", self.class);
NSLog(@"super.class ---> %@", super.class);
}
// 2018-04-06 16:36:48.460 runtime[3563:301512] self.class ---> FFBaseViewController
// 2018-04-06 16:36:48.460 runtime[3563:301512] super.class ---> FFBaseViewController
@end
当使用[self class]
时,这时的self
是FFBaseViewController
,在使用 objc_msgSend
时,第一个参数是receiver
也就是self
,也是 FFBaseViewController *baseVC
这个实例。第二个参数,要先找到 class
这个方法的 selector
,先从 FFBaseViewController
这个类开始找,没有,然后到 FFBaseViewController
的父类 UIViewController
中去找,也没有,等,一层一层向上找之后,在 NSObject
的类中发现这个 class
方法,而 NSObject
的这个class
方法,就是返回 receiver
的类别,所以这里输出 FFBaseViewController
当使用 [super class]
时,这时要转换成 objc_msgSendSuper
的方法。先构造 objc_super
的结构体吧,第一个成员变量就是 self
,第二个成员变量是 UIViewController
,然后要找 class
这个 selector
,先去 superClass
也就是 UIViewController
中去找,没有,然后去 UIViewController
的父类UIResponder
中去找,结果还是在 NSObject
中找到了。然后内部使用函数 objc_msgSend(objc_super->receiver, @selector(class))
去调用,此时已经和用 [self class]
调用时相同了,此时的 receiver
还是 FFBaseViewController *baseVC
,所以这里返回的也是 FFBaseViewController
4. Working with Libraries
库相关的操作,主要是用于获取系统提供的库的相关信息
-
objc_copyImageName
获取所有加载的OC
框架和动态库的名称
/**
* Returns the names of all the loaded Objective-C frameworks and dynamic
* libraries.
*
* @param outCount The number of names returned.
*
* @return An array of C strings of names. Must be free()'d by caller.
*/
OBJC_EXPORT const char * _Nonnull * _Nonnull
objc_copyImageNames(unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
class_getImageName
获取指定类所在的动态库
/**
* Returns the dynamic library name a class originated from.
*
* @param cls The class you are inquiring about.
*
* @return The name of the library containing this class.
*/
OBJC_EXPORT const char * _Nullable
class_getImageName(Class _Nullable cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
-
objc_copyClassNamesForImage
获取指定库或框架中的所有类的类名
/**
* Returns the names of all the classes within a library.
*
* @param image The library or framework you are inquiring about.
* @param outCount The number of class names returned.
*
* @return An array of C strings representing the class names.
*/
OBJC_EXPORT const char * _Nonnull * _Nullable
objc_copyClassNamesForImage(const char * _Nonnull image,
unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
eg:
unsigned int outCount1 = 0;
const char **names = objc_copyImageNames(&outCount1);
for (int i = 0; i < outCount1; i ++) {
NSLog(@"所有加载的框架或动态库的名称 -----> %s", names[i]);
}
free(names);
// 所有加载的框架或动态库的名称 -----> /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 10.3.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/introspection/libdispatch.dylib
// 所有加载的框架或动态库的名称 -----> /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 10.3.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/libxpc.dylib
// 所有加载的框架或动态库的名称 -----> /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 10.3.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/libsystem_trace.dylib
// ...
NSLog(@"获取指定类所在的动态库,UIView -----> %s", class_getImageName([UIView class]));
// 获取指定类所在的动态库,UIView -----> /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 10.3.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/UIKit.framework/UIKit
unsigned int outCount5 = 0;
const char ** classNames = objc_copyClassNamesForImage(class_getImageName(NSClassFromString(@"UIView")), &outCount5);
NSLog(@"outCount5 -----> %d", outCount5);
for (int i = 0; i < outCount5; i ++) {
NSLog(@"获取 uiview 中的所有类名 -----> %s", classNames[i]);
}
// outCount5 -----> 2079
// 获取 uiview 中的所有类名 -----> UIGestureKeyboardIntroduction
// 获取 uiview 中的所有类名 -----> _UIPreviewPresentationPlatterView
// 获取 uiview 中的所有类名 -----> UIKeyboardUISettings
// ...
5. block
运行时提供了一些函数支持针对block
的操作
-
imp_implementationWithBlock
创建一个指向函数的指针,当函数被调用时候,执行block
中的操作
参数block
的签名必须是,method_return_type (^)(id self, method_args ...)
形式,该方法能使用block
作为IMP
/**
* Creates a pointer to a function that will call the block
* when the method is called.
*
* @param block The block that implements this method. Its signature should
* be: method_return_type ^(id self, method_args...).
* The selector is not available as a parameter to this block.
* The block is copied with \c Block_copy().
*
* @return The IMP that calls this block. Must be disposed of with
* \c imp_removeBlock.
*/
OBJC_EXPORT IMP _Nonnull
imp_implementationWithBlock(id _Nonnull block)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
eg:
IMP blockImp = imp_implementationWithBlock(^(id obj, NSString *str) {
NSLog(@"imp_implementationWithBlock -----> %@", str);
});
class_addMethod([FFWinterModel class], @selector(testBlock:), blockImp, "v@:@");
[[FFWinterModel new] performSelector:@selector(testBlock:) withObject:@"imp_implementationWithBlock"];
// imp_implementationWithBlock -----> imp_implementationWithBlock
-
imp_getBlock
返回与使用imp_implementationWithBlock
创建的IMP
相关的block
/**
* Return the block associated with an IMP that was created using
* \c imp_implementationWithBlock.
*
* @param anImp The IMP that calls this block.
*
* @return The block called by \e anImp.
*/
OBJC_EXPORT id _Nullable
imp_getBlock(IMP _Nonnull anImp)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
-
imp_removeBlock
解除block
与使用imp_implementationWithBlock
创建的IMP
之前的关联关系,并释放block
的copy
/**
* Disassociates a block from an IMP that was created using
* \c imp_implementationWithBlock and releases the copy of the
* block that was created.
*
* @param anImp An IMP that was created using \c imp_implementationWithBlock.
*
* @return YES if the block was released successfully, NO otherwise.
* (For example, the block might not have been used to create an IMP previously).
*/
OBJC_EXPORT BOOL
imp_removeBlock(IMP _Nonnull anImp)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0);
6. weak
-
objc_loadWeak
加载弱引用指针引用的对象,并返回
该函数加载一个弱指针引用的对象,并在对其做retain
和autoreleasing
操作后返回,这样对象就可以在调用者使用的时候保持足够长的生命周期
该函数可在任何有使用__weak
变量的表达式中使用
/**
* This loads the object referenced by a weak pointer and returns it, after
* retaining and autoreleasing the object to ensure that it stays alive
* long enough for the caller to use it. This function would be used
* anywhere a __weak variable is used in an expression.
*
* @param location The weak pointer address
*
* @return The object pointed to by \e location, or \c nil if \e *location is \c nil.
*/
OBJC_EXPORT id _Nullable
objc_loadWeak(id _Nullable * _Nonnull location)
OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
-
objc_storeWeak
存储__weak
变量的新值,可用于__weak
变量作为赋值对象时候
/**
* This function stores a new value into a __weak variable. It would
* be used anywhere a __weak variable is the target of an assignment.
*
* @param location The address of the weak pointer itself
* @param obj The new object this weak ptr should now point to
*
* @return The value stored into \e location, i.e. \e obj
*/
OBJC_EXPORT id _Nullable
objc_storeWeak(id _Nullable * _Nonnull location, id _Nullable obj)
OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
不定期更新 不合适的地方 还请指点~ 感激不尽
愿祖国繁荣昌盛~
o(* ̄3 ̄)o
网友评论