协议只能用作通用约束,因为它具有Self或关联类型要求。

3

我有这个协议:

protocol ViewType {
    associatedtype T: ViewData.View
    var data:T! {get set}
}

ViewData.View 是一个类。

我有一个名为 TemplateLabel 的类,它继承自 UILabel 并符合 ViewType

class TemplateLabel:UILabel, ViewType {
    var data: ViewData.View.Label!
}

我从Storyboard中获取了一个TemplateLabel作为UIView,并尝试将UIView转换为ViewType以将data属性分配给它。

let view = SB.instantiateViewControllerWithIdentifier("view_label").view
if var v = view as? ViewType { // Error
    v.data = data // Error
}

但是我遇到了错误:

协议“ViewType”只能用作通用约束,因为它具有自我或关联类型要求

成员“data”不能用于“ViewType”协议类型的值;而应该使用通用约束


1
你应该转换为特定的实现,而不是约束协议。转换为 TemplateLabel。并且要在 Swift 中了解更多关于协议的内容 :) - werediver
然后你需要一个通用的方法...我可以展示一个例子(几分钟内)。另一种方法是陷入类型擦除,但我认为那太深奥了。 - werediver
那太好了,这正是我想要做的,一个通用的方法 x) - Arbitur
1
嗯,我错了。通用方法无法解决这种问题,因为通用方法在编译时针对特定类型进行实例化,但是除非将其强制转换为特定实现,否则在编译时无法确定对象类型。 - werediver
1
观看Rob Napier的演讲,以了解这个问题的见解- http://www.thedotpost.com/2016/01/rob-napier-beyond-crusty-real-world-protocols - Shripada
显示剩余3条评论
1个回答

1
我有一个答案给你,但那只是裸代码。我认为它在定义的上下文中可以非常有用。
import UIKit

// Framework

/**
 * Intended usage:
 *
 *     enum AppStoryboard: BundledStoryboard {
 *
 *         case Login
 *         case Main
 *
 *         var storyboard: UIStoryboard {
 *             return UIStoryboard(name: "\(self)", bundle: nil)
 *         }
 *
 *     }
 */
protocol BundledStoryboard {

    var storyboard: UIStoryboard { get }

}

protocol StoryboardViewController {

    static var bundledStoryboard: BundledStoryboard { get }
    static var storyboardId: String { get }

    static func instantiateFromStoryboard() -> Self

}

extension StoryboardViewController {

    static var storyboardId: String { return "\(self)" }

    static func instantiateFromStoryboard() -> Self {
        return bundledStoryboard.storyboard.instantiateViewControllerWithIdentifier(storyboardId) as! Self
    }

}

// Application specific

enum AppStoryboard: BundledStoryboard {

    //case Login
    case Main

    var storyboard: UIStoryboard {
        return UIStoryboard(name: "\(self)", bundle: nil)
    }

}

extension StoryboardViewController {

    static var bundledStoryboard: BundledStoryboard { return AppStoryboard.Main }

}

// View-Model relation

protocol ViewType {

    associatedtype Model

    func loadModel(m: Model)

}

// ViewController

final class ViewController: UIViewController, StoryboardViewController, ViewType {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func loadModel(m: UIColor?) {
        view.backgroundColor = m // Strange example, yeah.
    }

}

// Then somewhere...

let vc = ViewController.instantiateFromStoryboard()
vc.loadModel(.redColor())

我认为在这里你并不需要任何动态解决方案。你必须知道你正在实例化什么以及它可以接收哪些数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接