Swifting a Mock Server (with Vapor)

The aim of this post is put up the level of previous post (Testing at the edge of your App with a Mock Server), just by using Vapor (a swift backend framework) and deploying server with Heroku (a cloud platform that lets companies build, deliver, monitor and scale apps).

Setup the environment

Vapor

For installing vapor backend framework just:

$ curl -sL check.vapor.sh | bash
...
$ curl -sL toolbox.vapor.sh | bash
...
$ vapor --help
Usage: vapor <new|build|run|fetch|clean|test|xcode|version|self|heroku|docker>
Join our Slack if you have questions, need help,
or want to contribute: http://vapor.team

For creating a new vapor project, afterwards create a new git repository with the stuff generated and finally open the project:

$ vapor new mock-vapor
...
$ cd mock-vapor
$ git init
$ git add .
$ git commit -m "Initial commit"
$ vapor xcode

Up to this point you will have XCode with new project:

stp

Run the project, open your favourite browser and type the url http://localhost:8080

browser

Mock server is working on local ?. Ready for getting to next level? ?

Heroku

If you do not have an account just sign up here. Later on, download Heroku command line tools, for validating installation just type (restart computer if necessary).

$ heroku --version
$ heroku login
Enter your Heroku credentials.
Email: javi.calatrava@gmail.com
Password (typing will be hidden):
Logged in as javi.calatrava@gmail.com
$ vapor heroku init
Would you like to provide a custom Heroku app name?
y/n>y
Custom app name:
>mock-vapor
https://mock-vapor.herokuapp.com/ | https://git.heroku.com/mock-vapor.git

Would you like to provide a custom Heroku buildpack?
y/n>n
Setting buildpack...
Are you using a custom Executable name?
y/n>n
Setting procfile...
Committing procfile...
Would you like to push to Heroku now?
y/n>y
This may take a while...
Building on Heroku ... ~5-10 minutes [ • ]

….finally after several minutes the mock server is deployed on a remote site, just type https://mock-vapor.herokuapp.com/ in your browser.

browser2

Implementing a dummy service

Our mock server will return .json, first thing to do is setting  content-type.  Just update View.swift extension:

extension View: ResponseRepresentable {
    public func makeResponse() -> Response {
        return Response(status: .ok, headers: [
            "Content-Type": "text/html; application/json;charset=utf-8"
        ], body: .data(data))
    }
}

Validate with any rest analyzer:

post

Adding basic fixer answer. This is what our mock servier will answer:

drop.get("latest") { request in
    if let param = request.data["param"]?.string {
        if param == "FORCE_BUSINESS_ERROR" {
            return try drop.view.make("latest_FORCE_BUSINESS_ERROR")
        }else if param == "FORCE_SERVER_ERROR"{
            return  Response(status: .notFound)
        }else{
            return try drop.view.make("latest") 
        }
    }else{
        return try drop.view.make("latest")
    }
}

latest_FORCE_BUSINESS_ERROR is just a json template file.

The client App

The client app will be exactly the same presented in previous post, but obviously replacing urls.n In this case we will use three schemas:

  • Local mock server. For debugging with local mock server.
  • Remote mock server. For working with common development mock server.
  • Fixer real server. For working with final service.

Select Local mock server schema and launch the test:

tr

Deploy the mock server

At the moment there is nothing by typing https://mock-vapor.herokuapp.com/latest in the remote server:before

For deploying just push changes:push

This process can take several minutes… ?

push2

But finally we have the remote with latest, at this moment, just type: https://mock-vapor.herokuapp.com/latest. The remote server is ready!

after

Switch mock remote server

Switch oclient Mock Server Schema to lauch the tests on the client, but this time bouncing to a remote mock server.

rs

Conclusion

With this post you have seen how to deploy a remote mock server. You can use this server as a test platform or you could develop your app backend. If you were interested in investigating more you can fetch source code from here.

Useful links

     

Testing at the edge of your App with a Mock Server

The aim of this post is to just present how to build a simple mock server for validating the service calls on your iOS app with unit tests. The components that contains the service calls are at the edge our app and usually are not validated mostly because it is assumed that api is working fine, but this is not always true…

 

The mock server will respond with a controlled response and will also help you to simulate several error status responses or even delays on answers. Android and Windows phone platforms can also take profit on it.  The server will be implemented in node.js, but do not get scared, there is no need a lot of knowledge on this technology.

The server is mocking fixer public API service, and in concrete the following rest API http://api.fixer.io/latest?base=USD

What’s node.js?

Node.js is an open-source, cross-platform Javascript runtime environment for developing a diverse variety of tools and applications. For installing on your mac just type the following commands in your terminal:

$ brew install node
$ npm install express --save

Express  is a web application framework for Node, this will facilitate our task for developing our http server. For writing code, there are many text editors (sublime2atom,…) , but I recommend Visual Studio Code (VSC) because it allows you to debug the code.

The mock server

With VSC just open localMockServer folder, go to debug and press the play button.

vsc

Open your internet browser and type http://localhost:3080/latest in the url, if mock server was started well you should have to see something like this:

resp

Developing iOS service component

Once we have an answer from the server let start to develop the iOS service component. For doing that we will create a simple single view app, please do not forget include support for unit testing.

sva

For network service support I will use Alamofire pod, this is what it was AFNetworking in Objective-C.

For switching between real Fixer server and our mock server I will create a new schema and inside it I will define an environment variable for controlling which baseURL hast to be returned.

sch

baseURL attribute will be calculated in the following way:

    var baseURL:String{
        get{
            if let _ = ProcessInfo().environment["LOCAL_MOCK_SERVER"]{
                return "http://localhost:3080"
            } else{
                return "https://api.fixer.io"
            }
        }
    }

Remember, from now on we will work with mock server so switch to FixerClient-MockServer schema.

sch2

The service implementation is the following:

    public func latest(base :String ,
                       parameterWithDefault: String? = nil,
                       success succeed : @escaping ((DateCurrencyRate) -> ()),
                       serverFailure serverFail : @escaping ((NSError) -> ()),
                       businessFailure businessFail : @escaping ((NSError) -> ())){
        
        var parameters: Parameters = ["base": "USD"]
        if let _ = ProcessInfo().environment["LOCAL_MOCK_SERVER"],
            let param:String = parameterWithDefault {
            parameters["param"]=param
        }
        
        Alamofire.request(self.baseURL + "/latest",parameters:parameters).validate(statusCode: 200..<401).responseJSON { response in
            
            switch response.result {
            case .success:
                if let dateCurrencyRate:DateCurrencyRate = DateCurrencyRate(dictionary: response.result.value){
                    succeed(dateCurrencyRate)
                }else{
                    businessFail(NSError())
                }
            case .failure(let error):
                serverFail(error as NSError)
            }
        }
    }

The second function parameter is optional and only will be used for notifying server which test scenario we want to run. At the moment there are two error test cases, one for reproduce a server error and another for reproducing a business error (json with unexpected structure basically).

Unit testing our iOS app service component

The unit test implementation for forcing business error is the following:

        // Force busines error
        var asyncExpectation = expectation(description: "Force busines error")
        FixerService.sharedInstance.latest(base:"EUR",
            parameterWithDefault:"FORCE_BUSINESS_ERROR",
                success: {
                dateCurrencyRate in
                XCTFail()
            },serverFailure: { (error) in
                XCTFail()
            },businessFailure: { (error) in
                asyncExpectation.fulfill()
            }
        )
        self.waitForExpectations(timeout: 3, handler: nil)

After the rest of unit tests implementation just launch the test:

te

 

Conclusion

With the mock server all your business layer can be validated using unit testing and will isolate your development from backend. For doing this sample project I have used cocoapods 1.1.1 and XCode 8.1. You can download the code here.

Links

     

Scratching image table view controllers

The aim of this post is showing how to fix choppy tableviews when they are showing huge images fetched from the cloud.

 

The App

The app is very simple, just a table view that shows a collection of pictures.

Simulator Screen Shot 28 Aug 2016 17.03.55

The app presents the following problems:

  • The picture size is huge so the scroll must be smooth.
  • There is a high memory consumption, so iOS quick the app out.
  • The pictures are fetched every time that a cell is being presented (not cached).
  • Fetch is not cancelled once the cell is not shown in the tableview due to scroll.

filesizes

The picture resolution is 6144 x 4096.

 

The classical approach

Tableviews (and scrollviews) scroll must be smooth. User would not detect app bandwidth consumption easily, but a bumpy scroll is detected from the very beginning. Here what we have to do is to be sure that image is fetched in background and, once is retrieved, update image view in the main thread.

This is how a regular cell should have to be configured:

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("ReusableCellId", forIndexPath: indexPath)
        
        if let cell = cell as? ImageTableViewCell,
            let  _landscape:Landscape = self.landscapes![indexPath.row],
            let _url = NSURL(string: _landscape.url!){
            
            cell.activityIndicator.hidden = true
            cell.activityIndicator.startAnimating()
            cell.imvLandscape.image = nil
            
            let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
            dispatch_async(dispatch_get_global_queue(priority, 0)) {
                // do some task
                if let _data = NSData(contentsOfURL: _url){
                    dispatch_async(dispatch_get_main_queue()) {
                        // update some UI
                        cell.activityIndicator.hidden = false
                        cell.activityIndicator.stopAnimating()
                        cell.imvLandscape.image = UIImage(data: _data)
                    }
                }
            }
            
        }
        
        return cell
    }

 

Memory consumption

But memory consumption increases in a dramatic (deadly) way:

MemoryConsumption

When you access the NSData, it is often compressed (with either PNG or JPEG). When you use the UIImage, there is an uncompressed pixel buffer which is often 4 bytes per pixel (one byte for red, green, blue, and alpha, respectively). There are other formats, but it illustrates the basic idea, that the JPEG or PNG representations can be compressed, when you start using an image is uncompressed.

This model does not work at all with huge pictures, it is  necessary to work with a different architecture.

The image provider

We will delegate the  work of fetching and processing the image to a image provider class. Every cell will has its own image provider.

imageprovider

We will create the image provider in tableview willDisplayCell method:

    func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath){
        guard let cell = cell as? ImageTableViewCell else { return }
        
        let landscape:Landscape = landscapes![indexPath.row]
        
        guard cache.objectForKey(landscape.url) != nil  else {
            
            let imageProvider = ImageProvider( landscape: landscapes![indexPath.row],width: cell.imvLandscape.frame.size.width*2 ) {
                image in
                NSOperationQueue.mainQueue().addOperationWithBlock {
                    
                    self.cache.setObject(image!, forKey: landscape.url)
                    
                    if(self._isVisible(indexPath, tableView: tableView)){
                        cell.updateImageViewWithImage(image)
                    }
                }
                
                return
            }
            imageProviders.insert(imageProvider)
            return
        }
        
        let image:UIImage = self.cache.objectForKey(landscape.url) as! UIImage
        cell.updateImageViewWithImage(image)
    }

It could be the case that cell will dissapear before image provider ends its tasks. You can cancel the operation done by image provider.

    func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        guard let cell = cell as? ImageTableViewCell else { return }
        for provider in imageProviders.filter({ $0.landscape == cell.landscape }) {
            provider.cancel()
            imageProviders.remove(provider)
        }
    }

In my case I was not interested in doing that because it was highly likely to get back to the dissapeared cell.

Cache the downloaded stuff.

At the end is only necessary to download the image once, not every time that cell is going to be shown. We have implemented this by using NSCache object, this differs from other mutable collections in a few ways:

  • It incorporates various auto-removal policies, which ensures that it does not use too much system memory.
  • You can access from different threads without having to lock the cache yourselve.
  • Retrieving something from an NSCache object returns an autoreleased result.
  • Unlike an NSMutableDictionary object, a cache does not copy the key objects that are put into it.

Profile new architecture

With new architecture the memory consumption lasts in that way:

newmetrics

Awesome, It has been reduced memory consumption by 60!!!

 

Conclusion

There are times that is not under app developer the image size of images that has to fetch. If you use the classical approach then you will find that tableview scroll is choppy and most probaly OS will kick the app out. For avoiding such disgusting issue this architecture fits properly well. You can find the source code here.

     

Validating View Controllers with Quick and Nimble

On arriving  UI automated testing in XCode 7 developers had a great tool for automatically validate our apps.  But as our test suite starts growing we start facing some inconveniences.

By using accessibility interface you cannot validate view controller attributes, for instance validate if you got the right number of cells in a collection. Another problem that I faced was at time of refactoring test cycles took to long.

I strongly believe in testing, but dealing with such inconveniences  pushed me to search for another iOS test frameworks. After watching some videos and hearing about them in some conferences I decided to investigate about validating view Controllers with Quick and Nimble.

The aim of this post is just show how to setup Quick and Nimble test frameworks and play a little bit with them.

Quick and Nimble

Quick is a BDD testing frakework that is almost the same as XCTest, but with the additional focus on describing your intent and why you are testing parts of your code.

Nimble allows you to express expectations using a natural, easily understood language.

Environment

I have found some difficulties downloading sample projects with the framework integrated. So at the time of writing this posts the XCode that I am using is 7.3.1 and the Podfile content is the following:

use_frameworks!

target 'QuickAndNimble' do

end

target 'QuickAndNimbleTests' do
  pod 'Quick'
  pod 'Nimble'
end

target 'QuickAndNimbleUITests' do
  pod 'Quick'
  pod 'Nimble'
end

View controller undertest

The view controller under test shows a collection of Gremlins with a search bar that will allow to filter them by name.

Simulator Screen Shot 31 Jul 2016 00.33.15

 

Test are implemented as a regular UN test, so adding a new test is just adding a new UN test file:

projfiles

untest

As was mentioned before test are implemented as BDD test structure changes a little bit but do not get scared. Lets start  testing the view controller title:

import Quick
import Nimble

@testable import QuickAndNimble

class SpecsSearchCollectionVC: QuickSpec {
    
    override func spec() {
        var controller : SearchCollectionVC!
        
        beforeEach() {
            let storyboard = UIStoryboard(name: "Main", bundle: nil);
            controller =  storyboard.instantiateViewControllerWithIdentifier("SpecsSearchCollectionVCID") as? SearchCollectionVC
            
        };
        
        it("should not be nil") {
            expect(controller).notTo(beNil())
        }
        

        describe ("Collectionview validation") {
            beforeEach() {
                _ = controller.view
                controller.beginAppearanceTransition(true, animated: false)
            };
            
            it("view controlller tilte"){
                expect(controller.title) == ""
            }

First thing to do is import Quick and Nimble and extend our test class from QuickSpec. beforeEach is the chunk of code that will be execute before each test. Tests itself are implemented by specifying with it.

Another important issue is the call controller.beginAppearanceTransition before each test, this execute viewcontroller lifecycle calls before executing test.

Now lets launch test:

redtogreen

But remember we have to move from red to green. Now, just set the expected title string name and re-run the tests.

The first impression that you experiment with this framework is how easy and fast is execute a battery of test. An how easy is get into view controller internal attributes and methods for validating what is going on.

Let’s test that collection view can show all the expected gremlins

The view controller by default will show a hardcoded set of gremlins for better understanding, but that is not the real case scenario. For validating that the first that we do is just validate that the number of items that can see the collection view are 13, and afterwards we inject an array of 3 items for validating that the new number of items that can see the collection view now is different:

            it ("Initial collection view initialization with some data"){
                
                expect(controller.numberOfSectionsInCollectionView(controller.clvCollection)) == 1
                expect(controller.collectionView(controller.clvCollection, numberOfItemsInSection: 0)) == 11
                expect(controller.scbSearchBar.hidden) == false
                
                
                controller.setDataSource(["one","two","three"])
                expect(controller.numberOfSectionsInCollectionView(controller.clvCollection)) == 1
                expect(controller.collectionView(controller.clvCollection, numberOfItemsInSection: 0)) == 3
                expect(controller.scbSearchBar.hidden) == false
            }

Lets look for more gremlins

But the view controller also allows us search gremlins by name, now lets validate that this functionallity is really working:

describe ("Searchbar validation validation") {
            beforeEach() {
                _ = controller.view
                controller.beginAppearanceTransition(true, animated: false)
            };
    
            it ("Do a basic search"){
                
                controller.setDataSource(["one","two","three"])
                expect(controller.collectionView(controller.clvCollection, numberOfItemsInSection: 0)) == 3
                expect(controller.scbSearchBar.hidden) == false
                
                controller.searchBar(controller.scbSearchBar, textDidChange: "one")
                expect(controller.collectionView(controller.clvCollection, numberOfItemsInSection: 0)) == 1
                expect(controller.scbSearchBar.hidden) == false
        
                controller.searchBarCancelButtonClicked(controller.scbSearchBar)
                expect(controller.collectionView(controller.clvCollection, numberOfItemsInSection: 0)) == 3
                expect(controller.scbSearchBar.hidden) == false
                
            }
            
            it ("Do a basic search with empty text"){
                
                controller.setDataSource(["one","two","three"])
                expect(controller.collectionView(controller.clvCollection, numberOfItemsInSection: 0)) == 3
                expect(controller.scbSearchBar.hidden) == false
                
                controller.searchBar(controller.scbSearchBar, textDidChange: "")
                expect(controller.collectionView(controller.clvCollection, numberOfItemsInSection: 0)) == 3
                expect(controller.scbSearchBar.hidden) == false
                
                controller.searchBarCancelButtonClicked(controller.scbSearchBar)
            }
            
        }

An important issue that I want to mention at that point is that or view controller hides the search bar when there are no items. This is very easy to do with this framework, just check .hidden attribute from search bar and that’s all!.

You can download the sample project used in this post here.

Conclusions

With Quick and Nimble you can run a test suit very quickly and this is great for refactoring. On the other hand is direct to have access to view controller internal stuff, this will save you lines of code and execution time on UI testing. So Quick and Nimble is a great alternative to unload test stuff from UI testsuite.

gizmo

Useful links

Model your classes with Argo JSON parser

The aim of this post is just basic introduction about how to use Argo framework for feeding your model classes from JSON data.

What is Argo.

[From https://github.com/thoughtbot/Argo]

Argo is a library that lets you extract models from JSON or similar structures in a way that’s concise, type-safe, and easy to extend. Using Argo, you won’t need to write validation code to ensure that incoming data is of the right type, or to make sure required data fields aren’t turning up empty. Argo uses Swift’s expressive type system to do that for you, and reports back explicit failure states in case it doesn’t find what you’ve told it to expect.

Argo

Argo is the Greek word for swift and the name of the ship used by Jason, son of Aeson, of the Argonauts. Aeson is the JSON parsing library in Haskell that inspired Argo, much like Aeson inspired his son Jason.

Codoapods. First things first.

In the Podfile you will have to add two frameworks, Argo itself and Curry that is being used for saving effort on initializing structs and classes.

# Uncomment this line to define a global platform for your project
# platform :ios, '8.0'
# Uncomment this line if you're using Swift
use_frameworks!

target 'ArgoDeSwift' do
pod 'Argo'
pod 'Curry'
end

 

Parsing structs

In this section through different examples I will explain how to parse the most common JSON structures.

Example 1. Most Basic JSON structure.

The content of the json file is the following:

{
"id": 34,
"name": "Pedroooo",
"email": "pe@fm.com"
}

The modeling struct is the following:

import Foundation
import Argo
import Curry

struct Person {
    let id: Int
    let name: String
    let email: String?
}

extension Person: Decodable {
    static func decode(j: JSON) -> Decoded<Person> {
        return curry(Person.init)
            <^> j <| "id"
            <*> j <| "name"
            <*> j <|? "email" // Use ? for parsing optional values
    }
}

Just a few comments

  • As you can see with curry you save up call the initializer passing all class attributes.
  • <^> is for marking the first attribute, the rest are marked with a <*>
  • <| is for parsing a regular attribute and <|? for the optional ones.

For parsing just:

let user: Decoded<Person> = decode(JSONFromFile("person")!)
  • “person” is just the filename that contains the json.
  • JSONFromFile is a helper method that retrieves the json from the file. At the end of the post you will find a like for downloading whole sample project.

Example 2. 1-n attributes.

The content of the json file is the following:

 [{
  "id": 34,
  "name": "Juan",
  "cars": []
  },{
  "id": 35,
  "name": "Paco",
  "cars": [{"year":2000,"brand":"citroen"}]
  },{
  "id": 36,
  "name": "Salvador",
  "cars": [{"year":2000,"brand":"peugeot"},{"year":2005,"brand":"renault"}]
  }]

The modeling struct is the following:

import Foundation

import Argo
import Curry

struct CarOwner {
    let id: Int
    let name: String
    let cars: [Car]?
}

extension CarOwner: Decodable {
    static func decode(j: JSON) -> Decoded<CarOwner> {
        return curry(CarOwner.init)
            <^> j <| "id"
            <*> j <| "name"
            <*> j <|| "cars" // Use ? for parsing optional values
    }
}

And this one:

import Foundation

import Argo
import Curry

struct Car {
    let year: Int
    let brand: String
}

extension Car: Decodable {
    static func decode(j: JSON) -> Decoded<Car> {
        return curry(Car.init)
            <^> j <| "year"
            <*> j <| "brand"
        
    }
}

Just a comment:

  • <|| is for parsing a collection of items

For parsing just:

let carOwners:Decoded<[CarOwner]> = decode(JSONFromFile("car_owners")!)

Example 4. Another way of parsing JSON file.

The content of json file is the following:

{
    "persons": [{
                "id": 34,
                "name": "Sergio",
                "email": "sg@fm.com"
                }, {
                "id": 35,
                "name": "Remedios",
                "email": "rm@fm.com"
                }],
    "cars": [{
             "year": 2000,
             "brand": "citroen"
             }, {
             "year": 2005,
             "brand": "renault"
             }]
}

The modeling struct:

import Foundation

import Argo
import Curry

struct PersonsAndCars {
    let persons: [Person]?
    let cars: [Car]?
}

extension PersonsAndCars: Decodable {
    static func decode(j: JSON) -> Decoded<PersonsAndCars> {
        return curry(PersonsAndCars.init)
            <^> j <|| "persons"
            <*> j <|| "cars"
    }
}

For parsing the struct just:

let model: PersonsAndCars? = JSONFromFile("persons_and_cars").flatMap(decode)

As you can see the way of calling parser in that case is different but the result is exactly the same.

Parsing classes

For parsing classes I am based on the last struct example, but for clear understanding I will show an example.

This is the json content:

{
"year": 34,
"name": "Chispa"
}

The modeling class:

import Foundation
import Argo
import Curry

class Pet{
    var year: Int = 0
    var name: String = ""
}

extension Pet : Decodable {
    typealias DecodedType = Pet
    
    static func decode(json: JSON) -> Decoded<Pet> {
        let pet = Pet()
        pet.year = (json <| "year").value!
        pet.name = (json <| "name").value!

        
        return .Success(pet)
    }
}

In deep the idea is quite close than with structures, but in case of classes is carried out in a different way.

Finally for calling the parser:

let json: AnyObject = JSONFromFile("pets")!
let pet = Pet.decode(JSON(json))

Conclusion

I hope that throught all those examples you will not find any difficulty for understanting how to do a basic parsing. Please take a look at the library documentation for deeper understanding. You can download the sample project from here.

Usefull links

 

A dropdown view with Autolayout (and a few lines of code)

The aim of this post is just to explain how simple is to make a drowdown view controller using Autolayout (… and a few lines of code also). But believe be, the magic is done by Autolayout. At the end you will have a view controller that will allow to drop down the upper view:

Final

Setup the project

Create a brand new Single View Application project:

Screen Shot 2015-12-23 at 13.46.09

Be sure that Language is swift:

Screen Shot 2015-12-23 at 13.49.35

In the default View controller add two views, one in the top-half and the other in the bottom-half. Finally add a button in the middle of two views:

Screen Shot 2015-12-23 at 14.04.24

I have added some color in the view components just for better clarification.

Autolayout

Top subview. Add the following 5 constraints:

Screen Shot 2015-12-23 at 14.07.19

 

Bottom subview. Add the following 4 constraints:

Screen Shot 2015-12-23 at 14.09.26

 

Button. Add the following 3 constraints:

Screen Shot 2015-12-23 at 14.12.02

Screen Shot 2015-12-23 at 14.13.52

 

Button – Bottom subview. For the following constraint do not forget select Top subview and Button.

Screen Shot 2015-12-23 at 14.15.52

And apply the following constraint:

Screen Shot 2015-12-23 at 14.18.58

Autolayout is giving to you a warning because he excepts that Button and Top subview would be bottom alligned.:

Screen Shot 2015-12-23 at 14.19.40

Our intention is leave the buttom in the middle of two views, so we have to update constraint:

Screen Shot 2015-12-23 at 14.25.10

 

… and a few lines of code

Outlets

 

    @IBOutlet weak var btnFoldButton: UIButton!
    @IBOutlet weak var cnsUpperViewHeight: NSLayoutConstraint!

Now link outlets:

  • btnFoldButton to the button
  • cnsUpperViewHeight to the Top view height constraint.

 

Add pan gesture recognizer to Button:

 override func viewDidLoad() {

        super.viewDidLoad()
...

        self.btnFoldButton.addGestureRecognizer(UIPanGestureRecognizer.init(target: self, action: "panDetected:"))

    }

What we do in the gesture recognizer is just calculate new value for cnsUpperViewHeight constraint, the hard work is performed by autolayout.

class ViewController:UIViewController {

var heightUpperView:CGFloat = 0.0

...

func panDetected(recognizer: UIPanGestureRecognizer){

        if(recognizer.state == UIGestureRecognizerState.Began){

            heightUpperView = self.cnsUpperViewHeight.constant

        }

        let point:CGPoint = recognizer.translationInView(self.btnFoldButton.superview)

        let newHeight =  heightUpperView + point.y

        if(newHeight >= UIScreen.mainScreen().bounds.height * 0.15 &&

            newHeight <= UIScreen.mainScreen().bounds.height * 0.66){

                cnsUpperViewHeight.constant = newHeight

        }

    }
...

 

Finally

Let’s make some make up, just adding some picture at the top subview and a map at the bottom view.

For the picture and the map add the following constraints:

Screen Shot 2015-12-23 at 14.46.35

 

For the map do not forget the import MapKit in the view controller code:

Screen Shot 2015-12-23 at 14.53.20

Finally run the project:

Screen Shot 2015-12-23 at 14.56.24

 

Pan the button and you will see how top view is compressed, giving more room for bottom view.

You can also download the sample project from gitHub.

Variant

If what you really want is just shift the upper view and avoid compress effect on the top view, just remove the top constraint on the picture that is placed at the top subview:

 

Screen Shot 2015-12-23 at 15.03.23

This will be what you get:

Screen Shot 2015-12-23 at 15.04.26

Useful links:

Break up massive view controllers (Swift)

Introduction

MODEL-VIEW-ADAPTER DESSING PATTERN. It is quite common in iOS programming that view controllers begin to grow and at the middle of development you discover that you have a view controller class with hundreds or even thousands of line. This is the common scenario where the view controller, apart from dealing with its controllers (uitableviews, uitableviews, hierarchy of views,…), has also to process data for being properly presented attend to notifications.

 

The aim of this post is to explain an approach for breaking up view controllers into different design classes and provide them different responsibilities for practically leave the view controller with the responsibility of setup its view controller and filling its ui controllers when necessary.

Class design

MVC approach

MVC

This approach is the most convenient case that the amount of information that you have to present in the view is quite reduced.

MVA approach

mva

 

This other is the most convenient when you have to deal with more than one dataSource in the same view controller, and also the origin of the data to show come from different sources (a data base, internet request, some costing data process,…).

Responsibilities:

View. As always, show the content views.

View Controller. In this approach, setup its uicontrols (tableviews, collection views, a view hierarchy, …) and attend its events. This is not something new, but what is new is that is responsible of being delegate of an Adaptor class and implement its delegated methods. Those delegated methods are basically informing view controller that there is new data to show in the view.

ModelView. Is the model data to be shown in the view.

Adaptor. Is the responsible for starting the processes for retrieving data and providing it to Model Data. Once there is some data to show is provided to viewcontroller via delegate.

AsyncOperation1,…n. Are asynchronous operation for retrieving data from elsewhere. In the worst case scenario this action will take time.

As you can see the View Controller get slimmer by moving part of the code that it performed in MVC approach to Adaptor and AsyncOperation classes.

The template

For proving you that concept you can take this sample project that implements what I have exposed.

 

 

Custom uitableview cell in Swift

The aim of this post is to show how to build a Custom SWIFTed TableViewCell view cell. I have found several shallow examples with the default cell. But soon you will discover that will not fit a real sample project situation. I have found several difficulties from moving to Swift, that took me more time than I expected and that pushed me also to write this post.

The custom table view cell

I have just created a new Single View Project Application  in the default view controller  and added a new NSObject class that extends from uitableviewcell.

Captura de pantalla 2015-07-10 a las 18.54.54

 

Captura de pantalla 2015-07-10 a las 18.56.24

 

The storyboard

I have added a table view controller and a tableview cell with an image view and a label.

Captura de pantalla 2015-07-10 a las 19.02.50

Now is time to setup the custom table view cell. Firstly the  new  class associated to the cell:

Captura de pantalla 2015-07-10 a las 19.07.15

And secondly set the cell identifier:

Captura de pantalla 2015-07-10 a las 19.07.40

The View Controller

Now it is time for connecting the storyboard with the source code. Lets start off with the main view controller:

import UIKit

class ViewController: UIViewController, UITableViewDataSource,UITableViewDelegate {
    
    @IBOutlet weak var tbvData: UITableView!
    
    var items: [String] = ["We dkfj ld flkasjlfasjlkfj  askfksj kj s sjkjf lasjlfsj lfjljl jlk lk", "Heart asan ,nas ,fn ,masn ,mfnas ,mfn m,sanf,m nnj  asn sa ,ansmfnamf ma nfmnamsdfnma,snfdman,dfmn am nfmnasmdnmsfn masnmf nsmfn mn fdm", "Swift msandmf,an ,mf nasmnf m asnm,fn asmnf kjasnfasnf,mna,mna ,fn ,fn ,mfn,mfan f,amnaf,m nfadm,fn m,fan ,mfan,adf"]
    var images: [String] = ["Pic1","Pic2","Pic3"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        setupUIControls()
    }
    
    func setupUIControls(){
        
        tbvData.delegate=self;
        tbvData.dataSource=self;
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    //MARK - UITableViewDataSource
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        
        return items.count;
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
        
        
        let cell = tbvData.dequeueReusableCellWithIdentifier("CustomCellId", forIndexPath: indexPath) as! CustomTVC
        
        cell.configure(text:self.items[indexPath.row], image: self.images[indexPath.row])
        return cell
    }
    
    //MARK - UITableViewDelegate    
}

I have mapped the tableview to tbvData, and added the minimum uitableview delegates. The table view is filled with 3 elements contained in two arrays (items and images).

The table view cell

In the custom cell I have added an image view and a label as an example. This is the code that  configures the cell:

import UIKit

public class CustomTVC: UITableViewCell {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var img: UIImageView!
    
    public func configure(text text: String, image: String) {
        label?.text = text
        img?.image = UIImage(named: image)
    }
}

 

Finally

Captura de pantalla 2015-07-11 a las 14.58.34

You can get also find the code here

Singleton dessing pattern in a template (Swift)

The aim of this post is just complement Singleton design pattern in a template post , but in Swift.

Singleton implementation class

import UIKit

class MySingletonClass: NSObject {
    
   static let sharedInstance = MySingletonClass()
    
    override init() {
        print("MySingletonClass.init()")
    }
    
    func giveMe5()->Int{
        return 5
    }
}

 

Not that in Swift ‘dispatch_once’ is no longer necessary, as in Objective-C. Static constants in Swift, internally does it. So this is an issue that you do not have to worry about.

Template usage

This is how the pattern is used.

        MySingletonClass.sharedInstance
        print(MySingletonClass.sharedInstance.giveMe5())

 

Conclusion

As you can see Swift language structure facilitates a lot Singleton design pattern implementation. You can get the project source code used for writing this post here.

NSUserDefaults best practices

Following previous post and observing in many projects how NSUserDefaults settings are handled I have decided to write this NSUserDefaults best practices.

If you look for information about how to set/get any value in the default storage you will get this:

NSString *valueToSave = @"someValue";
[[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:@"preferenceName"];
[[NSUserDefaults standardUserDefaults] synchronize];

and for getting the value:

NSString *savedValue = [[NSUserDefaults standardUserDefaults]
    stringForKey:@"preferenceName"];

Easy, Is not it? The problem appears when there are many attributes deal with with the sets and gets scattered along the code and you want set break points for trapping when this attribute is being accessed.

Proposal

What I propose is to wrap this functionality in a single class that concentrates all the attributes that we want to get/set from the default storage system.

This is the declaration .h:

#import <Foundation/Foundation.h>

@interface ManagerSettings : NSObject

+(ManagerSettings*) sharedInstance;

@property (nonatomic, assign) int attributeName;

@end

Its implementation .m:

#import "ManagerSettings.h"

@implementation ManagerSettings


+(ManagerSettings*)sharedInstance
{
    static ManagerSettings *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[ManagerSettings alloc] init];
        // Do any other initialisation stuff here
    });
    return sharedInstance;
}

#pragma mark - Properties

static NSString *const kAttributeName = @"attributeName";

- (int)attributeName
{
    return [[[NSUserDefaults standardUserDefaults] objectForKey:kAttributeName] intValue];
}

- (void)setAttributeName:(int)value
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[NSNumber numberWithInt:value] forKey:kAttributeName];
    [defaults synchronize];
}

@end

The class is implemented as a singleton and for each attribute are overwritten set (and get) methods. In that way in a unique place the attribute is set (and get) into (from) the storage system.

And its usage:

    [ManagerSettings sharedInstance].attributeName=5;
    NSLog(@"%d",[ManagerSettings sharedInstance].attributeName);

The access to the attribute is more clean and in a unique class file we have all the system storage functionality concentrated. You can download the project used for writing this post here.