Skip to content

Instantly share code, notes, and snippets.

@wassafr
Created May 16, 2017 14:48
Show Gist options
  • Save wassafr/c8cb75829701dbc20ee11b15ea85c710 to your computer and use it in GitHub Desktop.
Save wassafr/c8cb75829701dbc20ee11b15ea85c710 to your computer and use it in GitHub Desktop.

Developing our own framework, the AilPod

Last november, we, the engineer team at Wassa, noticed we had 3 different issues that needed a quick fix:

  • Apple release swift 2.3 and swift 3 making most of our dependency framework not compiling. Objective-C is not subject to version change, so changing our dependency from swift to objective-c could make it work. Of course by reversing the language, we knew we would have to re-reverse back to swift language
  • We were using very similar code for native UI components (like UITableView and ToggleButton) This issue was leading in more testing and more bug fixing. Most of our projects are depending on tableview and UI stability.
  • We had a tendency to reuse code between projects without versioning it separatly

Those 3 issues have something in common: they can be easily solved by the creation of our own internal framework.

This is why we started developing the AilPod (pronounce as a french: "i-pod" ;-) )


The first and most urgent feature we developed was a network class using AFNetworking (objective-c) instead of Alamofire (swift).

Most of our projects make requests to REST APIs, but because of the new version of swift language, Alamofire became outdated and uncompilable. Our solution was to design a specific class called "AilNetworking" to implement AFNetworking features. By using Objective-C instead of Swift, this class does not depend anymore on Swift version. AilNetworking exposes the following functions:

class AilNetworking {
    // default init
    public init()
    
    // display debug in console
    public init(debugMode: Bool)
    // function used to perform request, return result as it is (not deserialized in json)
    public func performBackgroundFetchWithCompletion(method: AilMethod = .GET, url: String, headers: [String:String]?, postParams params:[String, Any], encoding: AilParameterEncoding, result: @escaping (Any?, AilError?) -> Void))
    
    // function to call if you want to display a connection error message
    public func networkIsReachable() -> Bool
}

The second feature developped was extensions to classes from Foundation and UIKit: String, UIView, NSDate, UIColor, etc.

The extensions for those classes implement basic features missing from Foundation and UIKit, like:

  • String: return the localized version of a string, for exemple: "my_localization_key".localized() -> "Localized String" func localized() -> String

  • UIView: make layer properties easily available from view

@IBInspectable var cornerRadius: CGFloat  
@IBInspectable var borderWidth: Float  
@IBInspectable var borderColor: UIColor
  • NSDate: comparison operators
func <(_ dateToCompare: Date) -> Bool
func >(_ dateToCompare: Date) -> Bool
func =(_ dateToCompare: Date) -> Bool
  • UIColor: Parse a string formatted as following "#FFFFFF" to transform to a UIColor object
func colorFromHexa(hexa: String, alpha: Double?) -> UIColor

The third most important feature is a custom implementation of a UITableViewController and its delegates: UITableViewDelegate and UITableViewDataSource.

Instead of re-writing the same basic implementation, the AilTableViewController class links a UITableViewCell and a custom type so the view is aware of what to display. This is how you can implement this custom AilTableViewController:

class MyTableView: AilTableViewController {
    override func viewDidLoad() {
        super.viewDidload()
        
        // here we choose to have auto-resized cells
        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 44
        
        // link the model with the cell identifier
        setCellIdentifier(cellIdentifier: "StoryboardCellIdentifier", forObjectClass: MyModelClass.self)
        
        // initialize the internal table
        let myModels: [MyModelClass] = []
        loadData(myModels)
    }
}
class MyModelCell: UITableViewCell, AilTableCell {
    func loadData(_ source: AnyObject, indexPath: IndexPath) {
        if let myModel = source as? MyModelClass {
            // use the model set in setCellIdentifier
        }
    }
    
    func definedHeight() -> CGFloat {
        return UITableViewAutomaticDimension
    }
}

After months of using the AilPod, we consider the project stable and well documented. As our developers would say: "Sometimes I think I found a bug in the Ailpod, and then I realize I was not using it correctly".

Our last issue about this project is to know what to add next: is a feature general enough to be added in the project ? Every new feature is discussed between the team members and is subject to several editing before being present in the AilPod.

Finally, by developing this SDK, we improve our skills to expose functions through a SDK. This knowledge will lead us to develop new internal SDKs, like one geolocation and 3d maps rendering.

Do you want to know more about us ?

Find us:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment