Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/121.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何将目标动作转换为块?_Ios_Objective C_Objective C Blocks - Fatal编程技术网

Ios 如何将目标动作转换为块?

Ios 如何将目标动作转换为块?,ios,objective-c,objective-c-blocks,Ios,Objective C,Objective C Blocks,我在一个类中有以下选择器: - (SoapRequest*) loginAndConnect: (id) target action: (SEL) action credentials: (WSAcredentials*) arg0 dialoutInfo: (WSAdialoutInfo*) arg1; 我希望能够使用一个块而不是另一个选择器来调用它作为操作,但我找不到有关如何执行此操作的信息。比如: [service loginAndConnect:self credential

我在一个类中有以下选择器:

    - (SoapRequest*) loginAndConnect: (id) target action: (SEL) action credentials: (WSAcredentials*) arg0 dialoutInfo: (WSAdialoutInfo*) arg1;
我希望能够使用一个块而不是另一个选择器来调用它作为操作,但我找不到有关如何执行此操作的信息。比如:

[service loginAndConnect:self  credentials:credentials dialoutInfo:dialoutInfo action:^(SoapRequest* aResult) {
    // more code here
}];
实现这一目标的最佳方式是什么

更新**

我几乎可以做到这一点,但在objc_发布版中,completionBlock对象出现了一个异常。我确信这与保留目标有关,但我不确定如何纠正它。以下是当前代码:

- (BOOL) checkService {

WSAcredentials* credentials = [[WSAcredentials alloc] init];
WSAdialoutInfo* dialoutInfo = [[WSAdialoutInfo alloc] init];
if (!service) {
    service = [[WSAWebSocketAdapterService alloc] init];
}
__block SoapRequest* request;
[service loginAndConnectWithCredentials:credentials dialoutInfo:dialoutInfo completionBlock:^(SoapRequestCompletionBlock completionBlock) {
        request = (SoapRequest*)completionBlock;
        if ([request isKindOfClass: [SoapFault class]]) {                
            return YES; // we got a response, that's all we care about
        }
    return NO;
}
];
return YES;
}
这是我的分类,非常接近下面发布的内容:

#import "WSAWebSocketAdapterService+BlockExtension.h"

// These objects serve as targets (with action being completed:) for the original object.
// Because we use one for each request we are thread safe.

@interface MyCustomSoapTargetAction : NSObject 

@property (copy) SoapRequestCompletionBlock block;

- (void) completed:(id)sender;

@end

@implementation MyCustomSoapTargetAction
- (void) completed:(id)sender
{
// Assuming 'sender' is your SoapRequest
if (_block != nil)
    _block(sender);
_block = nil;
}
@end

@implementation WSAWebSocketAdapterService(BlockExtension)

- (SoapRequest*) loginAndConnectWithCredentials:(WSAcredentials*) arg0
                                dialoutInfo: (WSAdialoutInfo*) arg1
                            completionBlock:(BOOL (^)(SoapRequestCompletionBlock))completionBlock
{
MyCustomSoapTargetAction *target = [[MyCustomSoapTargetAction alloc] init];
target.block = (SoapRequestCompletionBlock) completionBlock;

//
// Here we assume that target will be retained.
// If that's not the case then we will need to add it to some collection before
// the call below and have the target object remove itself from it after its
// block has been called.
//
return [self loginAndConnect:target action:@selector(completed:) credentials:arg0 dialoutInfo:arg1];
}
@end

谢谢你的帮助

您有权访问该类的源代码吗?生成一个接受块而不是选择器的类似方法将是一个相当简单的重写

AFNetworking库是这类东西的一个很好的风格指南。您的方法可能与此类似:

+ (instancetype)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest
                                        success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success
                                        failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON))failure;

或者,您可以使用此处演示的方法通过一个类别添加您的方法:

您有权访问该类的源吗?生成一个接受块而不是选择器的类似方法将是一个相当简单的重写

AFNetworking库是这类东西的一个很好的风格指南。您的方法可能与此类似:

+ (instancetype)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest
                                        success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success
                                        failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON))failure;

或者,您可以使用此处演示的方法,通过一个类别添加您的方法:

您实际上不需要源代码。一个类别就可以了。下面是一些示例代码,让您开始学习, 这甚至是线程安全的!如果您的对象没有保留目标,那么在调用其块之前,还有一点工作要做,以保持目标

// -- TheClassName+BlockExtension.h

typedef void (^SoapRequestCompletionBlock)(SoapRequest*);

@interface TheClassName(BlockExtension)
- loginAndConnectWithCredentials:(WSAcredentials*) arg0 
                     dialoutInfo: (WSAdialoutInfo*) arg1;
                 completionBlock:(SoapRequestCompletionBlock)completionBlock;
@end


// -- TheClassName+BlockExtension.m

// EDITED: If the 'target' object is not retained by the loginAndConnect... then
//         we may add it to this collection. In this implementation, a block can
//         only be used once.

static NSMutableSet *gSoapTargets = nil;

// These objects serve as targets (with action being completed:) for the original object.
// Because we use one for each request we are thread safe.

@interface MyCustomSoapTargetAction
@property (copy) SoapRequestCompletionBlock block;
- (void) completed:(id)sender;
@end

@implementation MyCustomSoapTargetAction

- (id) init
{
    // Objects adds itself to the global collection
    if ((self = [super init]))
        [gSoapTargets addObject:self];
    return self;
}

- (void) completed:(id)sender
{
    // Assuming 'sender' is your SoapRequest
    if (_block != nil)
        _block(sender);

    // Object removes itself from global collection when done.
    // On return from this method it will likely be released.
    [gSoapTargets removeObject:self];
}

+ (void) load 
{
    gSoapTargets = [NSMutableSet set];
}

@end

@implementation TheClassName(BlockExtension)
- (SoapRequest*) loginAndConnectWithCredentials:(WSAcredentials*) arg0 
                                    dialoutInfo: (WSAdialoutInfo*) arg1;
                                completionBlock:(SoapRequestCompletionBlock)completionBlock
{
    MyCustomSoapTargetAction *target = [[MyCustomSoapTargetAction alloc] init];
    target.block = completionBlock;

    //
    // Here we assume that target will be retained.
    // If that's not the case then we will need to add it to some collection before
    // the call below and have the target object remove itself from it after its 
    // block has been called.
    //
    [self loginAndConnect:target action:@selector(completed:) credentials:arg0 dialoutInfo:arg1];
}
@end
*更新:下面是一个基于代码使用此类别的示例:

- (BOOL) serviceIsAvailable 
{
    return _serviceIsAvailable;
}

- (void) _setServiceIsAvailable:(BOOL)value 
{
    // This method should probably be private thus the _ prefix
    // Do something with the result (set some status, warn user...).
    _serviceIsAvailable = value;
}

- (void) checkService 
{
    WSAcredentials* credentials = [[WSAcredentials alloc] init];
    WSAdialoutInfo* dialoutInfo = [[WSAdialoutInfo alloc] init];

    if (_service == nil)
        _service = [[WSAWebSocketAdapterService alloc] init];

    [_service loginAndConnectWithCredentials:credentials 
                                 dialoutInfo:dialoutInfo 
                             completionBlock:^(id sender) 
    {
        [self _setServiceIsAvailable:[sender isKindOfClass:[SoapFault class]]];
    }];
}

实际上,您不需要源代码。一个类别就可以了。下面是一些示例代码,让您开始学习, 这甚至是线程安全的!如果您的对象没有保留目标,那么在调用其块之前,还有一点工作要做,以保持目标

// -- TheClassName+BlockExtension.h

typedef void (^SoapRequestCompletionBlock)(SoapRequest*);

@interface TheClassName(BlockExtension)
- loginAndConnectWithCredentials:(WSAcredentials*) arg0 
                     dialoutInfo: (WSAdialoutInfo*) arg1;
                 completionBlock:(SoapRequestCompletionBlock)completionBlock;
@end


// -- TheClassName+BlockExtension.m

// EDITED: If the 'target' object is not retained by the loginAndConnect... then
//         we may add it to this collection. In this implementation, a block can
//         only be used once.

static NSMutableSet *gSoapTargets = nil;

// These objects serve as targets (with action being completed:) for the original object.
// Because we use one for each request we are thread safe.

@interface MyCustomSoapTargetAction
@property (copy) SoapRequestCompletionBlock block;
- (void) completed:(id)sender;
@end

@implementation MyCustomSoapTargetAction

- (id) init
{
    // Objects adds itself to the global collection
    if ((self = [super init]))
        [gSoapTargets addObject:self];
    return self;
}

- (void) completed:(id)sender
{
    // Assuming 'sender' is your SoapRequest
    if (_block != nil)
        _block(sender);

    // Object removes itself from global collection when done.
    // On return from this method it will likely be released.
    [gSoapTargets removeObject:self];
}

+ (void) load 
{
    gSoapTargets = [NSMutableSet set];
}

@end

@implementation TheClassName(BlockExtension)
- (SoapRequest*) loginAndConnectWithCredentials:(WSAcredentials*) arg0 
                                    dialoutInfo: (WSAdialoutInfo*) arg1;
                                completionBlock:(SoapRequestCompletionBlock)completionBlock
{
    MyCustomSoapTargetAction *target = [[MyCustomSoapTargetAction alloc] init];
    target.block = completionBlock;

    //
    // Here we assume that target will be retained.
    // If that's not the case then we will need to add it to some collection before
    // the call below and have the target object remove itself from it after its 
    // block has been called.
    //
    [self loginAndConnect:target action:@selector(completed:) credentials:arg0 dialoutInfo:arg1];
}
@end
*更新:下面是一个基于代码使用此类别的示例:

- (BOOL) serviceIsAvailable 
{
    return _serviceIsAvailable;
}

- (void) _setServiceIsAvailable:(BOOL)value 
{
    // This method should probably be private thus the _ prefix
    // Do something with the result (set some status, warn user...).
    _serviceIsAvailable = value;
}

- (void) checkService 
{
    WSAcredentials* credentials = [[WSAcredentials alloc] init];
    WSAdialoutInfo* dialoutInfo = [[WSAdialoutInfo alloc] init];

    if (_service == nil)
        _service = [[WSAWebSocketAdapterService alloc] init];

    [_service loginAndConnectWithCredentials:credentials 
                                 dialoutInfo:dialoutInfo 
                             completionBlock:^(id sender) 
    {
        [self _setServiceIsAvailable:[sender isKindOfClass:[SoapFault class]]];
    }];
}

“用块调用”是什么意思?您只需将“操作”块传递给您的函数,并确定它是否/何时应在其中运行。什么是“用块调用”?您只需传递“操作”块,并确定是否/何时应在其内部运行。或仅一个包含错误和结果的块,其中只有一个是非
nil
我有源代码,但它是自动生成的,因此我不想修改它。谢谢你的链接。或者只是一个包含错误和结果的块,其中只有一个是非
nil
我有源代码,但它是自动生成的,所以我不想修改它。谢谢你的链接。我还在
completed:
的末尾将
\u block
属性设置为nil,以避免潜在的内存泄漏。对于完成区块,执行此服务后,没有理由需要继续保留它。将_block设置为nil不需要花费任何费用,因此我们可以继续执行此操作,尽管在ARC环境中,这是不必要的,因为当对象被释放时,块将被释放。@aLevelOfIndirection您能否解释一下有关保留此对象的更多信息目标?我就快到了,但有一个例外,我确信这与此有关。我已经用当前代码更新了原始帖子。谢谢如果调用loginAndConnect的对象在调用块时没有保留目标,则MyCustomSoapTargetAction的实例将被释放。我将编辑我的帖子来处理这种情况。我还将
\u block
属性在
completed:
末尾设置为nil,以避免潜在的内存泄漏。对于完成区块,执行此服务后,没有理由需要继续保留它。将_block设置为nil不需要花费任何费用,因此我们可以继续执行此操作,尽管在ARC环境中,这是不必要的,因为当对象被释放时,块将被释放。@aLevelOfIndirection您能否解释一下有关保留此对象的更多信息目标?我就快到了,但有一个例外,我确信这与此有关。我已经用当前代码更新了原始帖子。谢谢如果调用loginAndConnect的对象在调用块时没有保留目标,则MyCustomSoapTargetAction的实例将被释放。我会编辑我的帖子来处理这个案子。