欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

IOS开发之多重MVC以及手势

程序员文章站 2022-11-05 11:53:33
ios开发之多重mvc以及手势 继续学习ios开发,这一次学习的是多重mvc架构以及手势识别。 把之前的view接口化 首先需要把之前的faceit程序的可以改变的参数单独提取出来。 //c...

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里面的情况,只需要在类前面加入如下的一行代码。
IOS开发之多重MVC以及手势

同样的,可以使用以下的放下把这些参数放到interface里面。
IOS开发之多重MVC以及手势

这样子的话就可以在storyboard的侧面的边栏里面了。
IOS开发之多重MVC以及手势

但是这个时候会发现,如果在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中设立。
IOS开发之多重MVC以及手势
IOS开发之多重MVC以及手势
IOS开发之多重MVC以及手势

接下来尝试使用swipegesturerecognizer来改变model的状况(请看下图对比改变model和只是改变view的区别)。
IOS开发之多重MVC以及手势

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

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

在这个root controller,里面有一个变量(array)来记录旗下的所有mvc。
var viewcontrollers: [uiviewcontroller]? {get set}
IOS开发之多重MVC以及手势