After switching to Xcode 6 and the iOS8 SDK I was confronted with a strange error message when trying to test my app on a device. The app was built and deployed to the device but Xcode did not run it. Instead it showed an alert with the following error message:
Could not launch "APP_NAME", process launch failed: Security
The only thing you can do is to press “OK”, but the app still does not run. When you try to run it again from Xcode you just get the same alert.
The solution to this problem is quite simple:
Run the App from Xcode
When the alert shows, press “OK”
Open the app on the device
An alert will be shown, asking you if you want to trust this app. Press “Trust”.
That was quite useful when some feature in your app could not be used, because the user disabled something in his settings. In that case you could inform the user that he had to change his settings if he wanted to use that feature and offer to open the settings directly from your app.
Unfortunately Apple decided to not longer allow this after the introduction of iOS 5.1
Good news: This feature is back with iOS8! Apple has added a NSString constant to UIKit that you are supposed to use. To avoid crashes on iOS versions below iOS8 it is a good idea to check if the constant exists on the system version the device is running. You could check if the user is running iOS8 or higher but I prefer to check directly if the constant exits rather than checking the iOS version. Who knows if Apple will decide to remove this constant again in the future…
So, to open the settings, you can use the following snippet:
if let settingsURL = NSURL(string: UIApplicationOpenSettingsURLString) {
UIApplication.sharedApplication().openURL(settingsURL)
}
If your app has it’s own settings bundle, the settings will be opened showing your app’s settings. If your app does not have a setting bundle, the main settings page will be shown.
Unfortunately there does not seem to be a way to go directly to subpages of the settings (except your own settings bundle). If you’ve found a way to do that, please let me know in the comments!
Update: Linking to a subpage of the Setting seems to work again for system versions greater or equal than iOS8. It is not officially documented by Apple but it seems to work, although I not sure how reliable this is. It works on my iOS 9.1 iPhone but not in the Simulator. So I would not recommend to use this in production.
So, with caution, you can try this to open the Keyboard Settings:
if let settingsURL = NSURL(string: "prefs:root=General&path=Keyboard") {
UIApplication.sharedApplication().openURL(settingsURL)
}
Or go even one level deeper:
if let settingsURL = NSURL(string: "prefs:root=General&path=Keyboard/KEYBOARDS") {
UIApplication.sharedApplication().openURL(settingsURL)
}
To make these unofficial URLs work you might have to add prefs to the URL schemes of your project’s Info.plist file.
One thing that I really like in AngularJS is how easy it is to load JSONP from the server and work with the result. With just one line of code you have the JSON object “in your hand”:
Really easy. But at first I could not make it work. The request was returning a valid JSONP response but the Javascript would throw an error:
Uncaught ReferenceError: angularcallbacks_0 is not defined
As usual the reason for this error was quite simple once I found it: When you work with JSONP you need to add the name of the callback function (aka “padding”) to the request. The JSON that comes back from the server will then be padded in a function of the name that you provided. For example:
When you request a JSON file like this:
{"key": "data"}
using JSONP:
https://myurl.com/getlist?callback=myCallback
you will get the following response:
myCallback({"key": "data"});
When you use AngularJS, the callback name must be JSON_CALLBACK.
https://myurl.com/getlist?callback=JSON_CALLBACK
AngularJS changes the callback name internally to make sure that you can use several requests simultaneously. So your response will look like this:
angular.callbacks._0({"key": "data"});
So far so good. But when I looked at the response that I got I noticed that the callback name was missing the dots. That was the reason for the Javascript error. AngularJS was expecting angular.callbacks._0 when all it got was angularcallbacks_0.
As it turned out the PHP on the server side was stripping all dots from request parameters. That was the reason why the JSONP response could not be handled by AngularJS.
This surely is trivial to most developers, but I am not exactly a wizard when it comes to bash scripting. So let me just post this as a note to myself.
This is how you remove all files that contain a specific substring in their file name. In this example I use it to remove all the conflict files in a Dropbox folder:
Open your terminal and navigate to the folder that contains the files that should be removed. This folder can also contain subfolders. Files in subfolders will also be removed if they contain the substring “Konflikt”.
As you can see, my system language is German, so Dropbox names all conflicted files with the Keyword “Konflikt”. Just change that to your system language.
Be careful! Once you have removed the files there is no turning back. No “undo” button here!!!
Recently I used CSS transitions to animate some images inside an UIWebView. Everything worked fine and the transitions where really smooth. I used the translate transition to move the images that where inside a div HTML element:
To move the images I created a CSS class that contained the transition:
This worked as expected. However, when the images moved, there was an ugly flicker. It turned out that this is caused by a CSS property call “backface-visibility”. Normally this is used, when you do 3D CSS transitions (e.g. 3D rotations). “backface-visibility” determines whether the backside of a HTML element is visible, when it is not facing the screen. As I am not doing any 3D transitions it should not matter how this property is set. Wrong. Obviously in Webkit Browsers it does matter. To fix the ugly flickering you have to add the following to the CSS class:
And thats not enough. The flickering became less but it was still there. Only after I also set the “backface-visibility” property on the images themselves, the flickering went away completely:
I don’t know if this is a bug in Webkit or if there is a logical explanation for this behavior, but setting “backface-visiblity” to “hidden” on all animated elements did the trick.
Recently I encountered a problem with the keyboard while displaying a HTML form inside a UIWebView: The HTML form was a simple form to ask the login credentials from a user. Nothing more than 2 text input fields and a submit button. When the user tapped on an input field the iOS Keyboard came up, as it should. But then, when the user tapped the submit button, the keyboard stayed in placed and was not dismissed. The normal behaviour would be that the keyboard would be dismissed as soon as the textfield loses it’s focus. But somehow this was not happening.
I found several solutions on how to dismiss the keyboard programatically by either using javascript or calling resignFirstResponder on the UIWebView when the form was being submitted, but the keyboard would still not go away.
Then I found the solution to that problem. I turned out that the lingering keyboard was a UI design choice by Apple. The keyboard dismissal is disabled when you present your UIWebView using a modal ViewController with presentation style UIModalPresentationFormSheet!
The solution is quite simple: You have to override your ViewController’s disablesAutomaticKeyboardDismissal method:
During my current project I had to move a time consuming CoreData operation to a background thread to avoid a frozen UI. After reading some horror stories about using CoreData on a background thread I was actually surprised how straight forward it was. I used Apple’s sample code ThreadedCoreData as a guidance. When I tested my changes everything went smooth. Until I started to touch my app’s UI while the background process was running. Suddenly the app crashed and the following exception was thrown:
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x1f0ec200> was mutated while being enumerated.'
The exception was being thrown on the background thread during a call to
In Apple’s example code the CoreData operations happen inside the main method of a custom subclass of NSOperation. That subclass is initialized using a custom initWithData: method and then added to a NSOperationQueue.
When doing CoreData operations on a background thread it is important that the background thread uses it’s own instance of NSManagedObjectContext. And this NSManagedObjectContext has to be instantiated on the background thread.
And that was the problem.
In Apple’s example the NSManagedObjectContext for the background thread is instantiated in the custom initWithData: method of the custom ParseOperation class. But that method is called on the main thread when instantiating a new ParseOperation object before adding it to the NSOperationQueue. So the NSManagedObjectContext instance is created on the main thread!
The solution was quite simple:
After moving the code that instantiates the NSManagedObjectContext from the initWithData: method (called from the main thread) to the main method (called from the background thread), the problem vanished and the code run smoothly.
So, when using CoreData in a background thread make sure that the background thread has it’s own NSManagedObjectContext instance that was created on the background thread!
And now for something completely different: After updating my OS to Mountain Lion, one thing was driving me nuts:
I just could not drag any window (Chrome, Finder etc.) from my MacBook Pro’s display to my secondary monitor (which I arranged on top of my MacBook Pro monitor). It just was blocked by the menu bar.
I took me a while to figure it out but apparently you have to show a little persistence: Just keep on dragging! At first the window is stuck below the menu bar but then just as the mouse is about to reach to top of the secondary monitor, the window jumps to the secondary monitor as well.
Sometimes when you transfer your project to another computer and especially when you create a new developer certificate in the progress, you’ll run into difficulties. When you try to run your app on a device, Xcode will throw the following error:
Code Sign Error: Provisioning Profile '###ID###' can't be found.
The problem is that in your project’s project.pbxproj file the old provisioning profile identifiers are still lingering. You need to clean up that file so that Xcode can build your project without errors.
Here’s how you do that:
1. Close Xcode
2. Right click on your project’s .xcodeproj bundle to show it’s contents.
3. Open the .pbxproj file in a text editor of your choice (make a backup copy first if you feel paranoid)
4. Find all lines in that file that include the word PROVISIONING_PROFILE and delete them.
5. Open Xcode and clean your project
6. Build your project
80F04C2F14BDF2CD00851339 /* Ad Hoc */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "iPhone Distribution: Caramelized GmbH";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "CaramelReader/Caramelized-Prefix.pch";
INFOPLIST_FILE = "CaramelReader/Caramelized-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.1;
PRODUCT_NAME = Caramelized;
↓ DELETE THIS LINE! ↓
PROVISIONING_PROFILE = "8B3033A4-0E28-42F8-80FC-70B6C3C473C7";
↑ DELETE THIS LINE! ↑
WRAPPER_EXTENSION = app;
};
name = "Ad Hoc";
};
Adding In-App Purchase items to your Application in iTunesConnect by hand is a boring and time consuming task. When I realized that I’d have to add about 1000 items for my app I really did not want to do that manually. Luckily there is a tool for mass upload of In-App Purchase items. It is a bit hidden though.
When you log in to iTunesConnect and select “Manage your Apps” there is a section in the footer called Application Loader. That’s the tool you’ll need.
Download Application Loader and the Spreadsheet Example. With Application Loader you can select a text file that contains a list of the In-App Purchase items that you want to add to your app. It is a tab separated list that contains all the metadata that you’d normally add manually when adding an item in iTunesConnect. Have a look at the spreadsheet example to see what format the list should have.
To add the mandatory screenshots I found it easiest to put all the screenshots in one folder and name the screenshot according to the product ID. If your item’s product ID is com.yourdomain.product1 than the screenshot must be named com.yourdomain.product1.jpg.
If you have that text file all you have to do is select the file in Application Loader, select the screenshot folder, hit “next” a couple of times and then “deliver”.
Voilá, that’s it! Do not panic if your new In-App Purchase items do not show up in iTunesConnect right away. Sometimes it takes a couple of hours(!) before the show up.