1

以下代码是用 Swift 2.0 编写的,用于创建一个数组dispatch_block_t

let a: dispatch_block_t = {
    self.pickImages()
}
let b: dispatch_block_t = {
    self.takePicture()
}
let c: dispatch_block_t = {
    self.pickVideos()
}
let d: dispatch_block_t = {
    self.shootVideo()
}
let e: dispatch_block_t = {
    self.recordAudio()
}
let f: dispatch_block_t = {
    self.closeView()
}

let block1 = Block(block: a)
let block2 = Block(block: b)
let block3 = Block(block: c)
let block4 = Block(block: d)
let block5 = Block(block: e)
let block6 = Block(block: f)

let actionsArray: NSArray = [block1, block2, block3, block4, block5, block6]

该类Block定义如下,

class Block: NSObject, NSCopying {
    var block: dispatch_block_t

    init(block: dispatch_block_t){
        self.block = block
    }

    func copyWithZone(zone: NSZone) -> AnyObject {
        return self.block as! AnyObject
    }
}

我可以使用上面的代码创建一个 dispatch_block_t 数组。但是,我需要将此数组作为参数传递给另一个函数,并且在传递此数组时遇到问题。

我在按钮单击事件上调用此函数,

menuView = btSimplePopUP(itemImage: imgs as [AnyObject],
    andTitles: titles as [AnyObject],
    andActionArray:  actionsArray as [AnyObject],
    addToViewController: self) 

执行以下代码段时出现错误,

- (instancetype)initWithImage:(UIImage *)image title:(NSString *)title action:(dispatch_block_t)action {
if ((self = [super init])) {
    _title = [title copy];
    _imageView = [[UIImageView alloc]initWithImage:image];
    _action = [action copy];
}

return self;
}

错误是,

无法将类型“()->()”(0x15164018)的值转换为“Swift.AnyObject”(0x101e500c)。

我在类copyWithZone函数中收到此错误Block

btSimplePopUp 的完整源代码可以在这里查看, https://github.com/balram3429/btSimplePopUp/blob/master/btSimplePopUp/btSimplePopUP.m

4

2 回答 2

1

dispatch_block_t是一个结构,而不是一个对象。事实上,它是一个 C 结构。我不明白你为什么需要使用 dispatch_block_t,为什么不直接传递闭包。如果您必须将其传递给dispatch_函数,请将其包装在调用站点的 dispatch_block_t 中。

要 Swiftify 这个:

在 Swift 中,dispatch_block_t它只是一个别名,() -> ()即返回的 void 函数/闭包Void。所以你可以简单地说

let a = { self.pickImages() }
// etc

let actionArray = [ a, b, c, ...]

但是,pickImages它是一个具有相同类型的函数(从技术上讲,它被柯里化了,self但不用担心这意味着什么),因此您可以忘记 a、b、c 位并执行此操作

let actionArray = [ self.pickImages, self.takePhoto, ... ]

在 Swift 中,只要你有一个参数,你就可以使用该数组中的一个“对象”,dispatch_block_t例如

dispatch_after(someTime, dispatch_get_main_queue(), actionArray[0])
于 2015-11-13T08:50:41.390 回答
0

您需要修改您的 Objc 框架。您的 btSimplePopUP 应该像此示例中的 ActionContainer 一样工作。ActionObject 是 Swift dispatch_block_t 的盒装版本。如何在您的代码中拆箱?请参阅 ActionContainer 作业功能。

//
//  Actions.h
//  test
//


#ifndef Actions_h
#define Actions_h
#import <Foundation/Foundation.h>

@interface ActionObject : NSObject
@property (nonatomic, copy) dispatch_block_t action;
@end


@interface ActionContainer : NSObject
@property  NSArray * actions;
-(void)job;
@end

#endif /* Actions_h */

...

//
//  Actions.m
//  test
//


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


@implementation ActionObject

-(instancetype)initWithAction: (dispatch_block_t)someaction {
    if ((self = [super init])) {
        _action = [someaction copy];
    }
    return self;
}

@end

@implementation ActionContainer
-(void)job {
    if (_actions != nil) {
        NSUInteger count = _actions.count;
        NSUInteger i;
        for (i = 0; i < count; i++) {
            ActionObject *action = _actions[i];
            action.action();
        }

    }
}

@end

...

//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//

#import "Actions.h"

...

//
//  main.swift
//  test
//


import Foundation

let a = ActionObject()
a.action = {
    print("swift a action")
}
let b = ActionObject()
b.action = {
    print("swift b action")
}
let arr: NSArray = [a,b]

let actions = ActionContainer()
actions.actions = arr as [AnyObject]
actions.job()

生产

swift a action
swift b action
Program ended with exit code: 0

...

@implementation ActionContainer
-(void)job {
    if (_actions != nil) {
        NSUInteger count = _actions.count;
        NSUInteger i;
        for (i = 0; i < count; i++) {
            ActionObject *action = _actions[i];
            // myAction is 'unboxed' swift block
            // you can save it, run it
            // somwhere in you ObjectiveC code
            dispatch_block_t myAction = action.action;
            // run it
            myAction();
        }

    }
}
于 2015-11-13T09:59:56.500 回答