当前位置: 移动技术网 > 移动技术>移动开发>IOS > IOS开发之多重MVC以及手势

IOS开发之多重MVC以及手势

2018年10月12日  | 移动技术网移动技术  | 我要评论

ios开发之多重mvc以及手势

继续学习ios开发,这一次学习的是多重mvc架构以及手势识别。

把之前的view接口化

首先需要把之前的faceit程序的可以改变的参数单独提取出来。

//changable parameters

    //1 means smile and -1 means sad.
    var smilefactor: cgfloat = 1 
    var eyeopen: bool = false
    var eyebrowtiltfactor: cgfloat = -1
    var linecolor: uicolor = uicolor.black

如果想要在main.storyboard里面实时可以看到view里面的情况,只需要在类前面加入如下的一行代码。
这里写图片描述

同样的,可以使用以下的放下把这些参数放到interface里面。
这里写图片描述

这样子的话就可以在storyboard的侧面的边栏里面了。
这里写图片描述

但是这个时候会发现,如果在faceview里面直接改变变量的初始值,storyboard的图像并不会重新渲染。要改变这个,需要使用变量的didset属性,意思是如果变量在某种程度上更改了,那么就需要执行dieset括号内的内容。

var smilefactor: cgfloat = 1 { didset{setneedsdisplay()}}

model部分

接下来我们将会完成mvc中model的部分,我把它命名为facialexpressionmodel。这个时候问题来了,是使用class呢,还是使用struct呢?因为看到stanford的老师在这个demo里面使用了struct。后来查阅了相关的资料,发现了它们根本的区别在于:

struct传值,class传引用

结构(struct)是一种值类型。也就是说,结构实例是分配在线程堆栈上的,结构本身是包含有值的,而不是像类一样的引用类型,包含的是所指向堆当中的引用(指针)。也就是说,结构的生存周期与简单类型(int,double等)相同的。

你使用的是一个对class实例的引用。而你使用的不是对一个struct的引用。(而是直接使用它们)

当我们将class作为参数传给一个方法,我们传递的是一个引用。struct传递的是值而非引用。

紧接着会有一个让人非常困惑的问题,到底model写的内容是什么呢?其实目前来看,我们的这个小应用都只是在控制view,所以目前只需要用到view和viewcontroller,那么model只需要模拟把各种情况写出来就好了(计算机的是结果,因为要显示的不是情况)。

model返回的是view的各种情况类型,一般用enum。

关于enum有以下两点需要注意:
1. relative值的使用
可以如下方式定义relative值,然后如下方式使用。

//定义
enum barcode {
  case upca(int, int, int)
  case qrcode(string)
}

//使用
switch productbarcode {
case .upca(let numbersystem, let identifier, let check):
    println("upc-a with value of \(numbersystem), \(identifier), \(check).")
case .qrcode(let productcode):
    println("qr code with value of \(productcode).")
}
rawvalue的相关使用
作为相关值的替代,枚举成员可以被默认值(称为原始值)预先填充,其中这些原始值具有相同的类型。
enum asciicontrolcharacter: character {
    case tab = "\t"
    case linefeed = "\n"
    case carriagereturn = "\r"
}

原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。当整型值被用于原始值,如果其他枚举成员没有值时,它们会自动递增。

enum planet: int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

let possibleplanet = planet(rawvalue: 7)
//这里就是possibleplanet就是uranus

关于这些类型的切换,有一个要处理的问题就是边界问题。比如如果我要从伤心、平静、开心三种状态之间切换,【更开心】这个操作有可能会向上跳一级,或者什么都不发生。以下的代码可以轻易的解决这个问题。

 func moresmile() -> mouth{
     return  mouth(rawvalue: rawvalue + 1) ?? .smile
 }

 func moresad() -> mouth{
     return mouth(rawvalue: rawvalue - 1) ?? .sad
 }

这里插播一个swift的命名规范。

其中类名、协议名、结构体、枚举等类型的命名规范通常是,大写字母作为开始,其余单词首字母大写,例如类名helloworldapp。

完成controller调控两大板块

我们已经知道了model里面是一个struct,所以我们需要一个变量来装载它(class类似的)。然后我们需要让他时刻更新view。方法和上面很类似,这里把关键函数updateui贴出来。

 func updateui(){
        switch facialexpression.eye{
        case .open:
            faceview.eyeopen = true
        case .close:
            faceview.eyeopen = false
        default:
            break
        }

        switch facialexpression.mouth{
        case .smile:
            faceview.smilefactor = 1.0
        case .relax:
            faceview.smilefactor = 0.0
        case .sad:
            faceview.smilefactor = -1.0
        default:
            break
        }

        switch facialexpression.eyebrow{
        case .happy:
            faceview.eyebrowtiltfactor = 1.0
        case .relax:
            faceview.eyebrowtiltfactor = 0.0
        case .sad:
            faceview.eyebrowtiltfactor = -1.0
        default:
            break
        }
    }

手势

手势的基类是uigesturereconizer,但是这是一个抽象的概念,真正的类是各种手势的gesturereconizer( 比如pinch和swipe)。而且必须view才能使用它们。一般来说是controller添加到view。不过一些基本的gesture可能本事就在view上。当识别成功,会使用handler来传输信息,如果不涉及和model沟通,那么只需要在view中,否则需要在controller中设立。
这里写图片描述
这里写图片描述
这里写图片描述

接下来尝试使用swipegesturerecognizer来改变model的状况(请看下图对比改变model和只是改变view的区别)。
这里写图片描述

let happyreconizer = uiswipegesturerecognizer(target: self, action: #selector(faceviewcontroller.happier))
happyreconizer.direction = .down           faceview.addgesturerecognizer(happyreconizer)

分别是创建reconizer、设置属性、以及添加进去view里面。
我们来看uigesturereconizer的基本格式(target:self/view, action: #selector(controller/view.函数名))。
所有的对应的处理函数func前面都要加入@objc。

@objc func happier(){
    facialexpression.mouth = facialexpression.mouth.moresmile()
    }           

同样的reconizer也可以通过在storyboard拖拽加入然后使用ctrl在controller中建立联系。

@ibaction func eyechange(_ recognizer: uitapgesturerecognizer) {
        if recognizer.state == .ended{
            switch facialexpression.eye{
            case .open:
                facialexpression.eye = .close
            case .close:
                facialexpression.eye = .open
            default:
                break
            }
        }
    }

这里写图片描述
这里我们使用xcode提供给我们的mvc,常用的分别有以下三种。
第一种是tabbar。
这里写图片描述
第二种是split,常用在ipad。左边一般是master,右边叫做detail。potrait的时候一般master隐藏在左边,可以抽屉式抽取出来。
这里写图片描述
第三种是navigationcontrol。
这里写图片描述
需要知道的是,ios在处理多级菜单的时候,是使用stack来存的。每一个页面push进去,然后返回就是pop。这一切是通过一个更高一级的controller(比如navigationcontrol)来控制的。

在这个root controller,里面有一个变量(array)来记录旗下的所有mvc。
var viewcontrollers: [uiviewcontroller]? {get set}
这里写图片描述

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网