ios – 具有预先实现的委托方法的子类对象

前端之家收集整理的这篇文章主要介绍了ios – 具有预先实现的委托方法的子类对象前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试创建一个NSURLConnection的子类,它已经预先实现了一个委托方法.

我目前的方法是使用一个“代理”委托,它具有预填充此方法调用其他方法,如下所示:

-(BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection{
if ([self.delegate respondsToSelector:@selector(connectionShouldUseCredentialStorage:)]) {
    return [self.delegate connectionShouldUseCredentialStorage:connection];
}
else{
    return NULL;
}

}

delegate是实际用户定义的委托.这会导致某种问题,因为在某些情况下返回NULL会导致操作停止.

这样做的正确方法是什么?

我的类最终应该有一个预先配置的方法调用,其他东西应该由dev实现.

编辑:另一个补充什么是void委托方法的正确方法

Edit2:另一个要求是子类应该像它的父类一样工作,但它必须预先实现一个委托方法.因此开发人员还可以实现NSURLConnection的另一个委托.无法看到如何使用自定义协议

解决方法

你可以做的是编写一个实现respondsToSelector:的NSProxy子类.像这样的东西:

URLConnectionProxyDelegate.h:

#import <Foundation/Foundation.h>

@interface URLConnectionProxyDelegate : NSProxy <NSURLConnectionDelegate>

- (instancetype)initWithDelegate:(id<NSURLConnectionDelegate>)delegate;

@end

URLConnectionProxyDelegate.m:

#import "URLConnectionProxyDelegate.h"

@implementation URLConnectionProxyDelegate
{
    __weak id<NSURLConnectionDelegate> _realDelegate;
}


#pragma mark - Object Lifecycle

- (instancetype)initWithDelegate:(id<NSURLConnectionDelegate>)delegate
{
    if (self) {
        _realDelegate = delegate;
    }
    return self;
}


#pragma mark - NSProxy Overrides

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    return [(id)_realDelegate methodSignatureForSelector:sel];
}

- (void)forwardInvocation:(NSInvocation *)invocation
{
    invocation.target = _realDelegate;
    [invocation invoke];
}


#pragma mark - NSObject Protocol Methods

- (BOOL)respondsToSelector:(SEL)sel
{
    // replace @selector(connection:didFailWithError:) with your actual pre-implemented method's selector
    if (sel == @selector(connection:didFailWithError:)) {
        return YES;
    }

    return [_realDelegate respondsToSelector:sel];
}


#pragma mark - NSURLConnectionDelegate Methods

// Since I don't know which method your pre-implemented method is,// I just chose connection:didFailWithError: as an example. Replace this
// with your actual pre-implemented method.
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"Connection Failed: This gets called only when the proxy delegate is used");
}

@end

然后在你的视图控制器类中使用这个类,你可以这样做:

SomeViewController.m:

#import "SomeViewController.h"
#import "URLConnectionProxyDelegate.h"

@interface SomeViewController () <NSURLConnectionDelegate>

@end


@implementation SomeViewController

#pragma mark - Button actions

- (IBAction)testSuccessURLWithNormalDelegate:(id)sender
{
    NSURL *url = [NSURL URLWithString:@"http://example.com"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    // Using self as the delegate
    [NSURLConnection connectionWithRequest:request delegate:self];
}

- (IBAction)testFailURLWithNormalDelegate:(id)sender
{
    NSURL *url = [NSURL URLWithString:@"not a real url"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    // Using self as the delegate
    [NSURLConnection connectionWithRequest:request delegate:self];
}

- (IBAction)testSuccessURLWithProxyDelegate:(id)sender
{
    NSURL *url = [NSURL URLWithString:@"http://example.com"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    // Using a proxy delegate,with self as the real delegate
    URLConnectionProxyDelegate *proxy = [[URLConnectionProxyDelegate alloc] initWithDelegate:self];
    [NSURLConnection connectionWithRequest:request delegate:proxy];
}

- (IBAction)testFailURLWithProxyDelegate:(id)sender
{
    NSURL *url = [NSURL URLWithString:@"not a real url"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    // Using a proxy delegate,with self as the real delegate
    URLConnectionProxyDelegate *proxy = [[URLConnectionProxyDelegate alloc] initWithDelegate:self];
    [NSURLConnection connectionWithRequest:request delegate:proxy];
}


#pragma mark - NSURLConnectionDelegate Methods

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"Connection Failed: This gets called only when the view controller is used as the delegate");
}

- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
{
    NSLog(@"Connection success: This gets called when the view controller OR the proxy delegate is used as the delegate");

    return YES;
}

@end

关于这一切的重要注意事项是URLConnectionProxyDelegate重写respondsToSelector:并将其传递给它的_realDelegate对象而不是调用super,如果选择器是你的“预实现”方法的选择器,它也总是返回YES.这意味着您甚至不必在NSURLConnectionDelegate协议中实现任何其他方法 – 您只需要实现“预先实现”的方法.

你甚至可以有几个预先实现的方法.只需在代理类的respondsToSelector中为选择器添加更多检查即可轻松完成:

[...]

if (sel == @selector(connection:didFailWithError:)) {
    return YES;
}
if (sel == @selector(connectionShouldUseCredentialStorage:)) {
    return YES;
}

[...]

…然后只是确保在代理类中实现所有这些方法,当然:

[...]

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"pre-implemented connection:didFailWithError:");
}

- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
{
    NSLog(@"pre-implemented connectionShouldUseCredentialStorage:");

    return YES;
}

[...]

希望这是有道理的,对你有所帮助.

猜你在找的iOS相关文章