以下代码是用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
答案 0 :(得分:1)
dispatch_block_t
是一个结构,而不是一个对象。实际上它是一个C结构。我不明白为什么你需要使用dispatch_block_t,为什么不只是通过闭包。如果必须将它传递给dispatch_
函数,请将其包装在调用站点的dispatch_block_t中。
为了解决这个问题:
在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])
答案 1 :(得分: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();
}
}
}