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