【问题标题】:Obj-C to Swift: Block to Closure/DelegateObj-C 到 Swift:阻塞到关闭/委托
【发布时间】:2015-08-11 03:59:55
【问题描述】:

保持 ViewController 精简并使用 MVMC 帮助我更轻松地进行维护。 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 新手,非常感谢您提供解决方案代码。谢谢。

【问题讨论】:

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


    【解决方案1】:

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

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

    然后定义closurelike,

    let configureCellBlock : TableViewCellConfigureBlock = { (cell : PhotoCell, photo : Photo) in
    
            cell.label.text = photo.name
        } as TableViewCellConfigureBlock
    

    那么在cellForRowAtIndexPath:你就可以像以前一样使用了,

    configureCellBlock(cell: yourCell, item: yourPhotoItem)
    

    【讨论】:

    • 我仍然有问题。我将做一个单独的项目并在本周末发布并更新此问题。
    • @user1107173 你能发布问题吗?
    【解决方案2】:

    你使用闭包而不是块。在 Swift 中实现协议就像在 Objective-C 中一样。必须从 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"
    })
    

    【讨论】:

    • 我仍然有问题。我将做一个单独的项目并在本周末发布并更新此问题。
    【解决方案3】:

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

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

    你会这样做:

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

    您想要在表格视图中显示的模型然后需要实现协议

    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
        }
    }
    

    【讨论】:

    • 感谢您的详细回复。我仍然有问题。我将做一个单独的项目并在本周末发布并更新此问题。
    猜你喜欢
    • 2023-04-03
    • 1970-01-01
    • 2015-08-04
    • 2019-06-17
    • 2012-10-11
    • 2019-11-27
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    相关资源
    最近更新 更多