How I architect Wreely - Community Platform swift based iPhone app

Hello!!

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 view, presenter and 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.

  • Slack For centralized project communication
  • Trello 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
  • GitLab For version control
  • Codacy 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.

  1. Initial project setup
  2. Setup network, database, analytics and basic utility library via dependency manager CocoaPods
  3. Setup network connection manager via Alamofire as a base library
  4. Setup database connection manager to persist data from remote server - Not yet implemented
  5. Setup class model as per network response using Mappable
  6. Setup initial extensions for native controls & class
  7. Setup helper class for logger, theme, analytics, error, constant and session
  8. Setup base class and protocols for inbuilt view controllers and UI classes

Initial project setup

  1. Created project via latest Xcode with init git repo
  2. Folder structure as below - Improving it every day
  3. Except for root and test folder all other folder name starts with WS (project initial)

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 FBAPIRequest

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.

  1. 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 FBDatabaseManager

  2. FBDatabaseManager should 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 NSManageObjectContext object with NSMainQueueConcurrencyType along with merge policies and self persistent store coordinator and also implement default app related data insert function task like Gender, Relationship Status, Months etc during this init
    • Perform all save operation of core data model via NSManageObjectContext object should be in asynchronous execution on a dispatch queue with DISPATCH_QUEUE_SERIAL queue option
    • 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 User model


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

Logger

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:

WSLogger.log(errorMessage, logType: .kError)

Analytics

Customized analytics class for this project which cover OneSignal, Mixpanel, Answers and 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 handle

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:

let error: LocalizedDescriptionError = WSError.customError(message: "Custom error here")

Later call default localizedDescription protocol method to get this custom message.

print(error.localizedDescription)

Session management

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:

  1. After successful access token response from server save it on session class via session manager singleton class
WSSessionManager.sessionManager.setAccessToken(response["access_token"] as! String)
  1. Once session is saved now you have to call user detail endpoint to save user object in current session via WSSessionManager
WSSessionManager.sessionManager.setCurrentUser(userObject)
  1. To get the active current user just call activeSession class func of WSSession where it will fetch current active session object via singleton class of WSSessionManager and then call currentUser instance func
WSSession.activeSession().currentUser()
  1. For logout call logout use as below which uses same way to get WSSession object as explained above:
WSSession.activeSession().logout()

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.

We can:

  1. Inherit protocols
  2. Create extension
  3. Even typecast it

In Wreely I have used protocols for each view controller via view and 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.

  1. WSOTPProtocol.swift
  2. WSOTPView.swift
  3. WSOTPPresenter.swift
  4. WSOTPCell.swift

Check below WSOTPProtocol implementation where WSOTPViewProtocol and 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.

  1. Integration of Core Data (As bit explained above but not yet implemented)
  2. Uses of DispatchQueue queues in-app with proper concurrent and serial type based on task for the network, heavy batch operation & database related things. (This is one of the ways to optimize large code base app)
  3. Pagination (With and without persistent database along with network per_page & page_no handler)
  4. Reachability handler
  5. Implement all possible helper protocols for stable and lesser code for UITableView, UICollectionView etc

Internal Server Error - Invalid command 'RewriteEngine' (Ubuntu Apache/PHP)

What is Internal Server Error?

It usually a server misconfiguration (check .htaccess file) or problem with your server side script.

First of all check for error log

$ 

sudo vim /var/log/apache2/error.log


If log file become empty then enable it via php.ini



For php7
$ sudo vim /etc/php/7.0/apache2/php.ini 

or

For php5
$ sudo vim /etc/php5/apache2/php.ini 

Find display_errors, display_startup_errors
, error_reporting
 (Which look’s like below)

;display_errors
;   Default Value: On
;   Development Value: On
;   Production Value: Off

;display_startup_errors
;   Default Value: Off
;   Development Value: On
;   Production Value: Off

;error_reporting
;   Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
;   Development Value: E_ALL
;   Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT

Uncomment it via removing semicolons (After change it will look like below)

display_errors
;   Default Value: On
;   Development Value: On
;   Production Value: Off

display_startup_errors
;   Default Value: Off
;   Development Value: On
;   Production Value: Off

error_reporting
;   Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
;   Development Value: E_ALL
;   Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT

Restart apache via below command


$ sudo service apache2 restart 

or

$ sudo /etc/init.d/apache2 restart


Now check in error.log file for Internal Server related problem.


If in error log you got module related problem like below:

/var/www/html/.htaccess: Invalid command ‘RewriteEngine’, perhaps misspelled or defined by a module not included in the server configuration 


Then perform below command for above error which enable rewrite module of apache2:

$ sudo a2enmod rewrite && sudo service apache2 restart

That’s it. You are done :)

What is GitHub Pages, Jekyll, Poole, Hyde and Hydeout?

Hello, Hope all good!

This is the first post on my personal blog and I want everyone to know how I setup this site using Jekyll and GitHub Pages.

Please read below things step by step as per their reference source and get to know about this. Good Luck!!

What is GitHub Pages?

GitHub Pages is a static site hosting service.

GitHub Pages is designed to host your personal, organization, or project pages directly from a GitHub repository.
You can create and publish GitHub Pages online using the Jekyll Theme Chooser.

GitHub Pages is a static site hosting service and doesn’t support server-side code such as, PHP, Ruby, or Python.

Reference

What is Jekyll?

Jekyll is a simple, blog-aware, static site generator for personal, project, or organization sites. Written in Ruby by Tom Preston-Werner, GitHub’s co-founder, it is distributed under an open source license.

Instead of using databases, Jekyll takes the content, renders Markdown or Textile and Liquid templates, and produces a complete, static website ready to be served by Apache HTTP Server, Nginx or another web server.

Jekyll is the engine behind GitHubPages, a GitHub feature that allows users to host websites based on their GitHub repositories.

Reference

Few useful article’s related to Jekyll and GitHub Pages:
Setting up your GitHub Pages site locally with Jekyll
Building a static website with Jekyll and GitHub Pages


Meet Poole

Poole is the butler for Jekyll, the static site generator.

It’s designed and developed by @mdo to provide a clear and concise foundational setup for any Jekyll site.
It does so by furnishing a full vanilla Jekyll install with example templates, pages, posts, and styles.

Reference


Hyde?

Hyde is a brazen two-column Jekyll theme that pairs a prominent sidebar with uncomplicated content. It’s based on Poole, the Jekyll butler.

Hyde is a theme built on top of Poole, which provides a fully furnished Jekyll setup—just download and start the Jekyll server.

Reference


Finally Hydeout?

Hydeout updates the original Hyde theme for Jekyll 3.x and adds new functionality.

Hydeout is available as the jekyll-theme-hydeout Ruby Gem.
Add gem "jekyll-theme-hydeout", "~> 3.4" to your Gemfile and run bundle install

Hydeout uses pagination, so if you have an index.md, you’ll need to swap it with an index.html that uses the index layout:

---
layout: index
title: Home
---

Find out more by visiting the project on GitHub.