我正在研究依赖注入(inject),目前正在更新我的项目以利用它。但是,我在关联类型和协议(protocol)符合方面遇到了问题。
我创建了一个快速演示项目,并创建了一些协议(protocol)和扩展,以便符合我的协议(protocol) ViewModelBased 的 View Controller 必须实现关联类型。理想情况下,我希望此关联类型符合 viewModel。这是我目前所拥有的
protocol ViewModel {
associatedtype Services
init (withServices services: Services)
}
protocol ViewModelBased: class {
associatedtype ViewModelType
var viewModel: ViewModelType { get set }
}
extension ViewModelBased where Self: UIViewController{
static func instantiateController(with viewModel : ViewModelType) -> Self {
// I have created UIStoryboard extension to allow for easy opening of view controllers
// in storyboard
let viewController : Self = UIStoryboard.mainStoryboard.instantiateViewController()
viewController.viewModel = viewModel
return viewController
}
}
所以我的应用程序中的所有 viewModel 都符合 ViewModel,这迫使它们实现服务类型。例如,我的 LoginModel 看起来像这样
struct LoginModel : ViewModel{
// service type
typealias Services = LoginService
// init service
var services : LoginService
init(withServices services: LoginService) {
self.services = services
}
/// calls login service - attempts login api
func attemptLogin() {
services.login()
}
}
所以这里有一个实现这个的 viewController 的例子
class SecondController: UIViewController, ViewModelBased {
var viewModel: LoginModel!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func loginTest() {
viewModel.services.onLoginSuccess = { isVerified in
print(isVerified)
}
viewModel.services.onLoginFailure = { errorCode in
print(errorCode)
}
viewModel.attemptLogin()
}
}
所以把它们放在一起,这允许应用程序像这样初始化一个 viewController 并传入一个 viewModel
let loginModel = LoginModel(withServices: LoginService())
let controller = SecondController.instantiateController(with: loginModel)
self.navigationController?.pushViewController(controller, animated: true)
这一切都很好,但我遇到的问题是,关联的类型目前可以是任何类型。理想情况下,我希望此 associatedType 符合 ViewModel 协议(protocol)。但是当我尝试这个时
protocol ViewModelBased: class {
associatedtype ViewModelType : ViewModel
var viewModel: ViewModelType { get set }
}
我的 SecondController 现在抛出错误并强制我初始化 LoginModel
var viewModel : LoginModel = LoginModel(withServices: LoginService())
但这不再使用依赖注入(inject),因为 viewController 现在负责创建 viewModel 实例并了解 viewModel 类的行为。
有什么办法可以解决这个问题吗?如果有人能给我一些关于我做错了什么的信息,我将不胜感激。
最佳答案
您可以扩展 Optional 以有条件地符合 ViewModel:
extension Optional: ViewModel where Wrapped: ViewModel {
typealias Services = Wrapped.Services
init(withServices services: Services) {
self = Wrapped(withServices: services)
}
}
现在您的 SecondController 将其模型声明为 var viewModel: LoginModel?,默认情况下将其初始化为 nil,同时仍确保其ViewModelType 是一个 ViewModel,实际上不需要创建它的实例。
关于swift - 关联类型符合协议(protocol)和依赖注入(inject)问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49938246/
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
由于fast-stemmer的问题,我很难安装我想要的任何rubygem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub