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 fromBaseApiManager
and conform to protocolApiInfoProtocol
. 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
- The request is generated by
RequestGenerator
, using Alamofire Request.
Persistance
-
Database
Like ApiManager, only need to subclass from
KMPersistanceDatabase
and conform toDatabaseManagerProtocol
, providepath
,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 toTableProtocol
let you create a new table in a database. Any objcect conformRecordProtocol
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
orReactiveSwift
. Fully use genericity.
License
All the source code is published under the MIT license. See LICENSE file for details.