Obj-C to Swift:阻止关闭/委托

时间:2015-08-11 03:59:55

标签: objective-c swift closures objective-c-blocks

保持ViewControllers的精简并使用MVVMC帮助我保持这么简单。 Obj.io有一个非常好的教程site。不幸的是,本教程仅在Objective-C中。

我正在尝试切换到Swift,并且非常迅速地移动,直到我到达用于配置单元格的块。

在教程中,他们创建了一个块typedef

typedef void (^TableViewCellConfigureBlock)(id cell, id item);

在创建单元格时返回cellForRowAtIndexPath中的单元格。

以下是一些代码,这是整个项目:Project

void (^configureCell)(PhotoCell*, Photo*) = ^(PhotoCell* cell, Photo* photo) {
   cell.label.text = photo.name;
};
photosArrayDataSource = [[ArrayDataSource alloc] initWithItems:photos
                        cellIdentifier:PhotoCellIdentifier       
                        configureCellBlock:configureCell];

self.tableView.dataSource = photosArrayDataSource;

cellForRowAtIndexPath

- (UITableViewCell*)tableView:(UITableView*)tableView 
        cellForRowAtIndexPath:(NSIndexPath*)indexPath {
    id cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier
                                              forIndexPath:indexPath];
    id item = [self itemAtIndexPath:indexPath];
    configureCellBlock(cell,item);
    return cell;
}

问题:如何在Swift 1.2+中完成相同的操作?我应该使用closureprotocol delegate等吗?更重要的是,我如何在cellForRowAtIndexPath中调用它?

我是Swift的新手,因此非常感谢解决方案代码。谢谢。

3 个答案:

答案 0 :(得分:4)

您可以在此处使用swift closures。将closureType定义为,

typealias TableViewCellConfigureBlock = (cell : AnyObject , item : AnyObject) -> Void

然后定义closure喜欢,

let configureCellBlock : TableViewCellConfigureBlock = { (cell : PhotoCell, photo : Photo) in

        cell.label.text = photo.name
    } as TableViewCellConfigureBlock

然后在cellForRowAtIndexPath:中,您可以像以前一样使用它,

configureCellBlock(cell: yourCell, item: yourPhotoItem)

答案 1 :(得分:1)

闭包是您使用的而不是块。您可以像在Objective-C中一样在Swift中实现协议。必须从NSObject继承以符合此协议。泛型在这里会很好,但是从Swift 1.2开始,它们不能用于与Objective-C的互操作。

class ArrayDataSource : NSObject, UITableViewDataSource {
    let array: [AnyObject]
    let identifier: String
    let configureCell: (UITableViewCell, AnyObject) -> ()

    init(array: [AnyObject], identifier: String, configureCell: (UITableViewCell, AnyObject) -> ()) {
        self.array = array
        self.identifier = identifier
        self.configureCell = configureCell
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let item: AnyObject = array[indexPath.row]
        let cell = tableView.dequeueReusableCellWithIdentifier(identifier) as! UITableViewCell
        configureCell(cell, item)
        return cell
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return array.count
    }
}

let tableView = UITableView()
tableView.dataSource = ArrayDataSource(array: ["foo", "bar", "baz"], identifier: "foo", configureCell: { (cell, obj) -> () in
    cell.textLabel?.text = "bar"
})

答案 2 :(得分:1)

Swift 2.0 中,您可以使用泛型(如此处所示 - sample github repo),这很容易。

但是在 Swift 1.2 中你需要删除泛型(不能使泛型类继承自objc类型)。请改用协议。这样您就不需要传递单元配置闭包并使用协议的强大功能。

你会这样:

protocol CellDescription {
    var title: String { get }
    var image: UIImage { get }
}

您希望在tableview中显示的模型需要实现协议

class Question: CellDescription {
    var image: Image { 
        return UIImage(named: "whatever")! 
    }
    var title: String {
        return "cell title"
    }
}

然后,您可以UITableViewController使用属性items: [CellDescription],并按照以下方式创建:

class CustomTableViewController: UITableViewController {
    var items: [CellDescription] = []

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier(pickerCell, forIndexPath: indexPath)
        cell.textLabel?.text = items[indexPath.item].title
        cell.imageView?.image = items[indexPath.item].image
        return cell
    }
}
相关问题