Latest Entries

Cocoa error 1671

Last week, I came across quite a serious bug in one of our iOS apps: all application data was lost when the app was quit. This is what happened:

Our app used Core Data to store things to disk, making these persist across app runs. Realising no data was available when the app started for the second time, I had a look at our saving routine:

NSError *error = nil;
BOOL saved = [managedObjectContext save:&error];
if (!saved || error) {
    NSLog(@"Failed to save: %@", error);
}

Nothing out of the ordinary. A break point tells that this code is run, the console shows no error, all good.

Having read this post, I now know to poke a little deeper in a case like this, but I hadn’t. So I wandered though the app for a while, until I finally returned here and put a break point on the line:

NSLog(@"Failed to save: %@", error);

Surprise: it breaks. Turns out our trusty NSLog silently fails to log this error! From here on, things start to roll:

(lldb) po error
(NSError *) $1 = 0x0882eec0 [no Objective-C description available]

Hm, that might be related..

(lldb) p (int)[error code]
(int) $5 = 1671
(lldb) po [error domain]
(id) $6 = 0x00b7655c NSCocoaErrorDomain
(lldb) po [error localizedDescription]
(id) $7 = 0x0d628730 The operation couldn’t be completed. (Cocoa error 1671.)

Google (and Bing) tell me: No results found for “Cocoa error 1671″. While 1671 has been used as a number before, there is absolutely nothing to be found in relation to iOS, Cocoa, or Apple. But wait, let’s try:

(lldb) po [error userInfo]
(id) $8 = 0x0882f080 {
    NSLocalizedDescription = "The operation couldn\U2019t be completed. (Cocoa error 1671.)";
    NSValidationErrorKey = firstLetter;
    NSValidationErrorObject = "<NSManagedObject: 0x882c030> (entity: Person;
        id: 0x882c080 <x-coredata:///Person/t41AD32DB-D331-4A65-A964-FB0B4359BAAA2> ;
        data: {\n firstLetter = \"\\Ud83c\";\n})";
    NSValidationErrorValue = "\Ud83c";
}

Et voila. What all printers failed to show me, the NSDictionary description was able to escape for \U2019readability\U2019 purposes. With great success: “\Ud83c” is not a valid string. A quick search on www.unicode.org/charts tells me I’ve been bitten by something out of the High Surrogate Area.

Isolated surrogate code points have no interpretation; consequently, no character code charts or names lists are provided for this range.

My bad. To determine the fist letter of a person’s name, I naively used:

NSString *firstLetter = [fullName substringToIndex:1];

And NSString isn’t really strict when it comes to the more exotic characters of the Supplementary Multilingual Plane, like emojis. These characters are represented by two 16 bit characters, which makes using substring and character methods a lot less obvious. Apple does warn about this in its documentation:

If you need to access string objects character by character, you must understand the Unicode character encoding, specifically issues related to composed character sequences.

Yes Apple, I’ll read it tomorrow, promise. Anyway, the Characters and Grapheme Clusters article from the iOS String programming Guide provides a valuable introduction, leading me to the proper implementation:

NSString *firstLetter = [fullName substringWithRange:
    [fullName rangeOfComposedCharacterSequenceAtIndex:0]];

All of a sudden everything starts working. Core Data stores first letter “\Ud83c\Udf3″, NSLog logs again, lldb debugs again, ttgtb.

Unicode is great fun, don’t miss out on it! Read some on Wikipedia, for example Supplementary Multilingual Plane. Knowing just a few fundamentals will save you lots of time, especially when people start using the iPhone’s Emoji keyboard. And the second lesson learned: do not trust NSLog.

Who’s name did cause all this trouble in the first place? http://en.wikipedia.org/wiki/%F0%9F%8C%B5.

Leonard van Driel
iOS developer at Noodlewerk

Meet the Makers: Growing pains

Noodlewerk and Innovattic organize another Meet the Makers. See below for more infomation:

In the 3rd edition of Meet the Makers: Growing pains two important people from larger companies (100-150 people) will talk about their growth: from startup to mature company.

Wednesday, April 4, 2012, 7:00 PM at Grand Cafe SPING, Nieuwe Plantage 58, Delft (map)

Please RSVP at Meetup.com to attend. We have limited space available.
Entrance is free and drinks are on the house.

We thank Sping to make this event possible.

Mendix
Abstract: hundreds of successful deliveries, one hundred employees, six years, one vision.
Interesting note: Mendix recently raised 13 million dollar.
Speaker: Johan den Haan, CTO of Mendix

Nimbuzz
Nimbuzz combines the powers of the Internet and mobile communications into one, and lets you make calls, send messages and share files, on any mobile device, for free. Nimbuzz is very popular in the East has got 80 million users.

Speaker: Evert-Jaap Lugt, CEO of Nimbuzz

Appsterdam Delft

2011 for Noodlewerk

Looking back at 2011, we are very proud. We expanded the team and got some talented new developers and designers. We made dozens of new iPhone, iPad and Android apps. We gave a design talk at the BNO in Amsterdam, we started Appsterdam Delft together with Innovattic, we did a tech talk at a Cocoa Heads meeting and presented our work at other various events.

This year was the year of the iPad. One of the highlights is “Money and Speed”, one of the iPad apps we made with the VPRO, which has won the Dutch Design Award in Eindhoven.

We made iPad versions of Uitzending Gemist, Radio apps and Z@ppelin for the Publieke Omroep (NPO). Digidentity will release a really nice iPad app for digitally signing documents and Raet has now an iPad version for their Netto app.

Another surprise was that we were nominated for being the developer of the year and our app Uitzending Gemist was nominated for best app of the year at the onemorething Awards 2011.

In 2011 we got the chance to work with companies like Consumentenbond, Raet, Digidentity, Troostwijk, Greenwheels and the Good and Green Guides. Not only did we make new mobile apps for those companies. We continued making apps for the NPO, VPRO and Parkmobile. And of course we should not forget the Android versions we made of Uitzending Gemist, Luisterpaal, Film it Yourself, Radio apps, Parkmobile and Park-line which all came out this year.

We will keep on developing and designing the best apps possible for all the great services our clients provide!

The Noodlewerk Team

Bookmarklet to auto-fill “Add New Test User” form in iTunesConnect

Sandbox test users for testing your In-App Purchase, tend to break very quickly, as they are blocked by Apple as soon as you (accidentally) use them in the App Store app (which happens very easily by mistake). If you want to create a bunch of new test users, you have to fill in a lengthy form in iTunesConnect for each one of them. Make sure you set up a catch-all on your e-mail server.

Here is a bookmarklet that auto-fills the whole form. You only need to press the “Save” button now.

javascript:var country = "75"; var rnd = Math.round(100000 * Math.random()).toString(); document.getElementsByName('0.0.9.7.3.1.19.1')[0].value = "Noodle" + rnd; document.getElementsByName('0.0.9.7.3.1.19.3')[0].value = "Werk" + rnd; document.getElementsByName('0.0.9.7.3.1.19.5')[0].value = "test" + rnd + "@mydomain.com"; document.getElementsByName('0.0.9.7.3.1.19.7')[0].value = "SBTest01"; document.getElementsByName('0.0.9.7.3.1.19.9')[0].value = "SBTest01"; document.getElementsByName('0.0.9.7.3.1.19.11')[0].value = "What's this nonsense?"; document.getElementsByName('0.0.9.7.3.1.19.13')[0].value = "Your Mother, doophus."; var monthOptions = document.getElementsByName('0.0.9.7.3.1.19.15')[0].childNodes; for (var m in monthOptions) { if (monthOptions[m].value === "1") { monthOptions[m].selected = true; }; }; var dayOptions = document.getElementsByName('0.0.9.7.3.1.19.16')[0].childNodes; for (var d in dayOptions) { if (dayOptions[d].value === "1") { dayOptions[d].selected = true; }; }; var countryOptions = document.getElementsByName('0.0.9.7.3.1.19.18')[0].childNodes; for (var c in countryOptions) { if (countryOptions[c].value === country) { countryOptions[c].selected = true; }; };

Tutorial: Using Charles proxy to debug HTTP(S) communication between server and iOS apps

Abstract

In all the apps we have developed so far, we have witnessed the use of tightly coupled communication between the iOS app on the device and a remote web service. For example, an app might request a JSON encoded list of popular items from the web server that is displayed to the user in a nice table. No matter how much time is spent on defining and specifying communication protocol, during development (and sometimes even during production) there are moments when there are problems with these app vs. server interactions.

Especially when these problems occur on the device or during production, it can be hard to trace the problem without the proper tools. Using a good proxy all communication between app and server can be monitored, which makes tracing these issues much easier. In our tutorial we’ll focus on HTTP and HTTPS traffic only and we will be using the Charles proxy, which is available for Mac, Windows and Linux/UNIX. Knowledge on the HTTP protocol is expected.

Intercepting HTTP traffic

Install Charles. There is a free trial, but costs $50 if you want to get rid of the nagging splash screen. Launch the app. It will immediately prompt you to ask for permission to configure the necessary network settings. This is needed in order for Charles to intercept network traffic. Choose “Grant Privileges” for the easy route.

By default, it will start recording HTTP traffic immediately, so you’ll see the table get filled with calls e.g. if you are browsing the web on your computer. You can try that for a start, for example by visiting google.com like I did here. On first start, the “Structure” tab will be selected. The Structure tab shows an expandable tree of hosts and paths that have been requested and intercepted during this Charles session. If you expand a visited hostname (e.g. www.google.com), you’ll get subpaths that have been visited, etc.

The other view is the “Sequence” view. Instead of presenting requests by hostname and path, it shows requests ordered by time. Personally, I usually use this view most of the times. If you select a request, you will get all the details for that request in the pane below the list of all requests (I selected a request to Twitter’s search.twitter.com in the next screen shot). Basically, the Request and the Response sections present the request sent by the app and the response received from the server.

On the bottom of the details viewer, there are some options that depend on what section of the details you are in. For example, in the Request section, you can view the Request’s Query String (previous screen shot) or the Request Headers (next screen shot).

One of the nice features of Charles is that is able to detect a few commonly used container formats, like JSON and XML, probably based on the Content-Type response header. For example in the case the response contains JSON, Charles will show a “JSON” tab with a view that formats the JSON response conveniently in a more readable way instead of just displaying raw text.

Proxying traffic from an iOS device to Charles

The next step is to use Charles to inspect traffic from an actual iOS device. The easiest way to do this, is to use Charles’ built-in proxy. First you need to tell your iOS to use the proxy. Go to Settings > Wifi > Select the Wifi network and make sure your machine that is running Charles is also in this network. Scroll down to the “HTTP Proxy” setting. (See next screen shot.) Select “Manual”. Enter the IP address of your machine that is running Charles. You can find the IP address quickly in Charles’ Help > Local IP Address menu. Enter “8888″, which is the default proxy port of Charles. Authentication is off by default.

Now open up an app that uses HTTP calls to a server (e.g. browse the web in Safari). Charles will detect that a new host is trying to use its proxy. You will need to accept it once by choosing “Allow”:

Once allowed, traffic will flow from your iOS device through Charles, which will forward it to its destination (while allowing you to inspect it). In the next screen you can see what traffic the Google Maps app is causing when I’m panning over the map on my iPhone (no JSON there but many binary responses):

Intercepting SSL traffic from an iOS device using Charles

Now you might think, wait a minute, what about SSL / HTTPS traffic? What if my fancy web service is using an encrypted connection? Well, fortunately there is a pretty simple way to inspect that as well. In this contrived example, we will look into encrypted traffic from Safari to https://mobile.twitter.com/. Open up the Proxy Settings menu from Charles. Add the hostname of the HTTPS server. In our case we added “mobile.twitter.com” and the default SSL port 443:

If you try visiting https://mobile.twitter.com/ from your proxied iPhone, Safari will present you a warning that it cannot verify the server’s identity because the Charles proxy is using untrusted, self-signed certificates.

You don’t want this, because the (correct) default behaviour of iOS (and NSURLConnection for example) is to disallow untrusted server connections. The solution is to add the Charles root certificate (the certificate that is used to generate SSL certificates on-the-fly when you are using the proxy) to the list of trusted root certificates in your iOS device. To do this you need to add a configuration profile containing Charles root certificate bundle. To save everyone some time, we created a signed configuration profile with Charles’ certificate bundle  for everyone to use.

If you visit http://charles.noodlewerk.com/ using Safari on your iOS device, you will be prompted whether or not you want to install the profile and the containing bundle. Once installed, iOS will trust the Charles proxy and will act as normally. Note that in essence you are weakening the security by installing this profile. So it is wise to remove the profile once you are done debugging if you are using your device in real life :)

Converting Mac Type 1 fonts to OpenType or TrueType

For a particular iOS project we received some old school Type 1 fonts. These Type 1 fonts do not seem to be supported by iOS, so they need to be converted to either OpenType or TrueType. Doing this for the first time took us quite a while to figure out, so decided to share it here.

The font files itself are a bit mysterious because they appear to be empty at first sight. Back in the days, people were using a legacy Mac OS feature called “resource forks”. This is a file system feature that has been around since one of the first Macs and has since been supported, even up until the latest Mac OS X.

Inside the resource fork of the Type 1 fonts, there is “printer font binary” data, wrapped with some other data. To convert the font, first we need to extract that “printer font binary”. There is a command line tool called “t1unmac” which is available through the MacPorts project.

Install the Type 1 command line tools and its dependencies:

sudo port install t1utils

Then use t1unmac to extract the “printer font binary” and save it into a file. Note that RawNor is the Type 1 font file here, and  /..namedfork/rsrc is added to the file name to access the resource fork.

t1unmac --raw RawNor/..namedfork/rsrc -o RawNor.pfb

Once you have the printer font binary (.pfb file), you can take a shortcut and use an online font converter like this one http://www.fontconverter.org/

Or you can take the long way home and install FontForge and use the example script they provided to convert from .pdf to .ttf or .otf.

Charles SSL Proxy .mobileconfig

I just created a convenient mobile configuration file to easily add the default Charles SSL Certificate Bundle to the list of trusted roots in iOS.

Just open http://charles.noodlewerk.com/ in Safari on your iPhone, iPod or iPad and it will prompt you to confirm installation of the Charles’ default SSL bundle.

Happy SSL sniffing!

Meet the Makers 2: Appsterdam Delft

We are happy to announce a new episode of “Meet the Makers” from Appsterdam Delft. We have invited top-notch designers and entrepeneurs that will be speaking about their apps and the creative processes behind it. Look below for more details about the speakers.

Location: SPING
Address: Nieuwe Plantage 58, Delft
Date: Wednesday October 26th
Time: 19:00 – 22:00 (introduction starts at 19:10)
Host: Ianus Keller

Please RSVP at the meetup.com page if you are planning to come, so we can make sure there is enough food, drinks and space for everyone: http://www.meetup.com/Appsterdam/events/35310372/

Afterwards, we might get some drinks in the city centre of Delft.

Hope to see you there,

Martijn Thé – Noodlewerk & Lauwerens Metz – Innovattic

Meet the Makers 2: Appsterdam Delft

These designers and entrepreneurs will be speaking about their apps and the creative processes behind it:

Alexander Griekspoor, Founder & CEO Mekentosj.com — Apps for scientists. Won 2 Apple Design Awards. Alex will be talking about his journey of the last 10 years as Mac software designer, entrepreneur and scientist.

Randy J. Hunt, creative director Etsy.com — Randy will give a peak behind the screens of the biggest and fastest growing community on the web of buyers and sellers of hand made products. How Etsy gets shaped and tweaked every day by Randy and his team of designers.

Cloud9 (http://c9.io) — This Appsterdam-based company has created a fully-fledged web app development tool suite that runs inside the browser! Yes it’s crazy and very hot. If there is one company that is stretching the browser beyond it’s limits of app-ness, it’s Cloud9.

Big thanks to SPING Delft for donating the venue, drinks and fingerfood!

Big thanks to Innovattic and Noodlewerk for the other leg work.

Jorn van Dijk van Noodlewerk spreekt bij BNO Tallks: apps & tabs (22 sept.)

Donderdag 22 september zal Jorn van Dijk te gast zijn als spreker  bij BNO Tallks in Pakhuis de Zwijger te Amsterdam. Het thema van de avond is “Apps & Tablets”. Het programma begint om 19:30. Na het programma zijn er nog “netwerktafels” waar er per thema gesproken kan worden met de uitgenodigde experts.

De sprekers:

Zie ook http://www.bno.nl/tallks

Checklist iPhone/iPad App aanmelden bij de App Store

Na het ontwikkelen van een applicatie wilt u graag dat deze soepel door het goedkeuringsproces van Apple heen komt en op zijn pootjes in de App Store terecht komt. Ook al is de ontwikkeling van de iPhone applicatie nog in volle gang, is het zinnig alvast na te gaan wat er nodig behalve de applicatie zelf. Bij het indienen van een iPhone applicatie bij de App Store komt ‘t één en ander kijken. Hier alles op een rijtje.

Contracten iPhone Developer Program

De nodige contracten met Apple dienen in orde te zijn alvorens de applicatie ingediend kan worden. Dit kan een aantal weken duren. De kosten hiervoor zijn $99 per jaar. Meer informatie over het iPhone Developer Program kan worden gevonden op de site van Apple. Het is ook mogelijk gebruik te maken van onze bestaande licentie. Het voordeel is dat  de jaarlijke kosten en de tijd die Apple nodig heeft om de contracten in orde te maken vermeden worden. Let wel dat bij gebruik van de bestaande licentie “Martijn Thé – Interaction Design” als uitgever van de applicatie wordt aangemerkt in iTunes en de App Store.

Promotionele teksten en beeldmateriaal

In de App Store en iTunes worden applicaties gepresenteerd met iconen, tekst en screenshots. Daarnaast dienen er links naar sites opgegeven te worden waar informatie over de applicatie en de uitgever gevonden kunnen worden. De meeste van deze gegevens dienen ingegeven te worden in iTunesConnect. Op een rijtje:

Tekst

In de iTunes Store worden tegenwoordig slechts de eerste 3 regels van de promotionele tekst weergegeven. De rest van de tekst kan worden uitgevouwen met door op “Meer…” te klikken. Maak goed gebruik van deze eerste 3 regels om de lezer te boeien.

Links

Direct onder de tekst in iTunes verschijnen twee links: “BedrijfsNaam website” en “ApplicatieNaam ondersteuning”. Deze links komen overeen met de velden Application URL en resp. Support URL in iTunesConnect. Het is zaak te zorgen dat bij het indienen van de applicatie deze links daadwerkelijk actief zijn. Er zijn in het verleden applicaties afgekeurd omdat de bijhorende info/support website nog niet af was.Er dient ook een Support Email opgegeven te worden in iTunesConnect. Naar dit adres worden vragen van gebruikers van de applicatie gestuurd, wanneer zij de “Meld Probleem” functie gebruiken in de App Store applicatie.

Screenshots

Tenminste één en maximaal vijf screenshots kunnen worden geüpload. Deze verschijnen in iTunes onder de promotietekst (de 3 regels, of de uitgevouwen tekst). In de App Store applicatie verschijnen deze afbeeldingen enigszins verkleind ook onder de tekst, in een scroll paneel. Het is aan te bevelen niet alleen screenshots, maar ook “reclame”-achtige afbeeldingen te gebruiken die de functies en unieke voordelen van het product uitleggen, of de applicatie in context laten zien. Een aardig voorbeeld van creatief gebruik van de afbeeldingen in de App Store is de Vocoder Synthesizer SV-5. Deze applicatie vervormt stemgeluid. De werking er van is visueel gepresenteerd in één van de vijf plaatsen voor “screenshots”. De afbeelding op een aantrekkelijke manier uit wat de applicatie doet. De toegestane formaten voor deze afbeeldingen zijn 320 x 480 pixels of 480 x 320 pixels. Wanneer het een screenshot betreft, dient de statusbalk van het screenshot afgesneden te worden zodat de afbeelding 20 pixels lager wordt.

Iconen

Zie post over de iconen.

Categoriën

Aan elke applicatie kan een primaire en secundaire categoriën toegekend worden door de uitgever. Op dit moment kan gekozen worden uit: Book, Business, Education, Entertainment, Finance, Games, Healthcare & Fitness, Lifestyle, Medical, Music, Navigation, News, Photography, Productivity, Reference, Social Networking, Sports, Travel, Utilities, Weather. Voor elke categorie worden top lijsten samengesteld. Het kan zinnig zijn om strategisch hiermee om te gaan door te kiezen voor één die raakvlak heeft met de applicatie, maar niet zo druk bevolkt is als een andere, wellicht voor de hand liggende categorie.

Trefwoorden

Er kan voor 100 tekens aan trefwoorden opgegeven worden (inclusief scheidende spaties). Trefwoorden kunnen alleen aangepast worden bij het (her)indienen van een nieuwe applicatie of updaten van een bestaande applicatie. Ze kunnen dus niet worden aangepast voor applicaties die al in de App Store staan. De trefwoorden worden gescreend bij het indienen.

Release datum

Standaard wordt de release datum op de dag van indienen ingesteld. In praktijk gebeurt het nooit dat een app daadwerkelijk op de dag van indienen in de App Store komt te staan. Het review proces van Apple duurt meestal minder dan 2 weken. Wanneer een applicatie goedgekeurd wordt, staat hij nagenoeg meteen in de App Store. Per e-mail wordt een notificatie verzonden zodra de applicatie door de keuring is. Als de datum van release beter gecontroleerd dient te worden, is het aan te bevelen de applicatie zo ver vooruit als mogelijk in te dienen, en de release datum in de verre toekomst in te stellen. Zodra er positief bericht van de keuring binnen is, kan de datum opnieuw ingesteld worden naar het precieze moment dat de applicatie zichtbaar moet zijn in de App Store. Let op: een applicatie verschijnt niet in de “Nieuw” lijst in de App Store als de release datum in het verleden ligt. Het is dus zinvol de release datum opnieuw in te stellen als de applicatie net goedgekeurd is naar de datum van goedkeuring. Op die manier komt de applicatie bovenaan de “Nieuw” lijst te staan.



Copyright © 2004–2009. All rights reserved.

RSS Feed. This blog is proudly powered by Wordpress and uses Modern Clix, a theme by Rodrigo Galindez.