Custom Core Data migration example

This post is a tutorial on custom Core Data migrations. There is no starter project that you can download and work on following the action steps outlined in this post. But there are action steps in this post that you can follow while developing your own app. And there is an example – my own app – of which you will see relevant parts of code and some screenshots. You can also download my app from the App Store to see what it’s all about. Throughout this post I’ll be telling you what to do, referring all the time to the example of my app. So, it’s going to be “Do this, do that. And by the way, here is how I’ve done it in my app”. 

A little bit of history

I’d been wanting to learn custom Core Data migrations for a very long time and here is why. I have an old app (written in Objective-C) which I wrote when I started learning iOS development. Actually, I was learning iOS development by writing that app. With very little previous experience in programming, I’d made some funny decisions about the data structure of the app. I released several versions with some minor changes and design improvements. Then I had some ideas on how to improve the app dramatically by adding new functionality. But in order to do that I needed to change the data structure completely. Since the change would be dramatic, I had to implement custom Core Data migration. The lightweight migration just wouldn’t do.

And because this app is just a part-time hobby for me, I allowed myself to procrastinate for months on this particular update. And one of the reasons for procrastination was a lack of good tutorials on custom Core Data migrations on the internet. There are some examples but they tend to talk about the details without giving you the overall picture of the migration process.

Here are some questions that had been bothering me before I learned custom Core Data migrations.

If I implement NSEntityMigrationPolicy classes do I have to do anything else, or will the migration occur automatically from then on? Answer: Nothing will happen automatically, you start the migration manually.

Do I have to implement all attribute mappings for all entity mappings? Answer: No, I didn’t have to implement any of those.

I use MagicalRecord, how is it going to affect the process of implementing custom migration. Answer: you don’t start using MagicalRecord until after the migration is completed

Core Data Model Versioning and Data Migration Programming Guide is talking about Core Data migrations in general. There is a section about customising the migration but it’s very short and leaves you with a lot of questions unanswered. I had to use information from several different sources on the internet to finally understand custom migrations.

Overall, the process of figuring out how to implement custom Core Data migration felt like collecting a jigsaw puzzle without knowing beforehand what the end picture would look like. So, what I intend to do with this post is to give you a bird’s eye view on the work that is needed to be done in order to implement custom Core Data migration.

I’ll use my app as an example, but this post is not so much about the little details and code snippets as it is about the overall strategy of implementing custom migrations. You can find all the code snippets you need on Stack Overflow. And I don’t talk much about theory either. This is not an in-depth guide to Core Data migrations. Hopefully, you’ve already read some theory, but maybe still need an example of how it’s done from start to finish. You will find such an example here.

As for me personally, when I was learning all this stuff, what I found myself lacking, is an overview or some king of a big picture. I hope this post will give you this big picture.

This post focuses only on custom Core Data migrations. So, before reading further, make sure you have general understanding of Core Data and lightweight migrations.

The original project

First let’s take a look at my app. We’ll see what its data structure was before and after the migration. The original app had a list of questions which you were supposed to answer on a daily basis.

This is what a question list looked like

And these are the entries in the diary

I told you that I’d made some funny decisions about the data structure of the app. Here’s what it looked like.

For the list of questions I had a class called Questions. There was only one object of that class. It had one attribute called questions of type Binary data. An archived array of NSStrings was stored there.

For daily records I had a class called Records (for some reason the name of the class was plural). It had three attributes:

  • date – I stored dates as strings that looked like this 2017-12-30. The reason I didn’t use NSDates was that at the time I wasn’t comfortable with timezones. I needed dates to always be the same after the entry was created. What if I used NSDates and a user changed the timezone? Some dates could change as a result. I figured it would be easier to store the date as a string and don’t have that problem. In the new version I fixed this, and you’ll see how later.
  • questions – an archived array of strings with question names;
  • answers – an archived array of strings with answers to the questions. I made sure in code that questions and answers arrays always had the same number of items. Question of index i had a corresponding answer in answers array, also at index i. If there was a question which had no answer, I stored [NSNull null] in the questions array in place of an answer to that question. I know, very strange decisions, but that was my first experience in app development.

Data structure after the update

The main reason for the update was to have multiple lists of questions. So, instead of one list of questions I now have several lists of question. Each list has a name and a bunch of questions. And each day record in the diary can now contain multiple entries, like this:

The lists of questions are now called templates. You can see them in a list on the Templates screen.

When you edit each template you can see that now there are 3 types of questions: text, number and Yes/No. These are really the types of answers a question can have. To better understand all this, I suggest you download the app and explore “My diary” and “Templates” sections in its menu.

The new data model looks like this:

There are Templates now. Each Template has a name and a list of TemplateQuestions. Each DayRecord has a list of SectionRecords, and each SectionRecord has a list of questions.

When to implement the migration in your development process

Now that you’ve seen ‘before’ and ‘after’ versions of the app let’s do the migration. But first let’s talk a bit about when to do the migration. At first I had this crazy idea of releasing the version of the app that would look and feel just like the old version but would have the new data model. I thought I’d do the migration, see that everything’s OK and then start developing the new UI in the next version of the app (the migration part was kind of mysterious for me at that time, and I just wanted to figure it out first and then continue with the rest of the development process). I started out with this approach but soon realised that it just wasn’t right. First of all, there is no reason to release an update without any new functionality. Second, while developing the new UI there may arise a need for changes in the data model, which it did, by the way.

So, if you have some other stuff to do, like changing the UI and adding new functionality just delete the old store by removing and reinstalling your debug app and pretend for a while that there’s been no previous version of the app. Develop and test the new version of your app. And then, when you are sure that the new data model won’t change, start implementing the migration.

Preparation for migration

The migration development process starts just like it would start for a lightweight migration. You add a model version. Select your data model file and then in Editor select Add Model Version.

You will see something like this

Now select one of these two versions and in File Inspector set new version as current version. 

Now your data model files should look like this (the green dot is on the second version):

And that’s where the similarities between custom and lightweight migrations end. After you created new data model you can forget about data migration for a while and develop your app as I suggested earlier. 

Actually implementing custom Core Data migration

When you are finally ready for data migration, the first thing you need is a mapping model. You create it just like you create any other file in Xcode, by clicking Command+N.

When you create it you specify the source store, destination store and a name. In my case source and destination store names were “Simple Q&A Diary” and “Simple Q&A Diary 2”. I named my mapping model SQADMappingModel1_2.xcmappingmodel. Once you have a mapping model you don’t have to configure anything in it right away. Instead you can leave it alone for a while, go to the AppDelegate and work on the migration code. Later you will return to the mapping model and customise it. You start with creating a mapping model because you will need to refer to it in your data migration code.

The intermediate result you are going to achieve after writing some code in AppDelegate is this: the migration will succeed without crashing the app but the data will be lost in the process (because you haven’t set up the mappings yet).

Should you migrate at all?

Typically you start the migration at startup. The best place for migration code is -application:didFinishLaunchingWithOptions: of AppDelegate.

But you don’t migrate data every time the app starts. You only need to do it once. Also, if the user is relatively new and has never had the older version of the app, the migration is not needed at all. You can find out if the user is new by checking the persistent store file. In the case of my app it is “Simple Q&A Diary.sqlite”. If this file does not exist at startup, it means that the user is new and this is the very first launch of the app. In this case you create a store and start using Core Data as usual. If the file existed at startup you must check if it is compatible with the new data model version. If it isn’t, it means that migration is needed. I made this ugly diagram to help you visualise the logic I just described.

Of course, using MagicalRecord is optional. And here is what this logic looks like in code (this piece of code is located in application:didFinishLaunchingWithOptions: method):

We’ll look into each of these methods. But first I want to tell you that the code I show you is the actual code from my app. I didn’t adapt it in any way for this post. So there may be some lines that are not relevant to the topic we are discussing here. For example, you can see this line

It just creates the initial list of questions, so the users can start adding their entries right away even before they created their own questions. You can see also, that I create initial data not only for the new users but also after the migration in some cases:

The reason is that in the old app the initial data is hard-coded, and is not saved in Core Data until the user changes it. So it is possible that some users will have no initial data after the migration.

Now lets look at the methods. Let’s start with helper methods and then look at the method responsible for the migration itself. Helper methods:

Here you can see that inside these methods I use other helper methods:

Method [SQADTracker logEventWithName:] is used for sending events into Firebase analytics. 

What migrates where

Before we look into migrateCoreData method there is one thing you need to understand about the migration: the data migrates from one store file into another store file. Prior to figuring out custom Core Data migrations I only had experience with lightweight migrations and I never needed to worry about store files. So, naturally I thought that the data inside my “Simple Q&A Diary.sqlite” file will just be transformed so that it will be compatible with the new data model.

Turns out this is not the case. To migrate data you need another, temporary store file. The data will be migrated from the old store to the temporary store. After the migration completes you will delete the old store and put the temporary store in its place. After everything is done you will end up with the store file which has the same name as the old file, but the data in it will be compatible with the new version of data model. Then you start to use Core Data as usual (for example you can initialise MagicalRecord at this point).

Note that on step 2 on the image you don’t actually create a temporary file yourself. Instead, this file is created on step 3 during the migration. You only need to specify it’s name.

Now let’s look into the migrateCoreData method:

Note how the mapping model is referenced here (with “cdm” extension). You can also see that the temporary store file name is specified (“SQAD_NEW.sqlite”). I could have chosen any other name for this file. After the migration succeeds the store replacement method is called. Here is the implementation of this method:

I leave all the tracking code (-[SQADTrackerlogEventWithName:] method calls) in these code snippets to give you an idea about the things you might want to track in your own app.

Intermediate testing

Now we can test this code by installing the previous version of the app, adding some data into it and then installing the new version on top of the old version. In the logs you should see that migration was successful. But there will be no data in  the store. Well, in the case of my app there will be initial data created after the migration, but the data that was entered in the previous version of the app will be lost.

Configure the mappings

What you need now is mappings. Go back to the mapping model that you created earlier. In my case it’s a file called SQADMappingModel1_2.xcmappingmodel. Inside it you will see a list of mappings. The names of the mappings will be the same as the names of the entities in the new version of your data model. In my case they looked like this:

Now let’s think a little bit about what we are trying to accomplish. You want to turn thisinto this

In the new data model there is a bunch of entities connected to each other through relationships. It’s easy to get confused about what should map to what. This is how you should think about it. If you look at new data model, you will see that entities connected to each other through a relationships can be viewed as hierarchies with parent entities and child entities. What you should be interested in is the topmost parent entities. They are Template and DayRecord.

So, when you configure the mappings in your mapping model you will specify that Questions entity (old data model) maps to Template entity (new data model)

and Records (old data model) maps to DayRecord (new data model) 

Reminder: I called Records entity so by mistake. I should have named it Record (without s). So think of it like this: each Record turns into a DayRecord.

What about the other entities (TemplateQuestion, SectionRecord, Question)? The child entities will be created programmatically, and I’ll show you how later.

In my project I selected Template mapping and set Questions as it’s source. Then I selected DayRecord mapping and set Records as it’s source. Then I created a subclass of NSEntityMigrationPolicy for each of the two mappings and specified the names of those classes in the mapping model. So, for Template I ended up with these settingsAnd these are the settings for DayRecord

Note that when you specify a source for the mapping, the mapping’s name changes. In my case Template turned into QuestionsToTemplate and DayRecord turned into RecordsToDayRecord. In user info you can see that I added a modelVersion key with a value of 2. This will be used later in the code. Also note that of five mappings I used only two.

I guess I could have deleted the other three, but I just kept them in the mapping model because they were harmless. And here is what relevant files look like in Project navigator

Implementing mapping policies in code

If you now test the migration you will see that nothing has changed: the migration succeeds but the data is lost. What you need now, is to implement createDestinationInstancesForSourceInstance: entityMapping: manager: error: method in each of the entity migration policy subclasses. 

This is how I did that in SQADQuestionsToTemplatePolicy.m file:

I don’t use MagicalRecord or NSManagedObject subclasses at this point. Instead I use key value coding. Xcode complained that method addQuestionsObject: was undeclared, so I had to import Template+CoreDataClass.h. You can see that I take all the data I need from the source instance called sInstance. It’s a Questions object from the old data model. Then I create a Template object and populate it with data, create a bunch of TemplateQuestion objects and connect them to the Template object. Note how I check model version before doing anything of it. This is the key-value pair I set in my mapping model previously.

Here is the contents of SQADRecordsToDayRecordPolicy.m file:

I pretty much do the same thing here: I get the data from source instance, create destination instance, and populate it with data . As you can see, I did some funny stuff with sortField. You don’t need to understand it. It’s just something I had to do to sort SectionRecrods according to their date and their order in their DayRecord.


What if migration was not successful? In some examples on Stack Overflow people suggested to not delete the old persistent store but to move it to another URL instead. I could have done it, but I thought about it and I couldn’t figure out how it would help me in any way if the migration failed for some users. I’d need to release an update where they could get their data from the backed up persistent store, which would be too much trouble for me.

But I still wanted to minimise the risk for users to lose all their data in case of a migration failure. I thought, if the migration failed there would be two persistent store files: the old one, and the temporary one. On the next launch there will be second attempt to migrate data. I didn’t know if the existing temporary file, possibly with corrupt data in it, would cause second and all the subsequent migration attempts to fail. So, I decided to just delete the temporary file (if it existed) at every launch. This is the method I used for it:

I called it in -application:didFinishLaunchingWithOptions: of AppDelegate before calling all the migration methods I showed you in this post. There is still a chance that after deleting the old store the attempt to move new store into its place will fail. But this never happened according to my analytics. Maybe you can suggest a better strategy for dealing with possible migration failures.

And this is the end. I hope this tutorial was helpful.


Too many app downloads from China. What is going on?

Recently I had quite a few downloads from China. As I later found out, those downloads were fake. I decided to write this post to share my experience with you. And if someone have already had the same experience maybe they’ll share their knowledge with me about what is going on and how to deal with it.

How it all started

First of all let me show you what my app downloads normally look like. This is my stats for the month of April 2017. As you can see, I normally have around 10 downloads per day.

Lets see what happened the next month

In May 2017 it was the same until the end of month when the number of downloads rose from 10 downloads per day to 50-60 downloads per day. I learned that the extra downloads were from China. OK – I thought – Chinese people have discovered my apps at last. And there are a lot of Chinese people out there so nothing surprising. By the way, the app that was downloaded the most at that time was 3Do.

Third month

The number of daily downloads was about the same for the next month. But in the very end of June I experienced a surge of downloads. One day it was 568 downloads total. The next day it was 6,54K. The day after – 7,50K. Now it was my other app – Stream Journal – that was downloaded the most. And all these downloads were once again from China.   

This time I decided to check my stats in Google Analytics, since I have implemented Google Analytics in Stream Journal but haven’t done it in 3Do yet. What I found out is that with all those downloads there was not a single app launch from China.

The possible explanation

I tried to find the explanation to this fake downloads mystery on the internet. But all I could find was other people complaining about having similar experiences with app downloads from China and other asian countries. It all reminded me of a video I once saw on Youtube about Chinese like farms. A like farm or click farm looks something like this.

You just pay for your fake Facebook likes and they give you your likes. But as the video explained they can’t just like only the stuff they were paid for, because in that case they would be easily found out. So they also like some other random stuff.

So, my hypothesis is that exactly the same thing has happened with my app downloads. It may be that one of those click farms found out my apps and used them to make their statistics look unsuspicious to Apple.

Here is the said video, by the way:

What I did about it

At first I put a price of $1 on my Stream Journal app just for one day to see what happens. What happened is that nobody bought my app that day. I made it free the next day. And there was about 100 downloads. Eventually I decided to make all my free apps unavailable in China. Sorry, Chinese people, I just don’t want your click farms to mess up my stats.

Now I enjoy the usual 10 app downloads per day. 


What happened?

I stopped blogging once again. For almost a month. This is just a quick post to tell you what’s going on.

In a couple of weeks I will go to Moscow for several days. I need to make a presentation at the main office of the company I currently work for. When I learned that I was to give this presentation, it sort of messed up all my plans, which resulted in two things. First, I stopped working on my app – ImpApp.

Second, for the last several weeks I couldn’t find time for blogging, because I was preparing for the presentation.

But I totally plan to resume both of these activities soon.

Also, now I have an email list. Leave your email to get updates from this blog. And when I release ImpApp you’ll be among the first people to download it.


Creating my new app – ImpApp

I’m going to build a new app. Actually I’m already working on it. I just thought why not document the process of its creation here on the blog. It turns out I have already started documenting the process. My previous post was about incorporating ads into an app. Guess what. That post came as a result of me working on my new app.

What’s the idea

Have you seen Memento movie? It’s about a man who can’t form new memories as a result of past trauma. He is searching for people who attacked him and killed his wife. But he keeps forgetting everything he learns during his investigation. So he has to use a system of Polaroid photos, notes, and tattoos to track information he can’t remember.

When I was watching this movie I kept thinking to myself that the movie wasn’t just portraying some curious condition of a traumatised mind. It also kept reminding me of the fact that we (by we I mean all humans) have a universal tendency to forget things.

There were moments in this movie which reminded my of some moments in my own life. Like when the main character found out that the girl who he thought was helping him, was actually using him, taking advantage of his condition (she told him about it herself laughing at his face, knowing that in a couple of minutes he will forget about it). And the guy was frantically looking for his notes to write down this new information.

There were moments in my life when I knew if I didn’t write down that genius idea at the very moment I had it, I would forget about it forever. Sometimes I would get out of bed in the middle of the night just to write something down.

Tattoos as reminders

This is Casey Neistat. He has a tattoo saying “Do more” to remind himself to do more, obviously. When I saw this tattoo I thought that it was actually  a good idea to use tattoos to remind yourself of something important. Also it reminded me of Memento movie. And that’s how the idea for my new app was born. Me, personally, I have a bunch of things I want to be reminded of every day. Only I don’t want to have tattoos. So I thought to myself, can an app substitute a tattoo?

By now you have figured out the idea of my new app: it’s going to be an app that you use instead of a tattoo to remind yourself of important things (thoughts, ideas, quotes) every day. I couldn’t think of a good name for it, so I decided to call it ImpApp. Imp – means important, because the app is all about remembering the important things. 

Basically it will look like a list. But it’s not enough to just write things down. You actually need to read them every day. That’s the main problem with most productivity apps, like diaries and journals: you don’t read your own notes very often. So, my app will remind you to open it every day via local notifications.

You might be wondering how this app is going to be different from Apple’s Reminders. Actually it won’t be very different. In fact when I first had the idea for this app many months ago, I created a list in Reminders called “Always remember” and set an alarm for 9:03 PM every day named “Read Always remember”. Here is what this list looks like.

And I’ve already been using this list for months. So, if you want to benefit from this idea you don’t actually need to wait for me to release my app. Just use Reminders and set an alarm.

Problem with Reminders

But there is (or will be) one downside to using Reminders instead of my future app. With time your list grows. And although all the things in the list are important to you they are not all equally important. Basically your list gets cluttered with less important stuff, making it hard to pay attention to the more important stuff.

So I thought it would be nice to have let’s say three lists. In the first one you can store up to 5 items. In the second one you store 20 items. And the third list is limitless. This arrangement will force you to sort your items according to their importance to you. Theoretically you could still do this in Reminders using multiple lists, only it is a little complicated.

What the app will look like

Here is what I came up with in terms of design.

Mind you that it is not finished. I will work on the design some more. The dark green area at the bottom of the screen will be occupied by a banner ad.

Monetisation of the app

I think that if a person starts using this app he or she will continue to use it. And the reason is not the fact that I will use notifications to remind users to open the app (many apps do the same thing). The real reason is that the notification will remind users to read the list of things that they believe are important. They won’t mind the notification. They won’t be annoyed by it. So, I predict high retention rate for this app.

People will be using it every day (hopefully). An that means that it makes sense to monetise the app through ads. I will be using just a little banner at the bottom of the screen to avoid annoying people too much. I think it is not the kind of app where people will tolerate full screen ads.

Also there will be an option to remove ads with one small payment. I think this is the kind of app where you should have such option. There are other apps where it is not as important. Like a cooking timer. When I use a cooking timer app I just set a couple of timers and then go on with my cooking. I don’t look at the screen. So I don’t care if the ads are showing. And I would never buy a paid version to remove the ads in this case. But when you read a list of very important things, and do it every day, you should have an option to remove the ads. It’s just humane to provide such an option.

When the app will be released

I already incorporated ads and figured out how to use local notifications. Right now I’m in the process of implementing in-app purchases. I guess I’ll finish them tomorrow. Then I will need one or two days to work some more on the design. After that I will start actually building the app. It shouldn’t take too long. The app itself should be easy to build. Also a lot will depend on my day job. Recently I had to put a lot of extra hours into it. It definitely slows me down.

I would say that the app will be ready in 2 weeks to 1 month. If you want to be notified when it is released write me an email. If you have a suggestion about my new app, leave a comment below.


Incorporating ads into your iOS app (using AdMob)

In the previous post I told you that I have a good idea for my next app. I still don’t want to tell you everything about it. But I know that I will need to use a bunch of technologies which I don’t use very frequently:

  1. In-app purchases.
  2. In-app ads.
  3. Local notifications

In fact, up until now I used each of these technologies only once.

In this post we will talk about incorporating ads into your app. Since the last time I used ads in my app things changed. Apple shut down their ads network, called iAd.

That’s not a big problem, though. You just have to use a third party ad network nowadays. I decided to use Google’s AdMob.

How to use AdMob

What you will need:

  1. First of all you need to have an AdMob account.
  2. Register your app in AdMob.
  3. Install AdMob SDK.

By the way, to use AdMob you will also need to download Firebase SDK. Just add these two lines into your Podfile (you need to know how to use CocoaPods):

pod ‘Firebase/Core’
pod ‘Firebase/AdMob’

After the pods are installed, add these lines into your application:didFinishLaunchingWithOptions: method of AppDelegate

You will find your ApplicationID in your AdMob account page.

To add a banner you do something like this in the viewDidLoad method of your view controller:

bannerView’s  class is GADBannerView, which is a subclass of UIView. You can draw your view in the Storyboard and then select this custom subclass for it. Then you connect the view to your view controller through a property bannerView. Also don’t forget to import GoogleMobileAds

You can keep the adUnitID you see above while debugging. You will see a test banner with no real ads on it. But before releasing your app to the App Store you should add real ad unit id. To get it you register your banner in your AdMob account.

When you see real ads in your banner, don’t touch the banner! It’s against the rules.

Basically all you need to know to start using AdMob you can find here:


Hardships of an iOS developer slash blogger

This post was supposed to be a technical one. It was going to be about creating and using an iOS static library. But instead I guess I will whine a little about how hard it is to blog nowadays.

As you may know I have a plan of how I write blog posts. Every Monday I must choose a topic for the next article, and then work on the article throughout the week. The first week after I made a decision to stick to that plan I sort of did it. What helped me a lot was the fact that the article was written for the most part long before that week even started.

This week I didn’t have that advantage. I just did nothing. I procrastinated. Well, I did something, like reading on the topic and going through a tutorial. But I didn’t write anything. Also I had couple things on my mind that distracted me from blogging.

Major distraction

Since I returned to Stavropol from Moscow (September 2016) I was living at my parents’ house. I planned to move out in a couple of weeks but for various reasons I stayed there for several months. Now, just the last weekend I finally found an apartment to rent. And so, the last week was full of preparations for the move. I finally moved into my new apartment just yesterday.

When I signed the papers a week ago I didn’t have all the necessary money on me, so a day later I had to dedicate a couple of hours to just delivering the rest of the money to the landlady.

Also, the other day I had to spend several hours setting up the internet connection in my new place. I didn’t do anything but I had to be in my apartment to let the cable men in, wait for them to finish their work and then sign the papers.

These little distractions quickly add up into a total inability to blog, let me tell you.

Another distraction

International Women’s day. Here in Russia we have this strange holiday on the 8th of March, when you congratulate the women you know (and sometimes the women you don’t even know) and buy them gifts. So, that also distracted me from blogging.

And another one

Several days ago I came up with an idea for an app. I’m not going to reveal anything right now, but the idea is genius. The app will be very easy to develop and hopefully it will have a very high retention rate, and that means I might make some money through ads in this app. I just couldn’t help thinking all the time about this app. I even started to work on the design for it.

Also, right now I’m reading a book on design, called The Non-Designers Design Book. And as I learn the concepts from this book I try to implement them right away in the design of my new app. I’m not rushing the design. I will finish it only after I finish reading the book. I don’t want any regrets about design mistakes later.


It’s hard to blog. On the other hand I see how blogging can be easy. If only I could write about something I want to write about.

You know how they say that you should find your niche and stick to it. Especially when you are just starting out as a blogger. So I have picked my niche which is iOS development.

But I find that it’s incredibly hard to stick to it. What if I’m interested in design right now? Do I have to force myself to stop learning design and learn some programming tips and tricks instead? The question that I keep asking myself is: why can’t I write about design? Maybe this is the way? What if I’m some kind of a unicorn developer in the making? Maybe that is my real niche?

Maybe blogging is not about following a bunch of rules? Maybe it’s about being authentic and writing about something that you want to write about? What do you think?


The work desk of iOS developer

All through my life I have never been a particularly organised person. If you looked at my work desk you’d see it cluttered with stuff. Mostly with papers. Piles of papers and folders. It was at the time when I worked as a civil engineer. I had to deal with a lot of paper drawings. But still, if you compared my desk to the desks of my coworkers you’d see a drastic difference. At times I had stacks of folders on my desk that were taller then the monitor of my computer.

Then when I switched to programming, things got better. I didn’t have that much stuff on my work desk any more. But I still had some. Again mostly papers. Many of these papers were not even mine. If somebody put something on my desk it would stay there forever. I did cleanups from time to time but it didn’t help. The good news was that now my desk was not the most disorganised desk in the office. All my coworkers had pretty much the same situation going on on their desks. Not huge piles of papers but still messy workplaces.

Going paperless

One day I saw a YouTube video where a guy was talking about how he ‘went paperless’. For couple of minutes into his talk I couldn’t quite figure out what he was talking about. Going paperless? Why would anyone do it. Why should anyone even think of such a thing. Before I watched that video I didn’t even view paper as a problem. But as the guy explained how his life changed after he went paperless it dawned on me that ‘going paperless’ is exactly what I needed.

At that time I was getting ready to start working remotely. I was still working at the office in Moscow. But I was to go to my home city of Stavropol in few weeks to work remotely in the same position for the same company. And I decided that at my home office I would go paperless.

Digitising journals

I started throwing away my paper journals while I was still in Moscow. At my apartment in Moscow I had all sorts of paper notebooks. I had a dream journal, a goals journal, a journal for my workouts, a journal for my daily to-dos, a journal for my ideas and maybe couple of other journals. I spent several evenings digitising all that journals. I would type  important information like logins and passwords into a password protected text file. I took photos of other useful stuff from my journals and stored them on my computer. After that I destroyed all my physical journals. It was a relief to know that I was dependant no more on some physical objects like paper journals to store important information. 

Now I store all the important documents in three places: on my computer, on my external hard drive and in the cloud.

Keeping some paper

I kept only one paper notebook. It’s just a blank notebook with tear-off sheets. The reason I kept it is simple. There are certain activities which are done more conveniently on paper than on the computer. Sometimes I need to draw something quickly that will help me to solve a problem at hand. Also, when the problem is really hard, I like to think on paper. I just write down my thoughts so I don’t loose my train of thought. Sometimes I need to derive a formula. In all those cases paper is irreplaceable.

So I only have one paper notebook left now. And I decided that I will never use it as a storage of information. When I use up a number of sheets in it I just tear those sheets off and throw them away. That way I always have a clean notebook. If I ever need to keep something from this notebook for later I would just take a photo of that thing, be it a formula, a drawing or something else. Up until now I never had to.

The secret to tidiness

Going through this process of decluttering my workspace I found out the reason I was so disorganised up until that point. It turns out I was some kind of a hoarder. I just had too much stuff. And the secret to being organised is to have as little stuff as possible.

Just take a look at my desk:

How are you going to make a mess on your table if you don’t have a lot of stuff in the first place? No matter how lazy or disorganised you are, you will always have a tidy desk.

And this is the biggest mess I can ever have on my work desk nowadays:

Also take a look into my top drawer:

This is all the stuff I have there. So, whenever I need a pen and a notebook, for example, I don’t have to look for them.


For many years I was very disorganised. I even took pride at it. I thought that the fact that my workplace is a mess somehow indicates that I’m a creative person. I thought that to have a tidy work desk you need a lot of discipline that would enable you to clean your desk regularly. And I just didn’t have that discipline, because, you know, I’m so creative. I didn’t have time for boring stuff like cleaning my desk.

Now I know it’s all BS. The mess on your desk indicates only your lack of priorities. Have only the things that you need, and don’t have the things that you don’t need. It’s as simple as that.


Blogging strategy for an iOS developer

For some reason I stopped blogging recently. Almost a month passed by without a new post. That bothers me a lot, and I need to change it. So in this article I’m going to describe my plan for blogging consistently from now on.

The reason I stopped blogging

Actually, I don’t have a good reason. Yes, I was busy doing other things. Like, for instance, I was learning the basics of Android development. Also, I was reading a lot about freelancing because I’m thinking of becoming a freelancer one day. I was doing some stuff, that I considered important, and I stopped prioritising blogging. So, I just stopped. I lost momentum.

Fighting YouTube addiction

And then I started watching YouTube. At first I was watching important stuff. Then I started watching less important stuff. Then I transitioned to watching just plain stupid entertaining videos. I even subscribed to PewDiePie. Each day I spent several hours on YouTube and went to bed very late.

I did it until I no longer remembered what my goals in life were. I stopped learning, I stopped programming my own apps. And I stopped blogging.

Couple of days ago I decided to end this madness and stopped watching YouTube altogether. And that sums up the YouTube cycle I go through over and over again throughout my life:

  1. I don’t watch YouTube at all and am being super productive
  2. I decide to watch it a little bit, just to get some useful information
  3. I start watching stupid entertaining videos and my productivity drops to zero
  4. I stop watching YouTube and become super productive again

So, right now I’m back in the productive stage of the cycle, and that’s good.

My old content strategy

When I started this blog I didn’t have a content strategy at all. I just wrote a bunch of posts about myself, how I became an iOS developer, what technique I used to be productive, how I make money on the AppStore. I also wrote about the stuff I was learning at that time. And then I ran out of ideas and almost stopped blogging.

Luckily, I noticed that when I need to do some task that I have already figured out how to do in the past, it’s nice to have a blog post about it. That way you don’t need to Google the same stuff over and over again. So, I decided instead of quitting blogging to blog for myself. I even wrote a post about this decision.

The decision to write small articles just for my own use allowed me to blog more or less consistently for months. This decision had its pros, but it also had its cons.


  1. You don’t quit blogging because of lack of ideas. As long as you learn something you can write about it.
  2. You don’t spend much time blogging. Sometimes it only takes several minutes to create a post (from idea to publishing). Most of the time you just copy and paste someone else’s code without much thinking.
  3. Your blog is your learning journal. Even if nobody reads it, it is useful at least for one person, which is you.


  1. Your blog becomes a collection of code snippets and is not very useful for other people. 
  2. You don’t develop your writing skills because you don’t spend enough time writing, and when you do write, most of the time it’s just a copy-paste, not real writing.
  3. You don’t learn as effectively as you could have. You learn best when you try to teach others, what you’ve just learned. That way you immediately start to see the gaps in your own knowledge. Teaching forces you to do a more thorough research and fill those gaps. But when you just copy and paste someone else’s code on your blog, it’s not teaching. It’s just a copy-paste. And by doing it you miss out on real learning. 

My new content strategy

First of all, I’m not giving up on writing short posts. They are still useful for me and they don’t take much time to write. I will continue to post some code snippets in an irregular fashion. But on top of that I must do some real blogging, meaning I will be writing some big and well researched posts, that will hopefully be useful not just for me, but also for other people.

Committing to a schedule

What I lacked up until now is a blogging schedule. Now I decided to have one. For starters I will create a ‘real’ blog post once a week. I will be posting every Monday. Later I may change the schedule so I will post more frequently. For now let’s see if I’m able to post at least once a week. 

Let’s go into the details of my schedule.

Monday. I pick a topic for my next blog post. If I don’t have ideas, I will just sit and generate dozens of ideas in one go. 

Tuesday – Wednesday. I start doing my research and begin to make the first draft of my blog post.

Thursday – Friday. I do the actual writing.

Saturday. I pick pictures for my blog post.

Sunday. I reread my post, and check that everything is OK.

Monday. I publish my post, and pick the topic for my next post.

Creating blog posts in advance

I plan to have 2-3 blog posts ready for publishing at any time. To have this 2-3 blog posts I will need to work harder on my blog for some period of time. I don’t even plan to do it right of the bat. At first I’ll just try to stick to my schedule of releasing one post a week. Then, when I get used to my new schedule, I will try to work on two blog posts during one week. That way I will do the same work on the same days of the week, and I will not have to change the schedule itself. For 2-3 weeks I will produce 2 blog posts per week, and that’s how I will accumulate the necessary number of posts ready for publishing.

Using pictures in my blog posts

Up until now, I have been using images from Google search. It’s not a good practice, though. And I’m not even concerned with possible copy rights issues. I just don’t want my blog to look unprofessional. So, I started buying stock photos. You can see couple of them in this post. With time I will also replace the photos on my older posts. 

Writing tutorials

I want to gradually turn my blog from my personal learning journal into something that will be of use to other people. For that reason at some point I will start writing tutorials. Right now I don’t even know what those tutorials are going to be about. I guess I’ll have to sit and generate some ideas.


This post was designed to be a reminder for me. I will come back to it from time to time to see if I’m doing everything I planned to be doing. I also hope this post was of some use to you too.


How to install Tomcat 8.5 on remote CentOS 7 server

In the previous post I told you how I installed Java on my production server. Now it’s time to install Tomcat. There are different ways you can do it. I must warn you that the way I did it might not be the best way, because I skipped all the security related steps. So, what you are about to read is not a definitive guide to Tomcat installation (if you are looking for that kind of guide check out this article). But I think this post can be a good starting point for a complete noob who doesn’t what to overwhelm himself with too much detail right from the start. Here we’ll just focus on installing Tomcat and making it work somehow.

My first attempt

At first I tried to just

sudo yum install tomcat

But this command installed Tomcat 7, while I wanted to install the latest stable version, which is currently Tomcat 8.5.9. So I had to remove Tomcat 7 with

sudo yum remove tomcat

(Note that I am logged to my remote server as sudo user by the name of karen)

By the way, if you install Tomcat 7 this way and then don’t see the default Tomcat page in browser, you need to install some additional stuff:

sudo yum install tomcat-admin-webapps.noarch tomcat-docs-webapp.noarch tomcat-javadoc.noarch tomcat-systemv.noarch tomcat-webapps.noarch

Also don’t forget to configure your ports. More on this later.

Before making my second attempt to install Tomcat I found a video tutorial, and went through it step by step. We will go through this tutorial later in this post, but before installing Tomcat we will need to setup FTP server. I’m sure there are other ways to transmit installation file to the remote server, but we will still need the FTP server later on for uploading our apps. So why not start with FTP server?

Setting up FTP server

I used this tutorial and I installed vsftpd like this:   

sudo yum install vsftpd

sudo yum install ftp

I’m not sure if the second line was necessary, because I didn’t quite understand the tutorial. Did I need to install ftp on my local machine or was it needed on the remote server? I just thought it wouldn’t hurt to install it also, so that’s what I did.

On my local computer I have FileZilla, which I installed a long time ago, so I used it to connect to the server.

At this point you’re not going to be able to connect to the FTP server. You need to open the port 21 in the server’s firewall:

sudo firewall-cmd –permanent –add-port=21/tcp

sudo firewall-cmd –reload

Now you can open FileZilla, specify url of your server, your name and password, and try to connect. It is going to connect, but it will throw an error soon after. The reason is that the actual data is transferred through a range of ports which are all closed in your firewall. The port 21 is just for the commands. For all the data you need to open some other several hundred ports. Also you need to tell the FTP server which ports it should use.

To understand why you need to go through all these steps you can read these articles:

Lets first configure the FTP server. Open the configuration file:

sudo vi /etc/vsftpd/vsftpd.conf

Now paste these three lines:




What we did here is we enabled the passive mode (read about it in the articles above) and set the range of ports that FTP server will use for transmitting the data. We need at least several hundred ports.

After saving and exiting the file don’t forget to restart your FTP server:

sudo /bin/systemctl restart  vsftpd.service

Now we need to open the port range in the server firewall:

sudo firewall-cmd –permanent –zone=public –add-port=10100-10900/tcp

sudo firewall-cmd –reload

Finally installing Tomcat

This is how I did it. I went to the official site of Tomcat and downloaded this file:

Then, using FileZilla, I uploaded it to my server. Now the file was in my home folder on the server.

I logged in to the server and moved the file to the new folder:

sudo mkdir /opt/tomcat

sudo mv /opt/tomcat

Then I checked the md5 sum:

cd /opt/tomcat


Then I unzipped the file:

sudo unzip

Actually I couldn’t unzip it at first, because I didn’t have the necessary program, so I installed it:

sudo yum install zip unzip -y

The reason I used specifically zip file instead of tag.gz is that that’s what was used in the video tutorial. I decided to not change anything. I think tag.gz would do just as well. 

Now I set right permissions:

cd apache-tomcat-8.5.9/bin

sudo chmod 700 *.sh

It means I can execute *.sh files.

And the last step is to create a couple of links:

sudo ln -s /opt/tomcat/apache-tomcat-8.5.9/bin/ /usr/bin/tomcatup

sudo ln -s /opt/tomcat/apache-tomcat-8.5.9/bin/ /usr/bin/tomcatdown

Now I can start Tomcat like this:

sudo tomcatup

And stop it like this:

sudo tomcatdown

If you followed all the steps and started Tomcat, now you can point your browser to your_server_ip:8080. You should see the default page of Tomcat:


How to deploy Java application to production server

After playing around with server side development (see my posts about it: post1, post2 and post3) I feel like I could develop back-end if I really needed to. Of course it would take a lot of time and I’d be googling a lot, but at least back-end development is not a mystery for me anymore. But there is one piece of knowledge regarding back-end development that I lack: I don’t know how to deploy my application to the production server.

So, I decided to address this issue, and rented a VDS (virtual dedicated server). I’m going to use it for my experiments and eventually for hosting back-ends of my future apps.

My goals are:

  1. Install Tomcat
  2. Install MySQL
  3. Deploy some Java application to the server.
  4. Learn how to use the server for sending Apple Push Notifications.

Here is what I have done already. I started reading about how to install Tomcat and found out that I should install Java first. And even before that I needed to create a sudo user.

Lets go step by step and see what I did.

Creating sudo user

After the purchase of VDS my hosting provider sent me the IP address of my server and the password of root user.  I logged in to the server via SSH.

local$ ssh root@server_ip_address

It is a good practice to not connect to the server as a root user. So I created another user.

# adduser karen

And set his password

# passwd karen

Then I added this new user to the wheel group to make him a sudo user.

# usermod -aG wheel karen

Then I switched to the new user account

# su – karen

Then I verified that I could use sudo

karen$ sudo ls -la /root

This command just lists the contents of /root folder which is normally only accessible by the root user.

I used this article as a reference.

Installing Java

Installing Java was easy. I did it with this one command:

sudo yum install java-1.8.0-openjdk

I verified that Java installed correctly with this command:

java -version

This article helped me.

To be continued.

In the next post I will tell you how I installed Tomcat on my production server.