form1.cn
Make a little progress every day

Part 9:iOS分层架构设计的概念

14th of March 2017 Swift Swift 1965

在本章中主要学习到了,分层架构的设计,其实就是分文件夹来创建View,Controller,Model的类文件


• 表示层,相当于TP中的View

用户与系统交互的组件集合。用户通过这一层向系统提交请求或发出指令,系统通过这一层接收用户 请求或指令,待指令消化吸收后再调用下一层,接着将调用结果展现到这一层。表示层应该是轻薄的,不应该具 有业务逻辑。


业务逻辑层,相当于TP中的Controller

系统的核心业务处理层。负责接收表示层的指令和数据,待指令和数据消化吸收后,再进行组织 业务逻辑的处理,并将结果返回给表示层。


数据持久层,相当于TP中的Model

数据持久层用于访问信息系统层,即访问数据库或文件操作的代码应该只能放到数据持久层中, 而不能出现在其它层中。


信息系统层,相当于开发WEB时用到数据库

系统的数据来源,可以是数据库、文件、遗留系统或者网络数据。


以下为分层架构设计实现的一个Note备忘录的DemoCode


数据持久层,PersistenceLayer/Note.swift 、NoteDAO.swift


业务领域对像类,可以理解为PHP框架开中的 数据库中的表

import Foundation

//业务领域对像类,可以理解为PHP框架开中的 数据库中的表
class Note {
    
    let Date: NSDate
    var Content: NSString
    
    init(date:NSDate,content:NSString) {
        self.Date = date
        self.Content = content
    }

}


DAO类,一般按表名命名,相当于PHP框架加的 Model

import Foundation

//DAO类,一般按表名命名,相当于PHP框架加的 Model
class NoteDAO {
    
    //保存数据列var,没用数据,数据保存到内存中
    var listData: NSMutableArray! //可变数组类型
    
    //只进行和数据库的交互,不需要保持任何状态,所以可以使用单例模式
    private static let sharedInstance = NoteDAO() //单例的实例保存这个属性中
    class var sharedFoo: NoteDAO { //swift中的静态计算属性
        
        //添加一些测试数据
        let dateFormatter : DateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        
        let date1: NSDate = dateFormatter.date(from: "2015-01-01 16:01:03")! as NSDate
        let note1: Note = Note(date:date1, content: "Welcome to MyNote.")
        
        let date2: NSDate = dateFormatter.date(from: "2015-01-02 8:01:03")! as NSDate
        let note2: Note = Note(date:date2, content: "欢迎使用MyNote。")
        
        //这里需要先实例化,才能添加值
        sharedInstance.listData = NSMutableArray()
        sharedInstance.listData.add(note1) //listData字典里面放的Note对像
        sharedInstance.listData.add(note2)
        
        return sharedInstance
    }
    
    //插入Note方法
    func create(model: Note) -> Int {
        self.listData.add(model)
        return 0
    }
    
    //删除Note方法
    func remove(model: Note) -> Int {
        for note in self.listData {
            let note2 = note as! Note
            //比较日期主键是否相等
            if note2.Date == model.Date {
                self.listData.remove(note2)
                break
            }
        }
        return 0
    }
    
    //修改Note.Content方法
    func modify(model: Note) -> Int {
        for note in self.listData {
            let note2 = note as! Note
            //比较日期主键是否相等
            if note2.Date == model.Date {
                note2.Content = model.Content
                break
            }
        }
        return 0
    }
    
    //查询所有数据方法
    func findAll() -> NSMutableArray {
        return self.listData
    }
    
    //修改Note方法
    func findById(model: Note) -> Note? {//返回类型为可选的,说明Note可以返回nil
        for note in self.listData {
            let note2 = note as! Note
            //比较日期主键是否相等
            if note2.Date == model.Date {
                return note2
            }
        }
        return nil
    }


}


业务逻辑层,BusinessLogicLayer/NoteBL.swift


业务逻辑层类,相当于PHP框架中的 Controller

import Foundation

//业务逻辑层类,相当于PHP框架中的 Controller
class NoteBL {

    //插入Note方法
    func createNote(model: Note) -> NSMutableArray {
        let dao:NoteDAO = NoteDAO.sharedFoo
        dao.create(model: model) //会有警告,因为create方法有返回值但在这里并没有使用
        return dao.findAll()
    }
    
    //删除Note方法
    func remove(model: Note) -> NSMutableArray {
        let dao:NoteDAO = NoteDAO.sharedFoo
        dao.remove(model: model)
        return dao.findAll()
    }
    
    //查询所用数据方法
    func findAll() -> NSMutableArray {
        let dao:NoteDAO = NoteDAO.sharedFoo
        return dao.findAll()
    }
    
}


表示层,presentationLayer/MasterViewController.swift 、DetailViewController.swift、AddViewController.swift


MasterViewController.swift

import UIKit

//Table列表页面
class MasterViewController: UITableViewController {

    let BL:NoteBL = NoteBL()
    var detailViewController: DetailViewController? = nil
    var objects = NSMutableArray()


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.navigationItem.leftBarButtonItem = self.editButtonItem

        //let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(insertNewObject(_:)))
        //self.navigationItem.rightBarButtonItem = addButton
        if let split = self.splitViewController {
            let controllers = split.viewControllers
            self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
        }
        
        //查出所有数据
        self.objects = self.BL.findAll()
        
        //(接收通知)监听通知事件RegisterCompletionNotification,交给registerCompletion函数处理
        NotificationCenter.default.addObserver(self, selector: #selector(CreateNoteList(notification:)), name: NSNotification.Name.init(rawValue: "CreateNoteList"), object: nil)// . object: nil 可以发送通知的视图接收过来
        
    }

    override func viewWillAppear(_ animated: Bool) {
        self.clearsSelectionOnViewWillAppear = self.splitViewController!.isCollapsed
        super.viewWillAppear(animated)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /func insertNewObject(_ sender: Any) {
        objects.insert(NSDate(), at: 0)
        let indexPath = IndexPath(row: 0, section: 0)
        self.tableView.insertRows(at: [indexPath], with: .automatic)
    }*/

    // MARK: - Segues

    //详细页面显示
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showDetail" {
            if let indexPath = self.tableView.indexPathForSelectedRow {
                let object = objects[indexPath.row] as! Note
                let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
                controller.detailItem = object
                controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem
                controller.navigationItem.leftItemsSupplementBackButton = true
            }
        }
    }

    // MARK: - Table View

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.objects.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        let object = objects[indexPath.row] as! Note//查询数组中的Note出来
        cell.textLabel!.text = object.Content as String//取Note的Content的属性
        return cell
    }

    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }

    //进行操作,当前主要处理delete操作
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            let removeNote = self.objects[indexPath.row] as? Note
            self.objects = BL.remove(model: removeNote!)
            //self.objects.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)
        } else if editingStyle == .insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
        }
    }

    //实现通知监听方法
    func CreateNoteList(notification : NSNotification) {
        let allData = notification.object as! NSMutableArray//取到投送过来对像
        self.objects = allData//拿到的数据给当前视图的变量
        self.tableView.reloadData()//重新加载当前表视图
        
    }

}


DetailViewController.swift

import UIKit

//详细页面显示
class DetailViewController: UIViewController {

    @IBOutlet weak var detailDescriptionLabel: UILabel!


    func configureView() {
        // Update the user interface for the detail item.
        if let detail = self.detailItem {
            if let label = self.detailDescriptionLabel {
                label.text = detail.Content as String
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.configureView()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    var detailItem: Note? {
        didSet {
            // Update the view.
            self.configureView()
        }
    }


}


AddViewController.swift

import UIKit

//添加备忘录
class AddViewController: UIViewController {

    let BL:NoteBL = NoteBL()
    
    @IBOutlet weak var noteTextField: UITextField! //TextField的输出口
    
    //Cancel的动作事件
    @IBAction func onCancel(_ sender: UIBarButtonItem) {
        self.dismiss(animated: true, completion: nil)//关闭模态
    }
    
    @IBAction func onSave(_ sender: UIBarButtonItem) {
        
        //实例化一个新的Note
        let note = Note(date: NSDate(), content: self.noteTextField.text! as NSString)//NSDate(),为当前日期
        //调用业务逻辑层的createNote方法,会返回添加后的所有数据
        let objs = BL.createNote(model: note)
        //注册通知,传输数据 . object: objs 把返回的所有数据投送出去
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "CreateNoteList"), object: objs, userInfo: nil)
        
        self.dismiss(animated: true, completion: nil)//关闭模态
        self.noteTextField.resignFirstResponder()//username放弃第一响应者
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        //注册点击事件
        self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    //点击空白处关闭键盘方法
    func handleTap(sender: UITapGestureRecognizer) {
        if sender.state == .ended {
            self.noteTextField.resignFirstResponder()//username放弃第一响应者
        }
        sender.cancelsTouchesInView = false
    }


}