Wednesday, 14 September 2016

Simple, Effective and Robust Network model for iOS applications in Swift (using Protocol Oriented Programming)

Hi,

Most of the time every single app that we develop in iOS usually deals with tons of network calls. We always take the shelter of third party frameworks such as Alamofire for swift or AFNetworking for Objective-C to handle such network calls.

Though these frameworks do a great job by taking care of all the boiler plate codes for us, we usually end up writing web service calls in multiple ViewControllers or in Controller classes, which will result in code duplication and also will raise the issue with maintenance of the code.

Issues with maintenance of the code?? But How??

Lets assume you are following MVC pattern and you have Controller class for each ViewController, which behaves as a mediator or a broker between ViewController and Data source, so its quite apt to keep the web service calls related to LoginViewController in its Controller.

So Lets create a LoginController class,

Whats happening in here???
Simple! We have a method name loginUser which takes username, password and success block as its arguments and assume that our loginUser method simply tells LoginViewController whether the login was successful or not ( I know thats a dumb thing to do!! but for this demo its fine I believe).

All that loginUser method does is, it hits the url "http://idontknowurl.com/getUser" using a .GET method and passes

["username" : "abcd",
 "password" : "1234"]

as its parameter, parses the login response, does all the magic it has to do to deal with success and failure cases, configures the loggedInUser instance and finally tells LoginViewController whether the login was successful or not by executing the closure with a boolean parameter.

Now lets see the User class,


User class is pretty straight forward, there can only be one logged in user per session, so I have a static variable named loggedInUser and have private implementation of init() to make sure that there can only be one instance of loggedInUser through out the application life cycle, declaring private init() ensures uniqueness of the loggedInUser instance for the entire life cycle.

User class has a method named configureUser as the name suggests, all it does is to configure the unique loggedInUser instance.

Now where is the issue here ??

Though there is an inherent issue here with this model, it is not significant enough to get noted easily, so lets try adding two more classes to understand the issue, what say?

As we are done with login now, lets consider fetching user profile info, Savy ?

Aye Captain!!

Lets create a class called UserProfileViewController as usual we will create a Controller class for it, lets call it as UserProfileController and will move fetching user profile info web service call to this class.

Now that we have user profile info, lets fetch the friends list for the logged in user, So lets create FriendsListViewController, and create its associated controller class and name it as FriendsListController,

now assume that fetchFriendsList fetches all the friends of the user based on the friendsLevel parameter, and in here we are fetching all the contacts of the user based on his gmail id.

Issue :

1. Did you see whats happening here, same code,
is being repeated in almost every single controller, don't you think that needs to optimised and kept in a single place?

2. Parameters like userId is being repeated in almost all the requests, isn't it redundant to place such parameters for all requests? Don't you think these parameters be declared as a default parameter and all requests should simply just get it by default ?

3. Authorisation headers like ["username" : "username", "password" : "password"] is common for all requests except login request, again is it not un-necessary to place these code for each requests again and again, isn't there a better way to declare them as default headers ?

4. What if tomorrow your server team says, there is another default parameter/header parameter that you need to send for each request, say ["xyz" : "abc"], what will you do ? You will open up every single controller and add this the default parameter to each request !!! What if your app is network call intense and you have 100 such calls happening, so you gonna change in 100 places and test every single web service call to ensure you din mess up anything ?? "May God help you :P"

5. Finally, what if tomorrow apple changes the underlying network API's itself, like it did with the release of iOS8, NSURLConnection was replaced by NSURLSession, or the third party framework you were using decides to change the network API itself, like AFNetworking 2.0 changed its API to be compatible with apple's network API changes,  don't you think you are kinda screwed!! You will have to now re-visit every controller that has network call and update every single API.

Fine! How to solve it then ?

There is no absolutely correct or the perfect solution to it, as designing your application architecture is a very creative task and it is even possible that every developer might perceive and design their app in a way that they find it feasible. Your application arctitecture evolves with your experience in developing the app, with your evolving skill set and finally with your evolving perspective towards the coding paradigm as a whole.

Am not the expert here, but here is how I design my Network model and it works pretty much awesome to me.

Before we go ahead and design, this network model can be designed easily using traditional inheritance, but because we are dealing with swift, which prefers a protocol oriented programming over object oriented programming, I am gonna extensively make use of protocols and structs.

Now What the hell is Protocol Oriented Programming ???

If you have not heard of this phrase before, and yet you are developing the app in swift, then there is very good chance that you might have misunderstood the Swift completely.

Though explaining the Protocol Oriented Programming is not in the scope of this tutorial, I strongly recommend you to go through WWDC 2015 video on "Protocol Oriented Programming in Swift". Here is the link to the video : https://developer.apple.com/videos/play/wwdc2015/408/

If you don't prefer spending your 45 minutes, watching the WWDC video, you can still continue to read the blog, but you might leave your self wondering, why the hell blogger is writing so much of code to achieve something, which he could have simply achieved by using inheritance, but believe me its worth trying something new :)

Is it necessary to design it in Protocol Oriented Programming ??  

Absolutely not!! I believe whether to use Object Oriented Programming or Protocol Oriented Programming is absolutely a trade off, In certain situation sticking with traditional Object Oriented Programming might make more sense than achieving the same thing with Protocol Oriented Programming.

But trying out something new, is always the perk of this job!! Isn't it? Hence designing this model in complete compliance with Protocol Oriented Programming.

Enough of this theory, Lets get started!!!

First principal of Protocol Oriented Programming, start with struct not with class!!
Lets create a BaseRequest struct then

Now that should be straight forward, I have everything that is needed to create a Alamofire Request as a property of struct named BaseRequest. init() method of the BaseRequest provides the default values for the parameters like baseURL, method,parameterEncoding,parameters and headers.

Default value for the baseURL is being read from the Constant class, method is by default set to .GET, parameterEncoding by default set to URL Encoding.

Whats important here though, is the initialisation of parameters and header fields. As we have seen in the above examples, excluding loginRequest all other request requires the headers and excluding loginRequest all other API's expect "userId" in parameter. So I am checking if the logedInUser instance has been initialised properly or not, if yes then I'll add username and password to default headers else I set the headers to empty dictionary. Similarly, If  logedInUser instance has been initialised properly, then I'll set userId as default parameter else I initialise it with empty dictionary. I hope it makes sense :)

Now BaseRequest looks great, but it in itself is of no use, because it is a struct, no other struct can inherit it,  so all the initialisations that we have made so far is only limited to BaseRequest struct itself.

Wait! So everything we wrote till now is useless?

Nope! here comes the protocol, corner stone of swift programming language! After all, Swift is a Protocol Oriented Program man!!

Lets create a BaseRequestProtocol,

Hmmm, whats that now!! It is a very simple protocol with a property of type BaseRequest.

Again, though the protocol in itself is of little help here, but it does not actually do what we want to achieve, isn't it ?

But then, we are dealing with swift, and Protocols in swift can provide default implementations as well. Woooooo hoooooo!!! Yeah, thats a great news now.

Lets go ahead and write a default implementation of BaseRequestProtocol

Now wait a second, thats a hell lot of a code there!! What does that even mean??

Simple, by declaring the property baseRequest in BaseRequestProtocol we mandated all the class/struct that extends  BaseRequest protocol should also declare a variable of type BaseRequest, and because setter and getter is exposed, all the class/struct that extends the BaseRequestProtocol can provide their own values to this property.

Now in default extension, we declare multiple variables whose setter and getter we override. By providing these variables in default implementation and not declaring it in protocol declaration we made these variables available to all the class/struct that extends the  BaseRequestProtocol and yet need not declare these  variables, they can access these variables as if they have been inherited from the parent/super class.

Now we are getting somewhere!!

All other setter getter are pretty much self explainable, they read the value of parameter from BaseRequest and return it in getter and set the new value passed to the appropriate BaseRequest property.

Though most of the setter and getter are simple, what is most important to notice is the implementation of parameters and headers properties setter and getter.  Setter and getter of the headers and parameters properties are identical, so it is enough, if we analyse any one of them.

Lets consider the setter and getter of Parameters property,
Getter is pretty much simple, simply return the parameter property of baseRequest, setter has a little trick, remember we set the userId as default if the logedInUser is set with appropriate values, now assume that I have to hit a API, which does not take any parameter at all, but because your logedInUser is configured userId comes by default, now most of the API at web end ignores such parameters, but what if you are stuck with some psychopath web API developer who says "Just Don't send it!!!" how to remove it then ? Simple, in the setter of parameters I am checking if the newValue is nil or not , if it is nil, then I'll clear the default parameters from baseRequest, else I simply update whatever user passed to baseRequest's parameter property.

Look carefully I am updating the values to baseRequest's parameter, So if user overrides some default value, the new value will be applied to baseRequest's parameter, if user adds a new key value pair, it gets added to baseRequest's parameter and finally if user won't provide any value to the default parameter, the existing value will persist.
Note : What If I want to remove only certain keys from default parameter while keeping the rest untouched? Thats easy to implement as well, try it on your own! if you find difficulty you know where to find me :)

Yeah, you are almost done with the request object!!!!
Lets create a LoginRequest using the BaseRequestProtocol, what say ?

Thats it, you have the login request ready! All you need to provide was the parameter that you wanted  to send and specify the endPoint!!

Hmmm thats good, but lets consider creating getUserProfile and getFriendsList request as well.

Thats all, you have your getUserProfileRequest ready, no need to pass userId to parameter, because we have added it as default parameter, so it will be available by default, Same is the case with headers as well.

Now lets consider a little tricky getFriendsList request, now along with userId we need to send friendsLevel as well in parameter.

Thats it!! Just pass the parameter that you want to add to default parameter and rest will be taken care off for you :)

Request is ready, but this request is hardly of any use in itself, its not even Alamofire request!! What we need now is WebServiceManager

Woo hoo! Thats all you need :)
WebService manager makes use of Alamofire Manager to create a AlamofireRequest from the BaseRequestProtocol and finally uses the created alamofire request to hit the web service and get data from server
Note : With a very little tweak to your BaseRequestProtocol, you can also add fileUpload and fileDownload capability to WebServiceManager. Try it your self. If you have an issue, you know how to reach me, Don't you ? :)
Now lets use this WebServiceManager in our LoginController and see how it goes along ?

Now how's that, huh? Still not convinced lets update UserProfileController

finally lets update FriendsListController

Woo hoo !! Thats all you are done with your network model buddy :)

After all these circus, the only question we need answer for is, Is all these code required? What is the benefit that we get with this ? How is it anyway better than the earlier approach ?

Here is my opinion on the issues I had iterated earlier :

1. Did you see whats happening here, same code,
is being repeated in almost every single controller, don't you think that needs to optimised and kept in a single place?
Code is no longer duplicated, Code to create a Alamofire request and Code to hit the web service is kept isolated and in one position. No Controller has to write the same code again and again anymore.

2. Parameters like userId is being repeated in requests like getFriendsList and getUserProfile, isn't it redundant to place such parameters for all requests? Don't you think these parameters be declared as a default parameter and all requests should simply just get it by default ?
3. Authorisation headers like ["username" : "username", "password" : "password"] is common for all requests except login request, again is it not un-necessary to place these code for each requests again and again for all requests, isn't there a better way to declare them as default headers ?

Addition of default headers and parameters to base request ensures that all the requests gets these values by default, and no need to pass them again and again for each request.


4. What if tomorrow your server team says, there is another default parameter/header parameter that you need to send for each request, say ["xyz" : "abc"], what will you do ? You will open up every single controller and add this the default parameter to each request !!! What if your app is network call intense and you have 100 such calls happening, so you gonna change 100 places and test every single web service call to ensure you din mess up anything ?? "May God help you :P"
All you have to do is to add an extra key value pair to the default value of parameter property of BaseRequest. Thats all! All other 100 requests gets it for free!!

 5. Finally, what if tomorrow apple changes the underlying network API's itself, like it did with the release of iOS8, NSURLConnection was replaced by NSURLSession, or the third party framework you were using decides to change the network API itself, like AFNetworking 2.0 changed its API to be compatible with apple's network API changes,  don't you think you are kinda screwed!! You will have to now re-visit every controller that has network call and update every single API.
As mentioned earlier, entire code to create a alamofire request from BaseRequestProtocol and hitting the web service get the data from server is kept isolated and contained in one file in our case WebServiceManager.  If any the underlying API changes for whatever reason, all you have to change is WebServiceManager's createAlamofireRequest or getResponseFromRequest.

Bonus :

Unit testing your Network model is much simpler now, and you can establish the trust to whatever level you prefer very much easily with this network model. Unfortunately how to write unit test is not in the scope of this article, more about it some other time.

I know this isn't the perfect model, but works pretty good for me, I would love to know your opinions on it. Please leave your comment below.

Sunday, 4 September 2016

Can Core data be trusted with sensitive informations?

Hi All,

Recently completed 4 years of my professional career as iOS developer. I started working on core data from my 2nd app onwards. For past 4 years, almost every single day I had to deal with core data and honestly speaking I felt like I knew in and out of core data until a question asked by my new boss seems to have shattered my whole confidence.

What the hell did he ask then ?? Yeah, you guessed it right!! The same question that we are trying to find solution for, in this blog.

"Can Core data be trusted with sensitive informations?!! Can you assure me that no body else gets an access to the data in core data except our app? What If somebody gets an access to the app bundle and copies the .sqlite file and opens it ??"

My answer was "Yeah!! I mean, most of the apps in iOS makes use of it, it should be secure ! I didn't test it though, I guess Core data takes care of the data security, it does right ??? In fact I don't know!!! never thought it that way".

A little bit of browsing landed me on the official Apple docs page on "Persistent Store Types and Behaviours" and hardly two minutes of reading changed my perception of core data and its security. Here is what Apple docs says :
Core Data makes no guarantees regarding the security of persistent stores from untrusted sources (as opposed to stores generated internally) and cannot detect whether files have been maliciously modified. 
Now considering that my app deals with the sensitive data of my clients, security of which I could not have compromised with, I really started questioning about the relevance of usage of core data in my app.

But if not core data then what else to use?? My app deals with multiple threads constantly changing the data, Core data provides me a thread safe persistent storage, now the over head of creating a thread safe data storage system with capability to hold the data persistently was immense and un-necessary.

So the only solution left was to find how to make core data secure :)

Let's Secure Core Data :

Solution 1 : Persistent store encryption using Data Protection

Here is the quote from the book Pro CoreData for iOS by Michael Privat and Robert Warner.
One of the security options that iPhone provides is hardware-level disk encryption. Apple calls it data protection. When enabled, it encrypts a portion of your disk when the device is locked and is automatically decrypted when the device is unlocked.
Though that sounds very much sweet, it isn't good enough to leave our data base security completely on it, Isn't it. Why is that???

1. Data protection needs to enabled manually by the user of the app by enabling Passcode security. Thats bad isn't it ?? How can you ask your apps user to enable the Pass Code protection? What will you say  "Sorry, We couldn't code to protect your data so we are leaving it to you and to apple to take care of it!!" ?.

2. As apple is expanding its customer base every day by day, you can't expect all the customer to be of same technical intelligence. Most your app user might not even know that there exists an option called " enable the data protection"!!, In fact I din knew it my self. How can we explain them the importance of it and convince them to enable it and leave the data unprotected on some un-secured device as it is.

3.The data is secure as long as nobody knows the passcode of the user's device. Once a valid passcode has been entered the data gets decrypted. So the app's data is as much secure as the device it self.

Now you might be wondering what a moron the writer is! Once the hacker/attacker enters the passcode and gets an access to the device won't he open up the app and see the data? Now if your app is dumb enough to show all the sensitive data without asking the user to go through any of the app specific security measures then no body can save your app.

On the other hand if you app has its own security measures to provide the access to sensitive data like having its own passcode lock or finger print scan security then your app might not give an access to the secure data.

But because data protection decrypts the file, if the hacker gets the access to the app bundle by using any of the various s/w available he can open up the .sqlite/.xml/or any other custom format file you have and can see all the secure info your app has collected in core data.

4.Finally the last point nails the last nail on the coffin of "data protection" feature. Here is the quote form the same book Pro CoreData for iOS by Michael Privat and Robert Warner.

Another inconvenience with this method is that for very large databases, the time it takes to unlock and start your application might be rather large since a huge file will need to be decrypted before it can be used.
Now you don't want your data protection to slow done the launch of your app or slow down some body else's device don't you ??? We are all aware of consequences we might have to face with that :D

Though I only enumerated the cons of data protection, it does a fair job from its perspective. It does encrypt the data once the device is locked and decrypts it when the device is unlocked for free to all the apps which wants to avail this security.

Though enabling the Data Protection hardly needs few lines of code in your existing app, covering it is not in the scope of this article. I'll discuss about it, sometimes later.

Solution 2 : Encrypt the Data in Core Data.

Though the solution.1 talked about encrypting the whole file it self, it is always possible  only to encrypt/decrypt the data that application puts in into the files rather than encrypting the whole file itself.

How can I do that??

Though core data, in itself does not do much to encrypt the data, it never stops you from doing it either, If you ever try to do so.

Here is how you can do it.

Let's consider a simple Core data entity "Person". This is how a typical Core data entity model looks like.



Now lets add a person to core data using code,


If we open up the .Sqlite file using the apps like SqliteBrowser, this is how you will see the data.








Now that's quite obvious, Isn't it?

Now lets assume the phone number and the nick name are very much sensitive informations and you don't want any one else other than your app to read it. So Let's encrypt them.

Modify your Core data model for Person entity as shown below.



Select the fields nickname and phone and change the data type to Transformable. Now open up the property inspector and click on nickname field, you should see something like,


Now the most important part!!. See that Name field below Attribute type drop down in property inspector, Enter EncryptedStringTransformer and hit enter. Repeat the same steps for phone field as well.

Now what the hell is EncryptedStringTransformer??

Don't worry! Its the name of the NSValueTransformer subclass that you are going to create in a while.

As the purpose of this tutorial is to show how to encrypt the core data and not to explain the encryption itself, I am using a open source Cross platform AES encryptor. Here is a link to its github repository : https://github.com/RNCryptor/RNCryptor

Selection of the encryption algorithm completely depends on your application requirement. There is no restriction imposed by core data as to which encryption algorithm to use to encrypt the data. So go ahead!! Find the algorithm that suites you the most and use it.

Now, for this article, lets go ahead and add the RNCryptor to the project. I am making use of cocoa pods in here, go ahead and use either Carthage or install it manually, whichever way you feel comfortable,


Now lets create the EncryptedStringTransformer about which we discussed just a while ago.


Now go ahead and override transformedValue and reverseTransformedValue methods of NSValueTransformer. These two methods gets called when your application tries to enter the data to /read the data from core data respectively.

Remember you specified EncryptedStringTransformer as the name of the transformer function for the fields nickname and phone, now whenever your application tries to enter the value for these two fields transformedValue function of EncryptedStringTransformer gets called and gives you a chance to transform the raw data to whatever you want. What we do in here is take the plain text, run the RNCryptor and convert it to cipher text and return the NSData.

Similarly, whenever your application tries to read the data from these two fields, reverseTransformedValue function gets called and asks you to reverse the transformation you applied before and return the original data. What we do here is very simple, we decrypt the cipher text, convert it to plain String and return it.

That's it!!! Now your Person entities nickname and phone fields data are encrypted. Lets insert the data to Person entity using the same code I posted above. Everything works just same as before, except for the .sqlite file fields value. Now if we open up the .Sqlite file,





Woo hoo!!! Can you see that nickname and phone fields no longer has text, instead now it says "BLOB".

Solution 2 over comes the issues in Data Protection. Now the data in .sqlite file will remain encrypted no matter whether the device is locked or unlocked. No other application can read the data from .sqlite file as it will not be knowing the encryption algorithm and the key used to encrypt the data. So only your app can read the data.

Though the solution 2 does what it says, it might not always be the perfect solution for securing the core data.

Hang on!! Now why is that??

1. Though it encrypts the data in .sqlite file, leaves the .sqlite file itself unprotected. Attacker still has an access to the schema of the data base or Core data model.

2. Though attacker can't read the data, solution 2 does not prevent him/her from corrupting the .sqlite file itself and hence causing the app to compromise the data security or might affect the functioning of the app itself.

3.Now the quality of encryption directly depends on the algorithm your app chooses to encrypt the data. Weaker the algorithm less secure is the data.

4.Encryption and decryption happening in NSValueTransformer's transformedValue and reverseTransformedValue obviously affects the application performance. More intense the encryption algorithm, much slower output from core data hence much slower the app.

Solution 3 : Using NSInMemoryStoreType persistent store to save sensitive data.

Securing the core data need not only mean encrypting the file. What if we can make use of Core data to its fullest potential and yet not save a word on file in file system?

Yes! Solution 3 talks about using the NSInMemoryStore as persistent store. As the name suggests persistent store used by core data is no longer a .sqlite file, instead persistent store is memory itself.

Now if you are not aware, Sqlite is not the only persistent store type supported by core data. Core data supports 4 Persistent store types.

1. In-memory : Here the entire object graph is kept in memory. Hence this is one of the fastest persistent store available. As nothing is stored on disk, it completely eradicates the question of some other application gaining the access to the data your app collects and saves it in core data.

2. SQLite : This is one of the most commonly used persistent store type. Core data makes use of Sqlite under the hood to to keep the data persistently. .Sqlite file gets created usually under the applications document directory which holds the data for each field in core data entity which we normally open up and browse using Sqlite browsers. Only partial object graph is kept in the memory.

3.Binary (atomic) : You can make use of this store type, if you want store writes to be atomic.

4.XML (atomic) : You can make use of this store type, if you want to create a human readable and externally passable data store. It is very much common to make use of this data store in the initial days of development and then to move on to SQLite data stores once the app makes its way to production. Sad news for iOS developers, XML is store type is not available for iOS till this day. 

Not all the data in core data may be sensitive to the user. For example, lets assume that a part of your app deals with users credit/debit card details or deals with users bank account informations. So for your app sensitive informations are the credit/debit card details or bank account informations. Informations like user's comments, users friends list or user's subscription list may not be that sensitive.

So rather than trying to secure the whole core data lets focus on securing only the part of it which actually requires the security.

To explain it lets consider a scenario. Continuing on the same example that I mentioned above. Lets add another entity to core data and lets call it Account info.




Each person can hold multiple accounts and each account belongs to one person.

Here the information like name, age may not be so important to the user, but information like account number, amount held in that account may be very much sensitive. So lets try protect the AccountInfo entity data from being accessed by the attacker or other apps.

How can I do that??

Simple, Lets open up the core data model. On the left corner, there is a button called Add Entity, Click and hold on it, till a popup appears, now select Add Configuration.



You will see a new Configuration being added. Lets name it as InMemory. Repeat the steps and create another configuration named SQLStorage

Once you are done you must be able to see 3 Configurations. 
1.Default
2.InMemory
3.SQLStorage

Now select the SQLStorage and drag the Person entity from entities list on left side to the entities section of SQLStorage as shown below,

























Now repeat the step for InMemory configuration but this time drag AccountInfo entity to the entities section.

Once done your InMemory Configuration must be having the AccountInfo entity and SQLStorage configuration must be having the Person entity as shown below.

InMemory Configuration after dragging Account info entity

SQLStorage Configuration after dragging Person entity
Now select the person entity from entities list and select the relationship from Person to AccountInfo (holds) and enable the transient property.


repeat the same steps for the inverse relationship (belongsTo) as well.

Believe me you are just few steps away now. Hang on!!

Let's open the AppDelegate's core data stack and lets have look at those mysterious methods that were auto generated for us when we selected Core data while setting up the project.

One of the method that we are really interested here is the PersistentStoreCoordinator getter. Your PersistentStoreCoordinator must be having a statement which looks like


Hmmm there is an option for specifying the configuration and no body told me about it till now !!!!

Lets create two persistent stores using the two configurations that we have created and add it to the persistent store coordinator. One of the persistent store is of type SQLStorage and another is of type InMemory.


Not so sensitive information holding entity Person is stored in SQLStorage persistent store and AccountInfo entity is stored in InMemory persistent store.

Now go ahead and add the data to AccountInfo with respect to some person in core data using the code,

To demonstrate it, I have created a simple list which shows the name of the person and the account number belonging to that person below if the person holds an account else show N/A.




Now lets quit the app and re launch.

Why is it showing N/A for both the entry in the list now ??

Simple, AccountInfo entity was added to the InMemory persistent store, data of the entities belonging to InMemory persistent store exists as long as the app is running and has an allocated memory in RAM. As soon as the app got quit, memory associated with the app was lost hence the persistent store as well resulting in complete data lose of AccountInfo.

Though, the solution 3 isn't suitable for all the scenarios, it might be useful in certain scenarios where the sensitive data is needed and should be associated with some other persistent data as long as the application is running. Every time the app is launched, all these sensitive informations can be synced and a relationship to the existing persistent data can be established providing the user experience as if this data always existed in device.

As the data is never stored in the form of any file on disk, the question of other application gaining the access to sensitive information becomes obsolete and hence ensures the complete protection of sensitive data.

Though Solution 3 ensures the complete protection of sensitive data, It can not be used as the perfect solution in all the scenarios, because of the following reasons.

1.As the data is never saved on disk, the concept of persistent storage completely fails here. In fact saving the data in InMemory persistent store is equivalent to holding the data in application scope variables (Singleton variables).

2. If your app deals with offline capability and needs the access to the sensitive information in offline mode this method fails miserably.

3. Though using the InMemory persistent store provides a thread safe memory based persistent store which allows us to enjoy all the benefits of core data like relationships, fetch requests, FetchedResultsControllers, In effect they are like any other primitive data types in memory as they loose their data once the app is killed hence completely fails the aim to achieve offline storage.

Solution 4: Using SqlCipher with Core Data.

SqlCipher is an open source extension to Sqlite which can be used to encrypt the entire .sqlite file on disk.

Pros : .Sqlite file gets completely encrypted and no other apps can read the data from it other than the one which created it.

Cons:
1. Does not work directly with core data. You will have to make use of a project on git hub to make it work with core data.

2. Works only with .SQLite persistent storage type.

Integration and exploration of SqlCipher with core data is not in the scope of this post.

Conclusion:

1. None of the four solutions proposed above are complete in themselves, but they might prove to be effective under very specific scenarios.

2.Selection of which solution to use or the combination of solutions to use completely depends on the apps requirements. Its up to you to decide which solution to use depending on your apps demand.

There are always more than one way to solve a problem, which one we pick depends on the situation. If you happen to encounter any other solution, that I failed to enumerate here, please leave a comment below.