Hope all good.
Let me introduce my Wreely - Community Platform app architecture to you guys that How I implemented it using swift 4.1 language along with
protocols way to architect this app.
NOTE: This is not a tutorial for any kind of architectural setup (While I’m trying it should be but for now it is not looking like that). It is just an overview of my current project architecture which I’m sharing to keep track of my swift project standards and reference for colleagues.
Before starting app design pattern, architecture & all let me share
Tools I have used in this project.
For centralized project communication
For project initial to-do list, list of project screen along with use cases for each screen, future plan etc
- GitLab Issues
For project issue tracking (Kanban style board)
- GitLab CI
For continuous integration
For version control
For code review
Now as per below list of GitLab issue list I will explain what I had done in that issue commit using issue number.
- Initial project setup
- Setup network, database, analytics and basic utility library via dependency manager
- Setup network connection manager via
Alamofireas a base library
- Setup database connection manager to persist data from remote server -
Not yet implemented
- Setup class model as per network response using
- Setup initial extensions for native controls & class
- Setup helper class for logger, theme, analytics, error, constant and session
- Setup base class and protocols for inbuilt view controllers and UI classes
Initial project setup
- Created project via latest Xcode with init git repo
- Folder structure as below -
Improving it every day
- Except for root and test folder all other folder name starts with
Setup network, database, analytics and basic utilities library via dependency manager
For dependency manager, I have used CocoaPods
The content of Podfile as below -
Improving it every day
Setup network connection manager via Alamofire as base library
It includes implementation of below:
Create API request class which handle common HTTP request parameter like below
- Url string
- Http Method
- Request parameter
- Post Data (For image or any binary data)
- Pass success/failure closure so once network connection manager get a response from the server it will inform this class
Filename Standard: Project two main initial capital word(2 Letters) + APIRequest i.e If your project name is Facebook then name should be
Other utilities this class handles:
- Request pagination (page number and per page)
- Which core data or realm model should be used based on a request type
- Create detail error dictionary return method because here only you are getting request parameter and response object
Create network connection manager class
- Initiate HTTP session manager class from here based on a request parameters getting from API request
- Pass success/failure closure so once session manager get a response from the server it will inform this class
- This class must synthesize(get/set) a singleton class of self
- Once got a response via session manager class handle it here and call a database manager (singleton class) response handler method
Other utilities this class handles:
- Network reachability implementation
- Which request should read or not like for login and sign up it should not check for a valid session for all other requests you should check for a valid token before performing it
Create HTTP session manager class (Should inherit from SessionManager- Alamofire if you are using it)
- Perform actual network request via the third party library i.e Alamofire or Apple native one to handle session request
- Perform GET, POST, PUT etc based on API Request class details
- Get the full path of URL using API Request class and constant base URL
Setup database connection manager to persist data from remote server
For now for persistent storage I have not implemented core data implementation in Wreely app but it is in the queue may be after completion of app remaining feature & optimization will do this.
Still, let me explain to you guys that how I will going to implement that soon. If your app is fairly static so it is good to implement persistence storage otherwise at the end it’s your choice but remember via below implementation you have to maintain below code which indirectly invites hidden or unwanted bugs which you will only have to maintain.
Below few steps I will perform for database manager implementation.
Create database manager class with name standard i.e Project two main initial letter + DatabaseManager So if your project name is facebook so name it as
FBDatabaseManagershould implement things of core data to handle the response
- Database version (get it via app version)
- Manage object context (Learn about NSManageObjectContext)
- Persistent store coordinator (Learn about NSPersistentStoreCoordinator)
- Manage object model (Learn about NSManageObjectModel)
- Clean up previous database response
- Singleton class for shared db manager
- Save context method for core data
- During init create
NSMainQueueConcurrencyTypealong with merge policies and self persistent store coordinator and also implement default app related data insert function task like
Monthsetc during this init
- Perform all save operation of core data model via
NSManageObjectContextobject should be in
asynchronous execution on a dispatch queuewith
- Now finally write handle response function along with API request object so parse it based in API request type
This parser function should be like below:
- Get a managedObjectContext object from shared DB manager
- Get parent manage-object from based on API request object
- Write one more method to customize response object to get a proper dictionary or array object for inserting into the database
- Finally, save it into core data based on array result from the above step
Setup class model as per network response using Mappable
As previously in Objective-C I always create a model using
Interfaces but in swift, I mostly use
Struct as because of it’s immutable behavior and allocation on the stack. (As we know stack is used for static memory allocation and Heap for dynamic. Variables allocated on the stack are stored directly to the memory and access to this memory is very fast).
Check below struct model as used in the project for
Setup initial extensions for native controls & class
Swift has the amazing set of open source extensions library which you can use via dependency manager CocoaPods or Carthage.
Few good libraries for extensions are as below:
In Wreely based on type, I have created project necessary extensions only as per below folder structure.
Soon will open source this project then you can easily see the content of these extensions and all other files.
Setup helper class for logger, analytics, error and session
My logger class as below which depend on Log library - An extensible color logging framework for Swift:
How to use:
Call below WSLogger class method directly from anywhere along with optional error type:
Customized analytics class for this project which cover
Firebase via one method.
How to use:
One should call
WSTracking.sharedTracking.setupInitialTracking() from login or signup or any start controller after initialization of all supported analytics library in appDelegate
Error handler helper class as below which used in the project.
How to use:
You have to initialize WSError object with customize message as below:
Later call default
localizedDescription protocol method to get this custom message.
Wreely session management fully depends on user-based
access_token key of UserDefault object. If exist it will fetch user details from the server during splash screen load and if not it will skip to OTP login screen.
All other internal endpoints need this
access_token to get a valid response.
See below implementation of WSSession class
How to use:
- After successful access token response from server save it on session class via session manager singleton class
- Once session is saved now you have to call user detail endpoint to save user object in current session via WSSessionManager
- To get the active current user just call
activeSessionclass func of
WSSessionwhere it will fetch current active session object via singleton class of WSSessionManager and then call
- For logout call
logoutuse as below which uses same way to get WSSession object as explained above:
Setup base class and protocols for in-built view controllers and UI classes
As we know swift is protocol-oriented programming (POP) rather than object-oriented programming(OOP) which gives him the ability to do more with protocol declaration.
- Inherit protocols
- Create extension
- Even typecast it
In Wreely I have used protocols for each view controller via
presenter as both confirming to each other protocol and calling protocol methods whenever necessary.
Let me give you simple example of WSOTPView module which contains below files.
Check below WSOTPProtocol implementation where
WSOTPPresenterProtocol initiated which will later adopt by WSOTPView and WSOTPPresenter respectively
Once above protocol initiated now let’s see WSOTPView implementation which adopted WSOTPViewProtocol methods which will call by WSOTPPresenter whenever necessary.
Same way you can see WSOTPPresenter implementation which adopted WSOTPPresenterProtocol methods which will call by WSOTPView as whenever necessary.
Along with the above view design pattern I have used storyboard for UI view and even for table view cells responsibility. Check below
WSOTPCell implementation which is implemented using a storyboard outlet.
WSOTPCell inherited by
WSTableViewCell which has below implementation
Few below things still in progress which I’m working on it.
- Integration of Core Data (As bit explained above but not yet implemented)
- Uses of
DispatchQueuequeues in-app with proper
serialtype based on task for the network, heavy batch operation & database related things. (This is one of the ways to optimize large code base app)
- Pagination (With and without persistent database along with network
- Reachability handler
- Implement all possible helper protocols for stable and lesser code for UITableView, UICollectionView etc