您的位置:首页 > 其它

OC 动态库的调用包括动态设置属性值,调用方法,设置代理实现代理方法

2016-09-18 14:44 357 查看
最近做了个动态更新模块的功能,是使用动态库来完成的。因为要求动态更新所以就不方便引入头文件了这里就只好采用动态调用动态库的方法了。具体包含以下几个方面:创建对象并设置属性值,调用对象的方法这个方法包括类方法(静态方法)和对象方法,设置对象的代理并实现代理方法。

在一切开始之前我们要先加载动态库这个在前面的博客中有说明的感兴趣的可以去看看。

首先创建对象这个很简单OC中有个方法
NSClassFromString(NSString *aClassName)
,官方解释为:Obtains a class by name,通过类名获取类。然后我们可以通过类创建对象了,这个创建出来的对象是id类型的。

Class FWPayParam = NSClassFromString(className);
_param = [[FWPayParam alloc] init];


对象创建出来了我们要给它赋值,这里我采用的方法是再创建一个类FanWeiPayParam,这个类的属性跟FWPayParam一样然后我们通过对象直接赋值,接下来看具体实现:

- (void)copy:(id)payParam {
//定义无符号int类型
unsigned int outCount,count;
//获取包含指定类公开的属性名地址(不包括这个类的父类属性)的数组,outCount数组长度
objc_property_t *property = class_copyPropertyList([self class], &outCount);
//遍历数组
for (count = 0; count<outCount; count++) {
objc_property_t t = property[count];
//获取属性名
NSString *key = [NSString stringWithUTF8String:property_getName(t)];
//获取属性名对应的属性值
id value = [self valueForKey:key];
//设置属性和属性值
[payParam setValue:value forKey:key];
}
free(property);
}


我们先获取FanWeiPayParam的属性和属性值然后通过
- (void)setValue:(nullable id)value forKey:(NSString *)key
这个方法设置属性值。

属性值设置到这里就完成了,因为代理通常都是作为一个对象属性的比如:

@property (nonatomic,weak) id<FWManagerDelegate> delegate


我们可以采用上面的方法直接给它设置这个属性值,也可以把这个代理属性作为一个函数的传入参数,这个稍后再说。

调用动态库里面的方法我们首先也需要通过类名获取类,在OC里面方法有两种类型一种是类方法类似于其他语言里面的静态方法,还有一种是对象方法。在oc里面对象方法是由对象调用的,类方法是由类调用的但同时我们又常说类也是一个对象它是类对象所以在这里调用动态库的方法时我们都使用下面几个方法无论它是类方法或者是对象方法区别只在于如果是对象方法要先创建一个对象,类方法无需创建对象。

- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;


第一个传入参数是SEL类型的值表示将要调用的函数,后面如果有值都表示将要调用的函数的参数。具体的实现如下:

- (void)thisClass:(NSString *)className performSelector:(NSString *)meth withObject:(id)object1 withObject:(id)object2 {

Class FWPay = NSClassFromString(className);

if ([FWPay respondsToSelector:NSSelectorFromString(meth)]) {

if (object1 != nil && object2 != nil) {
[FWPay performSelector:NSSelectorFromString(meth) withObject:object1 withObject:object2];
return;
}

if (object1 != nil && object2 == nil) {
[FWPay performSelector:NSSelectorFromString(meth) withObject:object1];
return;
}

if (object1 == nil && object2 == nil) {
[FWPay performSelector:NSSelectorFromString(meth)];
return;
}
}
}


接下来看完整的调用吧:

FWInvoke *invoke = [[FWInvoke alloc] initWithParamClass:@"FWPayParam"];
[payParam copy:invoke.param];
[invoke thisClass:@"FWPay" performSelector:@"startPay:delegate:" withObject:invoke.param withObject:self];


上面最后一个参数self就是我们设置的代理对象,至于我们要实现的代理方法直接在代理对象里面实现就可以了,原因很简单我们在使用代理的时候一般都先判断代理对象里面有没有实现代理方法了,如果实现了再使用代理对象调用代理方法。还有下面这种调用:

FWInvoke *invoke = [[FWInvoke alloc] init];
[invoke thisClass:@"FWPay" performSelector:@"applicationWillEnterForeground:" withObject:application withObject:nil];


下面是封装好的动态库调用的代码.h文件

#import <Foundation/Foundation.h>

@interface FWInvoke : NSObject
@property (nonatomic,strong) id param;
- (instancetype)initWithParamClass:(NSString *)className;
-(void)thisClass:(NSString *)className performSelector:(NSString *)meth withObject:(id)object1 withObject:(id)object2;
@end


下面是.m文件

#import "FWInvoke.h"

@implementation FWInvoke

- (instancetype)initWithParamClass:(NSString *)className {
self = [super init];
if (self) {
if (className != nil) {
Class FWPayParam = NSClassFromString(className); _param = [[FWPayParam alloc] init];
}
}
return self;
}

- (void)thisClass:(NSString *)className performSelector:(NSString *)meth withObject:(id)object1 withObject:(id)object2 { Class FWPay = NSClassFromString(className); if ([FWPay respondsToSelector:NSSelectorFromString(meth)]) { if (object1 != nil && object2 != nil) { [FWPay performSelector:NSSelectorFromString(meth) withObject:object1 withObject:object2]; return; } if (object1 != nil && object2 == nil) { [FWPay performSelector:NSSelectorFromString(meth) withObject:object1]; return; } if (object1 == nil && object2 == nil) { [FWPay performSelector:NSSelectorFromString(meth)]; return; } } }@end


限于笔者水平有限这里面会有很多错漏的地方在此抛砖引玉欢迎大家指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  调用动态库