分类存档: iOS/Objective-C

Objective-C Runtime

一、简介

Runtime,Objecive-c运行时,一套底层C语言的API。
我们平常写的OC底层都是基于Runtime来实现的, 例如:

//注意使用以下代码,请在xcode工程设置中找到Enable Strict Checking of objc_msgSend Calls并关闭该选项。
[self tryUpgradeApp];
//其实会转化为
objc_msgSend(self, @selector(tryUpgradeApp));

//如有参数:
[self tryUpgradeApp:arg1...];
//则转为
objc_msgSend(self, @selector(tryUpgradeApp), arg1, ...);

消息是直到运行的时候才和方法实现绑定的,编译器会把一个消息表达式转化成一个objc_msgSend的调用,该方法主要参数有消息接受者和方法标号,同时有可变参数可以接受相应的参数。

多数情况下开发者只需要编写objc代码即可,编译器会将objc代码转为runtime代码,在运行时确定数据结构和函数。

@implementation TestCls

+(instancetype) create
{
   TestCls* instance = [[[self class] alloc] init];
    [instance onCreate];
    return instance;
}

-(void) onCreate{
    NSLog(@"onCreate >> in >>");
}

@end

执行以下命令得到一个cpp文件。

clang -rewrite-objc TestCls.m 

生成的文件很大我们只看以下内容,从下代码可以看到,实际上objc的方法调用都是用过objc_msgSend消息机制实现的。

static __NSConstantStringImpl __NSConstantStringImpl__var_folders__9_4xdmxtdd1sv16b8cry0qlxzm0000gn_T_TestCls_b47c1a_mi_0 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"onCreate >> in >>",17};

static instancetype _C_TestCls_create(Class self, SEL _cmd) {
   TestCls* instance = ((id (*)(id, SEL))(void *)objc_msgSend)((id)((id (*)(id, SEL))(void *)objc_msgSend)((id)((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class")), sel_registerName("alloc")), sel_registerName("init"));
    ((void (*)(id, SEL))(void *)objc_msgSend)((id)instance, sel_registerName("onCreate"));
    return instance;
}

static void _I_TestCls_onCreate(TestCls * self, SEL _cmd) {
    NSLog((NSString *)&__NSConstantStringImpl__var_folders__9_4xdmxtdd1sv16b8cry0qlxzm0000gn_T_TestCls_b47c1a_mi_0);
}

二、runtime的数据结构

// 参考 objc/objc.h 

// id 
struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;



//sel
typedef struct objc_selector *SEL;

// class
typedef struct objc_class *Class;

struct objc_class {
    //class中也有一个isa指针指向所属的元类
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
   //指向父类
    Class super_class                                        OBJC2_UNAVAILABLE;
   //类名
    const char *name                                         OBJC2_UNAVAILABLE;
   //类的版本信息
    long version                                             OBJC2_UNAVAILABLE;
   //信息
    long info                                                OBJC2_UNAVAILABLE;
   //实例大小
    long instance_size                                       OBJC2_UNAVAILABLE;
   //成员变量列表
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
   //成员方法列表
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
   //系统调用的方法会缓存到cache中使调下次调用效率更高
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
   //该类实现的协议列表
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

继续阅读 »

iOS 从URL启动App与openURL

目标:

1、从URL启动自己或别人的App
2、传递数据

说明:

这是一个非常常用的功能,在一些第3方SDK中也常用集成如跳转到朋友圈分享微信支付,以及调回来之后的处理等。我们看下怎么实现:

实现:

继续阅读 »

iOS开发 UniversalLinks支持通用链接。

介绍

UniversalLinks 是iOS9退出的一个新特性,其作用为离开传统的scheme://方式外也可以启动app,方便在h5中调用app。(原https网页中 如采用iframe方式 调起app ,但https中的iframe.src应为https地址,故而对scheme://方式的兼容性并不到位。如为http方则没有这个问题)。

作用:
1、在浏览器(safari)中H5中将加上“打开app”的按钮。
2、允许再微信等app中启动自己的app (本人实测微信中不是所有情况都可以)

实现步骤:(下列苹果开发者文章中有详细的介绍,我这边再做简单的介绍)
继续阅读 »

iOS 并发队列

一、GCD

GCD是apple开发中并发队列(多线程)的一个解决方案。他主要用于优化应用程序以支持多核处理器。GCD用非常简洁的方法,实现极为复杂的多线程编程。GCD是纯C的api 在ios4.0时推出。
例如

 dispatch_async(dispatch_get_global_queue(0, 0), ^{
       //在子线程执行的代码,长时间处理
        
        dispatch_async(dispatch_get_main_queue(), ^{
                //主线程刷新UI
        });
    });

上述代码中,将需要长时间运行的操作代码放入子线程,执行完毕后回到主线程继续使用。

一、GCD队列
继续阅读 »

iOS 第三方库 Mantle

 

Mantle 主要是简化ios中model层的第三方库,我们在项目中大量的定义和使用model,而Mantle所做的就是让我们更方便的使用model。 Mantle 目前也是我们通讯框架中最要的组成部分

直接上代码吧

HVProjectInfoModel.h

#import <Mantle/Mantle.h>
@class HVVenueWeekTimesModel;

@interface HVProjectInfoModel : MTLModel <MTLJSONSerializing>

// projectid 项目id
  //(String)
@property(nonatomic, strong) NSString* projectid;

// 项目名称
  //(String)
@property(nonatomic, strong) NSString* projectName;

//  //(List)
@property(nonatomic, strong) NSArray<HVVenueWeekTimesModel*>* scene;


+ (HVProjectInfoModel*) modelFromDictionary:(NSDictionary*)dict;

+ (NSArray<HVProjectInfoModel*>*) modelsFromArray:(NSArray<NSDictionary*>*)array;

- (NSDictionary*) dictionary;

@end

MTLJSONSerializing协议包含了一下内容

@protocol MTLJSONSerializing 
@required
+ (NSDictionary *)JSONKeyPathsByPropertyKey;
@optional
+ (NSValueTransformer *)JSONTransformerForKey:(NSString *)key;
+ (Class)classForParsingJSONDictionary:(NSDictionary *)JSONDictionary;
@end

继续阅读 »