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

时间:2016-04-22 13:21:06

标签: ios swift generics protocols

我有这个协议:

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

我将TemplateLabel作为UIView从故事板中获取,并尝试将UIView转换为ViewType以将data属性分配给它

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

但我得到错误:

  

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

     

会员'数据'不能用于协议类型'ViewType'的值;使用通用约束

1 个答案:

答案 0 :(得分: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())

我认为你真的不需要任何动态解决方案。您必须知道您要实例化的内容以及可以接收的数据。