Search Your Question

Difference between MVC and Viper architecture

What is MVVM?

MVVM - Model View ViewModel

Advantage : 

Better Separation of Concerns
In a project built with the Model-View-Controller pattern, you are often faced with the question which code goes where. Code that doesn’t fit or belong in the model or view layer is often put in the controller layer. This inevitably leads to fat controllers that are difficult to test and manage.

The MVVM pattern presents a better separation of concerns by adding view models to the mix. The view model translates the data of the model layer into something the view layer can use. The controller is no longer responsible for this task.

Improved Testability
View controllers are notoriously hard to test because of their relation to the view layer. By migrating data manipulation to the view model, testing becomes much easier. Testing view models is easy. Because a view model doesn’t have a reference to the object it is owned by, it easy to write unit tests for a view model.

Another, and often overlooked, benefit of MVVM is improved testability of view controllers. The view controller no longer depends on the model layer, which makes them easier to test.

Transparent Communication
The responsibilities of the view controller are reduced to controlling the interaction between the view layer and the model layer, glueing both layers together.

The view model provides a transparent interface to the view controller, which it uses to populate the view layer and interact with the model layer. This results in a transparent communication between the four layers of your application.

There are some rules you know when using MVVM

Rule1 : The view does not know about the controller it is owned by. Remember that views are supposed to be dumb. They only know how to present the data they are given to the user.
Rule 2 : The controller does not know about the model. This is what separates MVC from MVVM.
Rule 3 : The model does not know about the view model it is owned by.
Rule 4 : The view model owns the model. When using the Model-View-Controller pattern, the model is usually owned by the controller.
Rule 5 : The view controller owns the view. This relationship remains unchanged when using the Model-View-ViewModel pattern.
Rule 6 : And, finally, the controller owns the view model. It interacts with the model layer through one or more view models.

Download task when app is inactive

 https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_in_the_background


For the background download, there is beginBackgroundTaskWithExpirationHandler: that is specifically designed to do that. When you use it, you will get few more minutes to execute whatever you need (after that limit, your application will get terminated no matter what).

You can write following methods:

func beginBackgroundTask() -> UIBackgroundTaskIdentifier {
    return UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({})
}

func endBackgroundTask(taskID: UIBackgroundTaskIdentifier) {
    UIApplication.sharedApplication().endBackgroundTask(taskID)
}

When you want to use it, you just simple begin / end the task when starting / finishing the download call:

// Start task
let task = self.beginBackgroundTask()

// Do whatever you need
self.someBackgroundTask()

// End task
self.endBackgroundTask(task)

Hope it helps!

What is SSL Pinning and How to implement it?

SSL stands for Secure Socket Layer, which is a protocol for creating an encrypted connection between client and server. It ensures that all data pass in network will be private and integral.

How SSL works? When client establishes the connection with server (called SSL handshake):

  1. Client connects to server and requests server identify itself.
  2. Server sends certificate to client (include public key)
  3. Client checks if that certificate is valid. If it is, client creates a symmetric key (session key), encrypts with public key, then sends back to server
  4. Server receives encrypted symmetric key, decrypts by its private key, then sends acknowledge packet to client
  5. Client receives ACK and starts the session

Using SSL, the client will allow the connection only from trusted sources that have the valid certificate. And it looks good for most cases. But what if someone stands between client and server, and acts like they are the real server? Let's call client is C, server is S and the attacker is A.

In step 1, instead of sending packet to S, A can catch the packet and pretend it as S. What if instead of receiving certificate from S, client C will receive fake certificate from A and believe it's valid. A can make C think that it is communicating with S, but actually all connection flows will be directed to attacker A.

Hence, SSL pinning can be the solution to prevent Man-In-The-Middle (MITM) attack. SSL pinning will ensure that client connect with designated server. The main key of SSL pinning that server certificate will be saved in app bundle. Then, when client receives certificate from server, it then compares 2 certificates to make sure that they are the same before establishing the connection.

URLSession

For NSURLSession, the main method to handle SSL pinning is URLSession:didReceiveChallenge:completionHandler:delegate. Set your class to conform URLSessionDelegate and paste this function to your class:


func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
        if let serverTrust = challenge.protectionSpace.serverTrust {
            var secresult = SecTrustResultType.invalid
            let status = SecTrustEvaluate(serverTrust, &secresult)
            
            if (errSecSuccess == status) {
                if let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) {
                    let serverCertificateData = SecCertificateCopyData(serverCertificate)
                    let data = CFDataGetBytePtr(serverCertificateData);
                    let size = CFDataGetLength(serverCertificateData);
                    let cert1 = NSData(bytes: data, length: size)
                    let file_der = Bundle.main.path(forResource: "name-of-cert-file", ofType: "cer")
                    
                    if let file = file_der {
                        if let cert2 = NSData(contentsOfFile: file) {
                            if cert1.isEqual(to: cert2 as Data) {
                                completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust:serverTrust))
                                return
                            }
                        }
                    }
                }
            }
        }
    }
    
    // Pinning failed
    completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
}

This function will “requests credentials from the delegate in response to an authentication request from the remote server.” We will compare the certificate from server with the one that saved in app bundle. If 2 certificates are identical, the authentication will let it pass and client can connect to server.

Types of SSL Pinning(What to Pin)?

Pin the certificate: You can download the server’s certificate and put this in your app bundle. At runtime, the app compares the server’s certificate to the one you’ve embedded.

One disadvantage of SSL pinning is that you have to save the certificate in the app. Whenever the certificate is updated, we need to release new version of app. But this also leads to another problem: what we do with older version?
  • Maintain the old certificate for a time, until we make sure all users have downloaded new version already.

Pin the public key: You can retrieve the certificate’s public key and include it in your code as a string. At runtime, the app compares the certificate’s public key to the one hard-coded hash string in your code.

Explain NSOPERATION Priority.

Ans : 

All operations may not be equally important. Setting the queuePriority property will promote or defer an operation in an NSOperationQueue according to the following rankings:

public enum NSOperationQueuePriority : Int {
    case VeryLow
    case Low
    case Normal
    case High
    case VeryHigh

}

The operations with high priority will be executed first.

let backgroundOperation = NSOperation()
backgroundOperation.queuePriority = .Low

let operationQueue = NSOperationQueue.mainQueue()
operationQueue.addOperation(backgroundOperation)