Package -

SwiftArchitectureWithPOP

A base architecture written in swift and protocol oriented.

Install

Using cocoapods:
pod 'bais-ios'
# or choose on your need
pod 'bais-ios/Persistance'
pod 'bais-ios/Networking'
pod 'bais-ios/RxExtension'
Manually

Download .zip package and copy the swiftAchitecture/Base folder into you project.

What to provide

Networking

  • Server

    Provide some basic functionality of a server like onlieURL, offlineURL, isOnline etc. In test Mode, offline the server.

  #if DEBUG
    Server.online = false
  #endif

You can comstomize the operation of dealing response data now, just subclass from Server and conform to protocol ServerDataProcessProtocol like:

func handle(data: Any) throws -> Void {
    
    if  let dic = data as? [String: Any],
        let errorCode = dic["error_code"] as? Int,
        errorCode != 0 {
        throw NSError(domain: kYourErrorDomain, code: errorCode, userInfo: [NSLocalizedDescriptionKey: message])
    }
}
  • ApiManager

    Now you can manager request with ApiManager, just sublass from BaseApiManager and conform to protocol ApiInfoProtocol. Only need to provide some infomation about the API and set where the callback is, you are already finished the configuration of an API.

    var apiVersion: String {
        get { return "v2" }
    }
    var apiName: String {
        get { return "user/login" }
    }
    var server: Server {
        get { return mainServer }
    }

The BaseApiManager provide some basic method like:

  public func loadData(with params: [String: Any]?) -> Void

Set delegate for receiving success with origin data or failure with error:

  extension ViewController: ApiCallbackProtocol {
    
      func ApiManager(apiManager: BaseApiManager, finishWithOriginData data: AnyObject) {
        
          if let apiManager = apiManager as? ApiLogin {
              print("login success: \n \(apiManager.originData())")
          }
      }
    
      func ApiManager(apimanager: BaseApiManager, failedWithError error: NSError) {
          
          if apiManager is ApiLogin {
              Log.debugPrint("login failed with error: \(error)")
          }
      }
  }

Or using chaining syntax:

api.loadData(with: nil).response({ (api, data, error) in
  if let error = error {
    // deal error
  }
  if let data = data {
    // do response if have data
  }
})
  • Rx supported

ApiManager provides an Observable for you, you can transfrom it or directly bind it to something:

api.rx.loadData(with: params)
    .flatMap {
        ...
        return yourResultObservable
    }
    .bind(to: label.rx.text)
    .dispose(by: bag)
  • Attentions
  1. The request is generated by RequestGenerator, using Alamofire Request.

Persistance

  • Database

    Like ApiManager, only need to subclass from KMPersistanceDatabase and conform to DatabaseManagerProtocol, provide path,databaseName,database, you are already create a new database in your project. e.g.

  class DefaultDatabase: KMPersistanceDatabase, DatabaseManagerProtocol {
    
    override init() {

        self.databaseName = "default.db"
        self.path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! + "/" + self.databaseName
        self.database = FMDatabaseQueue(path: self.path)
        
        super.init()
    }
  }
  • Table and Record

    Subclass from KMPersistanceTable and conform to TableProtocol let you create a new table in a database. Any objcect conform RecordProtocol can be record in the table you want. See more details in demo.

    Using this just like:

    let table = UserTable()
    let newUser = UserModel(name: "Klein", uid: 310)
    table.replaceRecord(newUser)
  • Fetch

    Fetch data with conditions using DatabaseCommandCondition:

    let table = UserTable()
    let condition = DatabaseCommandCondition()
            
    condition.whereConditions = "user_id >= 0"
    condition.orderBy = "user_name"
            
    let result = table.queryRecordWithSelect("user_name", condition: condition)
  • Advanced

    Always, database provide method of doing query or execute with sql directly, for complex database operation:

  let db = DefaultDatabase()
  db.query("select * from tableDoesntExtist", withArgumentsInArray: nil)

Tools and Kits

  • Custom extensions and categories.
  • UI relevant class for easy accessing global UI settings.
  • SystemLog can write log to files, and stored in sandbox.

Almost done >w<!

TODO

  • Networking: ~~cache~~, origin data transform to Model or View's data, priority of request.
  • Download and upload functions in API manager.
  • Persistance: transform data to model or View's data after query.
  • ~~Animations, Tools and Kits: TextKit like YYText, etc~~. (bais-ios won't provide those utilities, because base shouldn't have to.)
  • Refactoring, more functional and reative. Considering to use Rx or ReactiveSwift. Fully use genericity.

License

All the source code is published under the MIT license. See LICENSE file for details.

Github

link
Stars:

Advertisement