项目作者: Dylanooo

项目描述 :
基于Swift 4.0的MVVM框架,仿照Moya对Alamofire进行更轻量级的封装,网络请求返回实体或者实体数组,结构更清晰
高级语言: Swift
项目地址: git://github.com/Dylanooo/MVVM-Swift.git
创建时间: 2017-11-24T06:49:49Z
项目社区:https://github.com/Dylanooo/MVVM-Swift

开源协议:MIT License

关键词:
alamofire moya mvvm realmswift swift4

下载


Mac OS X
MVVM
Swift 4 compatible
MIT

MVVM-Swift

  • 基于Swift 4.0MVVM框架
  • 仿照MoyaAlamofire进行更轻量级的封装,网络请求返回实体或者实体数组(双刃剑,缺点在于对于简单数据结构也需要创建相应的实体对象,优点是保持项目结构统一,后续会优化)
  • 基于当下流行的Realm数据库,封装了一套方便开发者,对数据库CRUD操作的数据库工具类
  • 另外通过灵活使用Swift的语言特性,封装了其他更方便的工具类,使开发者的工作更轻松

Tips: 因为项目涉及的功能较多,部分功能测试不够充分,如果有不合理的地方,请多多指教,后续我也将不断完善这个框架,努力打造一套合理、简洁、实用的项目

项目结构

  • Controllers
  • ViewModels
  • Views
  • Utils

    • Extension
      • UIColorExtension
      • NSObjectExtension
      • NotificationCenterExtension
      • UIApplicationExtension
      • NSUserDefaultsExtension
      • UIViewControllerExtension
      • UIStoryboardExtension
      • UIViewExtension
      • StringExtension
      • UIImageExtension
      • FoundationExtension
    • Configure
    • ThirdPart
    • Custom

      • Managers

        • NetworkManager(仿照Moya的轻量级实现)
        • CacheManager (待实现)
        • AppManager
        • ThemeManager
        • DateManager
        • FileManager
        • LocationManager
        • DBManager(基于RealmSwift)
      • UITools

        • CustomProgressHUD
        • WebView(UIWebView&WKWebView)
  • Resources
    • Interface
    • Assets.xcassets
    • Images
    • Documents

架构工作流程

流程图

Utils中部分工具介绍

一、 NetworkManager

  • Model 中实现方式,遵循RealmSwift的写法
  1. import UIKit
  2. import RealmSwift
  3. class Province: DBModel {
  4. @objc dynamic var id: Int = 0
  5. @objc dynamic var firstletter: String = ""
  6. @objc dynamic var name: String = ""
  7. /// 设置与Contry的一对多关系
  8. let owner = LinkingObjects(fromType: Country.self, property: "provinces")
  9. /// 设置与cities的一对多关系, 保持字段名称与服务端返回一致
  10. let citys = List<City>()
  11. }
  • API 中实现如下:
  1. enum UserApi {
  2. case login
  3. case Image(count:Int,page:Int)
  4. case regester
  5. case xxx
  6. case download
  7. }
  8. extension UserApi: Request {
  9. /// 请求返回实体类型
  10. typealias EntityType = Country
  11. /// host 如果项目中所有host可以保持一致,直接在Request中设置默认Host,在具体的Api中可省略
  12. var baseURL: String {
  13. switch self {
  14. case .xxx:
  15. return "http://www.baidu.com"
  16. default:
  17. return "http://comm.app.autohome.com.cn"
  18. }
  19. }
  20. /// 具体业务对应的path
  21. var path: String {
  22. switch self {
  23. case .login:
  24. return "/news/province-pm2-ts0.json"
  25. case .regester:
  26. return "/regester"
  27. case .download:
  28. return "http://7xoyls.com1.z0.glb.clouddn.com/%E9%99%88%E5%A5%95%E8%BF%85-%E4%B8%80%E4%B8%9D%E4%B8%8D%E6%8C%82%20%28Live%29.mp3"
  29. default:
  30. return ""
  31. }
  32. }
  33. /// 参数
  34. var parameters: [String: Any]? {
  35. switch self {
  36. case .Image(let X, let Y):
  37. return ["x": X, "y": Y]
  38. default:
  39. return [:]
  40. }
  41. }
  42. }
  • ViewModel 中实现:
  1. import UIKit
  2. class UserViewModel: BaseViewModel<UserApi> {
  3. func login(pwd: String?, account: String?, complete: @escaping ((Country)->Void)) {
  4. provider.request(.login, responseHandler: { response in
  5. DebugPrint("value = \(String(describing: response.value))")
  6. DebugPrint("values = \(String(describing: response.values))")
  7. DebugPrint(response.message)
  8. if let province = response.value {
  9. complete(province)
  10. }
  11. })
  12. }
  13. }

二、 NotifcationCenterExtension

通过对NotificationCenter封装后,开发者在定义通知名称的时候,只需要在枚举NotificationName 中添加对应的case就可以了,方便简单

  1. enum NotificationName: String {
  2. // 用户登录成功
  3. case loginSuccess
  4. // 用户退出登录
  5. case logout
  6. }

调用时代码可以更加简洁了, 而且可以和调用系统通知格式保持一致:

  1. // 调用自定义的通知名称
  2. NotificationCenter.post(name: .loginSuccess, object: nil, userInfo: nil)
  3. // 调用系统的通知名称
  4. NotificationCenter.post(name: .UIKeyboardDidHide, object: nil, userInfo: nil)

PS:项目中所用服务端接口为本地服务,实现方式为Python+Flask+MongoDB,如有需要,请部署项目MVVM-Service