在iOS - Swift中的代理模式

5

我需要使用Swift在iOS中创建代理模式。

我已经尝试使用Objective C,以下是代码:

MyProtocol.h

#import <Foundation/Foundation.h>
@protocol MyProtocol <NSObject>
@required
-(void)testMessage;    
@end

TestBO.h

#import <Foundation/Foundation.h>
#import "MyProtocol.h"

@interface TestBO : NSObject <MyProtocol>

@end

TestBO.m

#import "TestBO.h"

@implementation TestBO 

-(void)testMessage{
    NSLog(@"Test Message");
}

@end

TestProxyHandler.h

#import <Foundation/Foundation.h>

@interface TestProxyHandler : NSProxy

@property (nonatomic, strong) id object;

- (instancetype)initWithProtocol:(Protocol *)protocol andObject:(Class)clazz;

- (void)forwardInvocation:(NSInvocation *)invocation;

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector;

@end

TestProxyHandler.m

#import "TestProxyHandler.h"
#import "TestBO.h"

@implementation TestProxyHandler 

- (instancetype)initWithProtocol:(Protocol *)protocol andObject:(Class)clazz{
    if ([clazz conformsToProtocol:@protocol(MyProtocol)]) {
        self.object = [[clazz alloc] init];
    }else{
        NSLog(@"Error it does not conform to protocol");
    }
    return self;
}

- (void)forwardInvocation:(NSInvocation *)invocation{
    NSString *selString = NSStringFromSelector(invocation.selector);
    NSLog(@"Called %@",selString);
    [invocation invokeWithTarget:self.object];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    return [self.object methodSignatureForSelector:selector];
}


@end

我已使用以下方式调用它

id <MyProtocol> delegate = (TestBO *)[[TestProxyHandler alloc] initWithProtocol:@protocol(MyProtocol) andObject:[TestBO class]];

[delegate testMessage];

但是即使初始化程序显示消息,我仍然无法使它在Swift中运行。 TestHandler.swift
import Foundation
class TestHandler: NSProxy {
    var object: AnyObject

    convenience override init(`protocol`: Protocol, andObject clazz: AnyClass) {
        if clazz.conformsToProtocol() {
            self.object = clazz()
        }
        else {
            NSLog("Error it does not conform to protocol")
        }
    }        
}

有人知道如何使用Swift实现这个吗?

编辑:

Java中,您可以使用Proxy.newProxyInstance来创建方法的运行时实现,但是在iOS中是否可以使用Swift实现?有任何线索吗?


嗯?所以关键词可以用 ` 符号指定,无论如何我试过改名字但仍然不起作用。 - Girish Nair
你找到解决方案了吗?如果是的话,如果您能提供它,我将非常感激。 - Ruben
@Ruben:请检查我的答案。 - Girish Nair
1个回答

2
与Objective C和Swift相比,Swift对于运行时语言访问的访问权限非常有限。所以根据我目前的研究,它做不到 :(
我甚至尝试在Swift中使用NSProxy类进行子类化,但是无法调用super.init,代码永远无法编译,然而在Objective C中同样的事情可以实现。
所以我最终采取了这种方法:
我创建了一个协议,使用
@objc protocol SomeProt {
    // Some method
}

请注意,协议前面的关键字@objc是必不可少的,否则您将无法将其作为变量传递。同时,添加@objc限制了协议的使用仅限于Objective-C运行时特性,因此不要期望在Swift中获得协议的所有功能。
public func someMethod(`protocol` : Protocol, implementation : AnyClass) {
    let isImplemented : Bool = implementation.conformsToProtocol(`protocol`)
        // some code
}

如果您需要在某些字典或应该符合 NSCopying 类的地方使用它,则使用

NSStringFromProtocol

NSProtocolFromString

方法

现在我编写了一个Objective-C帮助类来进行初始化

ObjcHelper.h

#import <Foundation/Foundation.h>

@interface ObjcHelper : NSObject
+(NSObject *)objectForClass:(Class)clazz;
@end

ObjcHelper.m

#import "ObjcHelper.h"

@implementation ObjcHelper
+ (NSObject *)objectForClass:(Class)clazz{
    return [[clazz alloc] init];
}
@end

现在我们来使用它。
let prot : SomeProt = ObjcHelper.objectForClass(NSClassFromString("PROT_HANDLER_CLASS_NAME")) as! SomeProt

然而,如果将来有人能够提供更好的答案,请务必在此处发帖。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接