在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:gozelus/iOSReview开源软件地址:https://github.com/gozelus/iOSReview开源编程语言:开源软件介绍:严禁转载!
一、对象内存模型
Runtimereference:objc runtime
Categotyreference:美团技术博客:深入理解Objective-C:Category categoty 简介
categoty 类比 extension
categoty 内存结构typedef struct `categoty`_t {
const char *name;
classref_t cls;
struct method_list_t *instanceMethods;
struct method_list_t *classMethods;
struct protocol_list_t *protocols;
struct property_list_t *instanceProperties;
} `categoty`_t; 我们知道,所有的
category 的加载
需要注意的时, 根据这个原理,我们可以得知,如果有多个类别中同时都复写了类中的某个方法,那么最终调用的是最后被加载的 category 中 Load 方法
category 与关联对象由于 #import "MyClass+Category1.h"
#import <objc/runtime.h>
@implementation MyClass (Category1)
+ (void)load
{
NSLog(@"%@",@"load in Category1");
}
- (void)setName:(NSString *)name
{
objc_setAssociatedObject(self,
"name",
name,
OBJC_ASSOCIATION_COPY);
}
- (NSString*)name
{
NSString *nameObject = objc_getAssociatedObject(self, "name");
return nameObject;
}
@end 关联对象存储在一张全局的 KVO
App 启动Load 与 InitializeLoad
值得第一提的是, Initialize与 值得注意的点是:类初始化的时候每个类只会调用一次 无论是重写 BlockBlock 基本原理int main() {
void (^blk)(void) = ^{
(printf("hello world!"));
};
blk();
return 0;
} 如上,通过 // block 的真面目
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
// ..... 一大坨无关代码
// 通过这个结构体包装block,用于快速构造block
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
(printf("hello world!"));
}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main() {
void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
return 0;
} 比较核心的是以下内容:
由此我们可知,上述一个简单的
至此,一个简单的 __block 捕获原理
int main() {
int a = 1;
void (^blk)(void) = ^{
printf("%d", a);
};
blk();
return 0;
} 经过 struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int a;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int a = __cself->a; // bound by copy
printf("%d", a);
}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main() {
int a = 1;
void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a));
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
return 0;
} 经过上一节的讨论,我们知道代码块是由 由于构造函数的参数为整形,在 如果想要在内部修改 int main() {
__block int number = 1;
void (^blk)(void) = ^{
number = 3;
printf("%d", number);
};
blk();
return 0;
} struct __Block_byref_number_0 {
void *__isa;
__Block_byref_number_0 *__forwarding;
int __flags;
int __size;
int number;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__Block_byref_number_0 *number; // by ref
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_number_0 *_number, int flags=0) : number(_number->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
__Block_byref_number_0 *number = __cself->number; // bound by ref
(number->__forwarding->number) = 3;
printf("%d", (number->__forwarding->number));
}
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->number, (void*)src->number, 8/*BLOCK_FIELD_IS_BYREF*/);}
static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->number, 8/*BLOCK_FIELD_IS_BYREF*/);}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
int main() {
__attribute__((__blocks__(byref))) __Block_byref_number_0 number = {(void*)0,(__Block_byref_number_0 *)&number, 0, sizeof(__Block_byref_number_0), 1};
void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_number_0 *)&number, 570425344));
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
return 0;
} 可以看到整形 上节提到,构造函数中的参数是值拷贝,故此处代码块内部拿到的指针拷贝一样可以操作外部的 block 引起的循环引用原理RunLoopreference:深入理解Runloop Runloop 基本原理一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。如果我们需要一个机制,让线程能随时处理事件但并不退出,通常的代码逻辑是这样的: function loop() {
initialize();
do {
var message = get_next_message();
process_message(message);
} while (message != quit);
} 在 /// 全局的Dictionary,key 是 pthread_t, value 是 CFRunLoopRef
static CFMutableDictionaryRef loopsDic;
/// 访问 loopsDic 时的锁
static CFSpinLock_t loopsLock;
/// 获取一个 pthread 对应的 RunLoop。
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论