JSAUIKitCocoa是为使用JavaScript混合Objective-C开发iOS应用提供的MVC框架,以及为部分原生UI组件(如UIView)提供JavaScript快速初始化支持。使用JSAUIKitCocoa,你能够方便的使用JavaScript来编写iOS应用的显示层业务逻辑,以及实现显示层业务逻辑的动态下发。javascript
咱们将用JavaScript和MMVVC模式建立这样一个应用界面java
用户进入登陆页面时,显示最后一次登陆的用户信息,用户修改用户名后,头像中的名称显示当前用户名(真实场景应该会改变头像图片)git
$class("app.UserManagerModel",{ $static:{ lastloginUser:function(){ return { username:"UserA", password:"password" } } } });
lastloginUser方法返回最后一次登陆的用户信息,即Domain-value Object。github
$class("app.AvatarView",{ $init : function(param){ this.textView = $new("UILabel","initWithJSAParam:",{ fontSize:12, textColor:"#FFFFFF", textAlignment:"center" }); var avatarView = $new("MyRelativeLayout","initWithJSAParam:",Object.assign(param,{ backgroundColor:"#03A9F4", subviews:[ { view:this.textView, leftPos:5, topPos:5, rightPos:5, bottomPos:5, } ] })); //这里是一个小技巧,将一个非OC代理对象转换为OC代理对象,以便该对象传递到OC系统时转换为OC对象 this.$this = avatarView.$this; }, setName:function(name){ name = name.trim(); if(name == ""){ name = "Unknown"; } this.textView.invoke("setText:",name); } });
用户头像是一个ModelView,即和业务逻辑相关的View,这个View将显示用户头像,并能够从新设置用户名(setName方法),setName方法在此DEMO实现中只是将头像中的文本设置为新的名字,真实业务场景能够调用Model层方法获取用户名对应的图片,而后修改头像图片。相比ViewMode的Data-Bind,ModelView能够包含更加复杂的显示转换逻辑。同时这个ModelView能够复用到任何须要展现用户头像的地方。编程
使用OC编写ModelView架构
若是这个ModelView的显示逻辑更为复杂,如处理复杂动画显示,则这个ModelView可直接使用OC编写,即编写一个UIView的继承类,在这个例子中,AvatarView实际是一个MyRelativeLayout(MyLayout框架中的相对布局UIView)对象,AvatarView使用JS脚本编写显示业务逻辑,在MyRelativeLayout中放入了一个UILabel以显示用户名文本。app
ModelView中使用的OC原生类,如MyRelativeLayout、UILabel,由于其与业务逻辑无关,则可视为View层组件。框架
$class("app.LoginView",{ $init : function(lastloginUser){ this.avatarView = new app.AvatarView({ width:80,height:80 }); this.avatarView.setName(lastloginUser.username); this.userNameInput = $new("UITextField","initWithJSAParam:",{ width:200,height:30,borderStyle:"RoundedRect", placeholder:"用户名", text:lastloginUser.username, onEditingDidEnd:function(view){ jsa.cocoa.UIResponder.fromNative(view).dispatch("onEditingDidEnd",null,null); } }); this.passwordInput = $new("UITextField","initWithJSAParam:",{ width:200,height:30,borderStyle:"RoundedRect",secureTextEntry : true, placeholder:"密码", text:lastloginUser.password, }); var loginView = $new("MyRelativeLayout","initWithJSAParam:",{ subviews:[ { id : "avatar", view:this.avatarView, topPos :{value : "safeAreaMargin",offset : 20}, centerXPos : 0, }, { id:"username", view:this.userNameInput, topPos :{id : "avatar",pos : "bottomPos",offset : 10,}, centerXPos : 0, }, { id:"password", view:this.passwordInput, topPos :{id : "username",pos : "bottomPos",offset : 10,}, centerXPos : 0, },{ view:jsa.cocoa.UIButton.button({ type:"System", width:50, height:30, title:"登陆", onClick:function(view){ jsa.cocoa.UIResponder.fromNative(view).dispatch("onLoginClicked",null,null); } }), topPos :{id : "password",pos : "bottomPos",offset : 10,}, centerXPos : 0, } ] }); jsa.cocoa.UIResponder.fromNative(loginView.$this).setObserver(this); this.$this = loginView.$this; }, onEditingDidEnd:function(){ //在用户名输入结束后,将新的用户名更新到avatarView var username = this.userNameInput.invoke("text"); this.avatarView.setName(username); }, onLoginClicked:function(){ //当点击登陆按钮时,发出登陆事件,并在事件对象中加入登陆表单对象的值(相似于form的post) var username = this.userNameInput.invoke("text"); var password = this.passwordInput.invoke("text"); //抛出事件,Controller可监听该事件以处理登陆事件 jsa.cocoa.UIResponder.fromNative(this.$this).dispatch("onLogin",null,{ username:username, password:password }); } });
LoginView即登陆页面,在LoginView中使用app.AvatarView来展现用户头像,并监听UITextField组件的onEditingDidEnd事件,以动态改变登陆用户名对应的用户头像。经过引入ModelView,可有效的将显示业务中的临时交互逻辑放在ModelView中,而避免将显示逻辑代码写在Controller中。布局
$class("app.Main",{ $extends : "jsa.cocoa.JSAUIViewController", getView : function(viewController){ var lastloginUser = app.UserManagerModel.lastloginUser(); this.loginView = new app.LoginView(lastloginUser); return this.loginView; }, onLogin:function(object,userInfo){ console.log("User:"+userInfo.username+" Password:"+userInfo.password); } });
在将显示逻辑分离到ModelView后,Controller的职责就更加清晰了,getView方法中得到页面所需的Model数据,并用Model数据初始化页面对应的ModelView对象。post
onLogin方法处理loginView视图中的登陆事件。
该DEMO的可运行版本已包含在JSAUIKitCocoaDemo,JS脚本地址:https://github.com/JSAppSugar/JSAUIKitCocoa/tree/master/JSAUIKitCocoaDemo/JSApp/app