How to resolve assets error in Xcode 8

Recently I started seeing this error:

Invalid Bundle – The asset catalog at ‘Payload/XXXXX/Assets.car’ can’t contain 16-bit or P3 assets if the app supports iOS 8 or earlier

When I saw it in my own app I just changed the deployment target to iOS 9.3. Next time I saw this error in the project that I do on my job. This time the client wanted to keep supporting iOS 8.0 so I had to find another solution. After googling for some time I found the solution here.

The rest of the post is just a copy-paste. I need it here on my site, so I don’t have to look for it again later.

1. Create an Inspectable .ipa file.  In the Xcode Organizer (Xcode->Window->Organizer), select an archive to inspect, click “Export…”, and choose “Export for Enterprise or Ad-Hoc Deployment”. This will create a local copy of the .ipa file for your app.

2. Locate that .ipa file and change its the extension to .zip.

3. Expand the .zip file. This will produce a Payload folder containing your .app bundle.

4. Open a terminal and change the working directory to the top level of your .app bundle

cd path/to/Payload/your.app

5. Use the find tool to locate Assets.car files in your .app bundle as shown below:

find . -name ‘Assets.car’

6. Use the assetutil tool to find any 16-bit or P3 assets, in each Assets.car your application has as shown below. :

sudo xcrun –sdk iphoneos assetutil –info /path/to/a/Assets.car > /tmp/Assets.json

7.  Examine the resulting /tmp/Assets.json and look for any contents containing “DisplayGamut”: “P3” and its associated “Name”.  This will be the name of your imageset containing one or more 16-bit or P3 assets.

8.  Replace those assets with 8-bit / sRGB assets, then rebuild your app.

Update:  If your Deployment Target is set to either 8.3 or 8.4 and you have an asset catalog then you will receive this same error message, even if you do not actually have 16-bit or P3 assets.  In this case you will either need to lower your Deployment Target to 8.2, or move it up to 9.x.

Facebooktwitterredditpinterestlinkedinmail

How to prevent double tap on UIButton

If you Google this question you will get a lot of wrong answers, which may be marked as right answers on Stackoverflow. The simplest “solution” is to disable the button temporarily inside its action method.

For instance:

But from my experience this approach doesn’t work. The reason is that UIKit framework doesn’t perform your commands immediately: it decides on its own when the right time to do what you ask it to do is. I read about it somewhere a long time ago and I don’t have any links now, so feel free to correct me if I’m wrong. But that’s what I have encountered many times in my work. And it’s strange that nobody on the internet is talking about it. That’s why I wonder if I overlooked something, but anyway…

Here is the solution that I use. I create a BOOL variable or a property on my view controller. Then I just use this flag instead of enabled property of UIButton.

Of course, you must enable the button later by setting the BOOL variable to NO.

Facebooktwitterredditpinterestlinkedinmail

How to free a lot of space on your development Mac computer

Since about a week ago I started working from home. I used to work on a powerful iMac at the office but now the only computer that I use for iOS development is my MacBook Air 13” (early 2014). I also have a monitor and a wireless keyboard. My setup looks something like this.

Everything is well and good, my laptop is powerful enough for my programming work. There is only one thing I don’t like about it: its HD is only 120 Gb so it runs out of memory all the time. Or, used to run out of memory until I figured out how to free a lot disk space.

First of all I installed a program called Disk Inventory X, which allowed me to analyse my disk space usage. Then I found out that the most memory consuming thing on my computer was this folder

~/Library/Developer/Xcode/iOS DeviceSupport

It weighs many gigabytes (it weighed tens of gigabytes when I first found it) and they say that it is perfectly safe to delete everything from this folder. Now whenever I feel like I don’t have enough space I clean this folder.

There is also one other folder that rapidly eats up the disk space.

~/Library/Developer/Xcode/Archives

Every time you build an archive in Xcode it ends up in this folder. The archives for some of the apps I work on take more than 100 Mb. Some days I can make quite a few of these archives. Now I remove the older archives from time to time. Just recently I freed 10 Gb on my computer this way.

By the way, the whole purpose of this post is to remind myself of the location of these folders, so I don’t have to look for it in the future.

Another thing I did: I bought a 1 Tb external hard drive. I use it for storing my photos, movies and backing up my documents. I don’t store any photos on my MacBook any more and I even switched off iCloud sync so that the photos I take on my iPhone don’t automatically end up on my computer. I just move my photos from my iPhone to the external drive manually from time to time. 

Now at any time I have at least 20 Gb of free space on my computer which is pretty comfortable for me and I don’t need to buy another computer which is super good.

Facebooktwitterredditpinterestlinkedinmail

Creating an email subscription web service (Part 2)

In the previous post of this series I decided what tables I’m going to have in my database. I created those tables (people_table, lists_table, subscriptions_table) using Workbench. Then I had to spend one evening trying to fix an issue with Russian language in MySQL. I just couldn’t save entries to the database, if those entries had Russian symbols in them. I was trying to find a solution that would fix this issue once and for all, like maybe changing some setting in MySQL or in Workbench. But I couldn’t.

So, for now the only way for me to use Russian symbols in my database is to set the collation of each table at the time of its creation to utf8-default. If the table already exists and it has wrong collation, I don’t know how to change it. If you know how to set text encoding globally in MySQL, please, tell me in the comments section below.

I have read something about JavaMail and about setting up a mailing server in general. It all seemed complicated, so I’m not sure if I’ll ever complete this project. I will definitely read some more on this topic, though. For now, I decided to do without the mailing part of an app. What I want to do now, is create a web form with two fields – name and email – and a server side which will get the information from a web form and save it to the database.

So, I created the form. This is what it looks like.

webform

And here is its source code.

Notice the third input – list_id. It has type “hidden”  so it isn’t visible on the page, but the value of the list_id parameter will be sent to the server. This is how the server will know which list the user is subscribing to. The value of this parameter is set manually for now. 

I also created a Web Project in Eclipse called EmailSubscriptionService. To use JDBC in it I downloaded Connector/J from https://dev.mysql.com/downloads/connector/j/

I needed to put the mysql-connector-java-5.1.39-bin.jar file from the archive somewhere into my project. I didn’t know what the right place for it was, so I just put it into WebContent/WEB-INF/lib folder. I’m almost sure (after googling a little) that it is not the best place for this file. But it works, and that’s what is most important for me right now.

I created two files: AddEmailToList.java and MySQLConnection.java. Then I spent two evenings coding. Finally, I have all the main functionality. I can add people to the list from the web form.

This is my AddEmailToList.java file:

 

And this is myMySQLConnection.java file:

 

This is my lists_table with just one list in it:

lists_table

After I get the request from the web form I first check if the list with a specified id exists. Just in case.

Then I add a person to the people_table, if that person is not already in the table, which can be checked by the email: each email is unique in the people_table.

people_table

After that I get the person_id from the table and add it to the subscriptions_table along with the list_id, which is 1 all the time (it was hardcoded into the web form, as I showed above). This is my subscriptions_table:

subscriptions_table

What’s next

Since I am more interested in learning databases (and a little bit of web development) than in learning the mailing stuff, I will postpone the learning of JavaMail until better times. Instead, I will create an admin panel for my app. It will allow me to see my lists of subscribers from the browser.

To be continued.

Facebooktwitterredditpinterestlinkedinmail

Adding servlet-api.jar to Eclipse project

As you may know, if you have servlets in you Java project you need to add servlet-api.jar to you Web App Libraries. Since I don’t work in Eclipse very often, I always keep forgetting how to do it. So, here is a short instruction with pictures.

Go to Web App Libraries/Build Path/Configure Build Path…

screen-shot-2016-09-11-at-21-31-16

Click Add External JARs…

screen-shot-2016-09-11-at-21-30-40

Find and choose the servlet-api.jar file. It should be located in the lib folder of your Tomcat. In my case the path to the file is:

/usr/local/apache-tomcat-8.0.33/lib/servlet-api.jar

Facebooktwitterredditpinterestlinkedinmail

Implementing a Custom URL Scheme (iOS)

Somebody asked me to add a custom URL scheme to my app, so that they could open the app from a launcher. Before that, I had only done it once, so it took me some time to Google this topic and remind myself of how it’s done.

This post will serve as another memo for me. This is how you add a custom URL scheme to your app:

Defining your app’s custom URL scheme is all done in the Info.plist file. Click on the last line in the file and then click the “+” sign off to the right to add a new line. Select URL Types for the new item. Once that’s added, click the grey arrow next to “URL Types” to show “Item 0”. Set your URL identifier to a unique string – something like com.yourcompany.yourappname.

After you’ve set the URL identifier, select that line and click the “+” sign again, and add a new item for URL Schemes. Then click the grey arrow next to “URL Schemes” to reveal “Item 0”. Set the value for Item 0 to be your URL scheme name.

The quote and the image are from this site.

Facebooktwitterredditpinterestlinkedinmail

Developer’s guide to learning design (and Photoshop)

Here are my thoughts on how one can start learning UI design.

For a very long time I thought that I don’t need to learn design. Or, more precisely, I thought that I must not learn design, because I’m a specialist, and specialists don’t waste their time on things that are outside of their domain of expertise.

But the thing is, I’m interested in design. As far as I can remember I always loved to draw, and I believe I do have at least some artistic abilities. Also, it seems so cool to be able to design and then develop you own apps from start to finish. Nothing hinders your creativity. You don’t  just implement other people’s ideas, you come up with your own ideas, and everything you create is truly yours.

So, I decided to at least try to learn something about design. Maybe I’ll get serious about this design thing one day. And maybe it will not be that bad. Yes, if I do it for real, I might be spreading myself to thinly. But on the other hand, what if I become one of those mythical creatures called unicorn developers? Wouldn’t that be cool?

Learning design is a lot like learning programming

Anyway, for now I’m just learning the basics. More specifically, I decided to learn Photoshop. I have already spent several evenings learning Photoshop, and here is what I have found out.

Learning design is a lot like learning programming. At first I didn’t know where to start, and I thought that maybe I needed to buy a course on Photoshop. But then I decided to take the approach I used for learning programming. And it worked.

First of all you need to learn how to use the tools. To do it you just draw something. And when you try to draw something in Photoshop, you are going to have lots of questions. When you have questions, just Google them. That’s how you learn design. And that’s how I learned programming. There is no need to buy any courses.

What to draw? Don’t try to create at first. Just copy. I believe it is very important, and here is why. If you try to create something as a beginner, you creativity will be hindered by you lack of ability. So you will end up producing something too simple and too ugly. You might have a great vision inside your head, but then you will have to simplify it and distort it to match your limited abilities.

On the other hand, if you just forget about creativity for a while, and concentrate on copying stuff, that will enable you to develop your abilities. This way you know exactly what you are trying to achieve, and you just do whatever it takes to recreate someone else’s design. Your newly developed skills will let you be creative later.

The best way to start with this approach is to go through some tutorials. Here are the tutorials I used.

Tutorial 1Tutorial 2Tutorial 3.

And this is just one example of what I ended up with:

web-ui-kit

Tutorials are good, because they tell you in great detail, what you should do. I think it is the best way to learn different tools in Photoshop.

I plan on going through a couple more tutorials. Then, the next step is to find a design that I like and try to copy it. This time without a tutorial. Then I will do it for many times for different designs.

Notice, how it is exactly the same as learning programming. In programming you too go through a bunch of tutorials at first. Then you create a bunch of your own apps. Only after that you read books and go through courses.

Other things I discovered

When it comes to mechanical skills of a designer (like ability to use Photoshop) I believe they can be all divided into two big areas.

One is all about rectangles and texts. Seriously, while going through the tutorials, that was all I was doing: drawing rectangles and texts. Now, when we talk about text, there is this thing called typography which is an entire field of knowledge in its own right, and there is a lot I can learn there. But for now I like to think about texts and rectangles as being two parts of one skill set which is all about placing stuff on the screen.

Note, that here I’m only talking about the mechanics of design process. There is a difference between knowing how to place stuff on the screen and knowing where to place stuff on the screen. I’m not even starting to think about learning the latter part just yet.

The second area (or a skill set) is all about illustrations. This one I haven’t yet started to learn. But I think it can be learned the same way, through tutorials. In this case the tutorials don’t need to be necessarily focused on UI design. They can be more general and focused on little things, like, for instance, how to draw a semicircle, or a sector. Stuff like that. Also I know that designers like to use other people’s artwork when it comes to icons, so maybe learning how to do illustrations is not that crucial for a UI designer.

There is also a funny little thing I have learned. Usually, when designers give me their designs so that I can start developing an app, I often notice that they misspell words. Like all the time. And over time that lead me to believe that maybe designers as a species are sort of not very bright people, to put it mildly.

Now, when I started learning Photoshop I discovered the real reason for designers’ ‘illiteracy’. It turned out that Photoshop doesn’t have a spell checking capability (or at least I haven’t found one). BTW, can you find a typo in the picture in this post? I didn’t make it on purpose.

Facebooktwitterredditpinterestlinkedinmail

Implementing scrolling behaviour without UIScrollView

Suppose you want to create a screen that looks something like this.

fortune_wheel

How would you do it? You may think that the labels on the right side can be put inside a UITableView. But there is a problem: each label belongs to a certain sector on the wheel, meaning that each label should be aligned vertically to a corresponding number on the wheel. So, as you rotate the wheel, the vertical distances between the labels will not stay the same. I’m not sure if you can dynamically change the row height in UITableView, but even if you could, this approach doesn’t seem to be right.

When I had to implement such a screen, I basically created my own version of a table view, with reusable cells for the labels on the right side as well as for the sectors of the wheel. I’m not going to go into detail about how I did it. The process was pretty straightforward. Actually there was no table view. It was just a bunch of reusable views which I called cells by analogy with UITableView.

What I want to tell you about, though, is how I implemented the scrolling. Because I had some problems with it.

There are two parts to scrolling. First part is when your finger is on the screen. The second part is the inertial movement of views after you lift your finger off the screen.

The first part you implement in the touchesMoved:withEvent: method. It may look something like this:

What happens here is easy to understand.

In the second part, at the moment when you lift your finger off the screen, you need to calculate the initial angular velocity with which the wheel will start its rotation. That velocity will then decrease with time. The problem I had was about calculating that initial velocity.

The solution was easy but I was thinking too hard.  I tried to implement strange use cases. I thought, what if you put your finger on the screen, then move, then instead of lifting it you wait for some time, and then with quick movement you swipe and lift your finger? Now, I thought, the velocity in this case should be calculated based only on the last swipe. And the first movement should be ignored.

What I did was I saved the position and time of the last touchesMoved event. Then I used it in touchesEnded:withEvent to calculate velocity. So, to calculate the initial velocity of inertial movement of the wheel I used only the last microscopic movement of the finger. And it sort of worked. But not always. In most cases that last little movement would take about 0.01 seconds. But in some cases it would take much less than that, something like 0.00001 seconds. The movement itself almost always was no less then 2 pixels. That would result in a very high speed. Imagine that you don’t do a swipe, and just gently lift your finger off the screen, expecting the wheel to stay still, but it starts rotating!

I tried to artificially limit the velocity, but it resulted in stalling of the wheel from time to time. Finally, as an experiment I tried to use the whole movement of the finger, not just its tiny last part. And it worked! Then I compared the behaviour of my screen to that of a normal UITableView, and as far as I could see it was exactly the same. So, that lead me to believe that’s exactly how the scrolling is implemented in UITableView. Here is the code that I used (not exactly):

Update (September 6, 2016)

OK, it turned out that it wasn’t as simple as I described it in this post. I had to make one little adjustment.

Imagine, that you move your finger on the screen and then stop, wait a second, and then just lift your finger off the screen. In this case the wheel must not move. But in the simplistic model that I have described above you may produce an undesirable movement of the wheel.

How to fix this? You need to analyse the last part of your touch to learn if there was a significant enough movement of the finger in that last part. If there was no movement or it was less than a certain amount of points, you just set the angular velocity of the wheel to zero.

Facebooktwitterredditpinterestlinkedinmail

Creating a settings screen using UITableViewController

A settings screen is a screen that looks something like this:

When I started out with iOS development, I knew only one way of creating such a screen. I would create a UIScrollView and just put all the views and their constraints on it manually using the Interface Builder. That was a lot of work but at that time I didn’t know any better.

Once I had a job interview. And an interviewer asked me how I implemented a certain settings screen in my app. I told him it was a UIScrollView with a bunch of views in it. He asked me why I hadn’t used UITableView, that way I could have  implemented repeating elements as UITableViewCells. Good idea! – I thought.

Up until that point I only used UITableView with dynamic cells. So I tried table views with static sells. It turned out you can only use them inside UITableViewController, and not inside UIViewController with a table view. That got me confused. I couldn’t figure out what was the use of a UITableViewController, since there was no way to customise it. For instance, you can’t add a button at the bottom of the table view if that table view is inside UITableViewController.

Having no luck with static cells I tried using table views with dynamic cells to create settings screens.I used this approach in a couple of projects. It worked, but it wasn’t much of an improvement over using UIScrollView. With scroll view you have to do a lot of work in the Interface Builder. With table view with dynamic cells you have to do a lot of coding.   

Anyway, a couple of days ago I finally figured out how to use UITableView with static cells to create a settings screen. The solution is so simple, I can’t believe I figured it out only now, after 2 years of doing iOS programming.

This is how you do it. You create a UIViewController and a UITableViewController. Then you put your UITableViewController inside your UIViewController, as a child view controller. That’s it. If you want to put a button outside of the table view, just do it in the UIViewController. This is how it may look in your Storyboard. 

The cool thing is that once you created one cell, you can just copy it. Then in your UITableViewController you can make outlets for all your text fields, labels, buttons and other UI elements you have inside the table view. Also, when the keyboard goes up, the table view adjusts accordingly.

Unfortunately, I couldn’t customise the section headers right in the storyboard, so I had to do it programmatically. Here are the only three UITableViewDataSource methods that I implemented:

 

Facebooktwitterredditpinterestlinkedinmail

Adding and removing Child View Controllers

When you add or delete a child view controller, there is a number of things you need to do. For me it has always been  too easy to forget what things I needed to do and in which order. So I decided to create this post as a little reminder for myself. All the quotes and code examples are from Apple’s “View Controller Programming Guide for iOS”.

Adding a Child View Controller

  1. Call the addChildViewController: method of your container view controller. This method tells UIKit that your container view controller is now managing the view of the child view controller.
  2. Add the child’s root view to your container’s view hierarchy. Always remember to set the size and position of the child’s frame as part of this process.
  3. Add any constraints for managing the size and position of the child’s root view.
  4. Call the didMoveToParentViewController: method of the child view controller.

Example:

Removing a Child View Controller

  1. Call the child’s willMoveToParentViewController: method with the value nil.
  2. Remove any constraints that you configured with the child’s root view.
  3. Remove the child’s root view from your container’s view hierarchy.
  4. Call the child’s removeFromParentViewController method to finalize the end of the parent-child relationship.

Example:

 

Facebooktwitterredditpinterestlinkedinmail