Whether the web service you’re working with is using HTTP Basic Auth or HTTP Digest Auth, as long as you’re using NSURLConnection, NSURLCredential has you covered.

Apple have made it very easy for us developers. All we have to do is implement a delegate method.

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
	if ([challenge previousFailureCount] < 0)
	{
		[[challenge sender] cancelAuthenticationChallenge:challenge];
		return;
	}
 
	NSURLCredential *credential = [NSURLCredential credentialWithUser:aUsername 
                                                                 password:aPassword 
                                                              persistence:NSURLCredentialPersistenceForSession];
	[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}

And that’s it. NSURLCredential will handle both HTTP Basic and Digest auth for you, including all the ugly base64 encoding and MD5 hashing.

Apple has a couple of weeds taking root in their walled garden recently.

The most recent being the Pokemon fiascos. There are a few “apps” in the App Store that are currently occupying alarmingly high rankings in the top app listings. One of these is “Pokemon Yellow”. “Wow, Pokemon Yellow is in the App Store!” Hold it right there.

It’s a scam, (you knew that, right?) According to the countless 1 Star reviews, the “game” simply opens, displays a picture of one of the newer Pokemon Nintendo DS games (not even Pokemon Yellow) and then promptly closes, leaving the poor sap who just paid 99c feeling a little more than dumb.

So what’s the problem here? The fact that someone is ripping off Mega Giant Nintendo for a quick buck? The fact that the app doesn’t work as advertised? That fact it’s blatantly a scam? These are all big problems, but, for me, they aren’t the problem. Sure people are losing out on their money – but individually it’s only 99c, it probably costs more for a bag of Haribo. Collectively, though, that is a lot of money. The amount of downloads it takes to get that high in the rankings leads to serious money.

However, the real problem is how the hell did this manage to get approved in the first place?! This is precisely the type of thing Apple’s review process is designed to prevent. Yet here we are, with hundreds (if not thousands) of people buying into false promises, having their money taken from them in dishonest ways. This is exactly what Apple tried to get rid of.

As a developer myself, I have had apps rejected in the past. Some of them have been silly reasons, some have been more sensible, but all of them have been in line with their published Guidelines (requires developer login).

Examples include:

  • Having an app rejected because the table cell selection states were persistent, which contradicts the Human Interface Guidelines.
  • Having an app rejected for using a circular, blue ‘plus’ button as an ‘invite friend button’, when its intended use is for adding existing contacts. (Again, with the HIG).
  • Attempting to sell an in-app purchase that used the name “Premier League” in its title. I was told I needed written consent from the copyright holder in order to use its trademarks. Perfectly fair enough.

So how the hell did this Pokemon Yellow get past these insanely picky reviewers?

The app uses Nintendo trademarks, copyrights and imagery for starters. If it was enough for my “Premier League” IAP to be rejected, why isn’t it enough for this one?

Not only that, the app doesn’t work as advertised. Unless, it says “will immediately close after opening” in the description (which, I couldn’t find at all, so maybe I’m missing it?). Again, this on its own should be enough for rejection.

Finally, the app, even if it did work, offers no substantial benefit or use whatsoever, yet another reason, which by itself should result in rejection.

What the hell Apple? This place is meant to be a haven from all this shit.

The only thing I can think of that would lead to this is an inside job. Maybe one of the reviewers wanted a quick buck and could successfully hide his true identity, like a real super villain. Where’s Batman when you need him?

Today I saw HP’s Z1 all-in-one workstation. A number of people on youtube and twitter are taking issue with the fact HP said “The first 27″ all-in-one” but they’re missing the most important part of the claim to give themselves an excuse to bash HP, and bring into light that Apple has a 27″ all-in-one and has done for a long while.

I’m not usually one to rush to HP’s defences but the part they’re missing is “workstation”. HP said “The first 27″ all-in-one workstation“.

Without that simple word, HP would be outright lying. We all know HP have copied Apple in the past, more recently with the HP Envy and, to some extent, they’re doing it again here with regard to the website’s page layout and the way the videos are presented and directed.

But they’re not lying.

The 27″ iMac, while very powerful, is not a workstation. The HP Z1 has the equivalent of a Mac Pro inside a case that is a similar (though, not as elegant or attractive) form factor as the iMac. It also has the ability to be opened very easily and has a mostly tool-less design that allows fast and easy swapping of the components. However, going off on a tangent here, I suspect that HP will require custom, HP branded components that will fit inside the Z1. And they’ll likely charge a lot more than if you bought the same component for a ‘normal’ system.

Anyway.

I’m going to call it, right now, at 23:00 on Sunday 19th February 2012: Right now would be the perfect time for Apple to discontinue the Mac Pro and announce the iMac Pro.

Think about it. Apple have been neglecting the Mac Pro for some time now, with product refreshes being just that – refreshes. Nothing ground-breakingly new. They’ve already discontinued the Xserve.

Removing the Mac Pro from their product lineup would mark the point where Apple leaves the server market (their current server offerings are Mac Pro’s which, ask any ‘server guy’ don’t really fit in those racks), but it’s becoming increasingly clear that the server market isn’t Apple’s target audience, and I don’t think they want to be there anymore.

I’m not going to make any assumptions on how Apple would create a mythical iMac Pro, but seeing the Z1 makes me think it can be done. Apple took existing consumer desktop computers and created an iMac. Why wouldn’t they be able to take existing workstation computers and create something just as attractive? I mean, if I told you before the Macbook Air came about that you could have a 13″ laptop with a Core i7 CPU and have it still be thinner than any other laptop, would you have believed me?

I’m not saying any kind of iMac Pro would be as customisable as the Z1, I mean, this is still Apple. Even the Mac Pro is only ‘so’ customisable. But still, an iMac with a desktop class GPU just screams “desire” to me. Also, there’s the small stumbling block of the price. I can’t imagine it would be very competitively priced. Again, this is Apple.

So there you have it. I respect HP for doing this. They’ll lead the way for more, better all-in-one workstations. Let’s all remember that Apple is almost never the first to enter a market. They see what others do first, wait for them to fail and do it better themselves.

In short, don’t.

Today, the company I work for had two of it’s clients apps rejected because they stated within the app that a portion of the profits made will be donated to charity.

Apple’s App Store Review Guidelines (requires a developer account login) state the two following points:

21. Charities and contributions

21.1
Apps that include the ability to make donations to recognized charitable organizations must be free
21.2
The collection of donations must be done via a web site in Safari or an SMS

The first point prevents any app that makes donations to charity from being a paid app. Even if the application doesn’t provide an actual means of donating as a feature, the act of donating profits from the sale price counts as an ability to make a donation.

Why would Apple do this, you ask? Are Apple evil? Do they hate charity? No, at least, I don’t think so.

There are some people out there who (for whatever reason) don’t like to or just don’t want to donate to charity. Apple is protecting their right to choose to donate to a given charity while also protecting the rights of people who do want to donate (nothing stops them from donating outside of Apple, for instance). Maybe these people don’t agree with the charity’s ideals or maybe they have some other reason. However, just because someone doesn’t want to donate to a charity doesn’t mean they shouldn’t be able to use your app. The choice of using your app and making a donation shouldn’t be mutually exclusive, and I agree with that.

There is also the question of legal liability – however, I can’t think of a case where that would apply without it also applying to Apple paying developers who don’t make charitable donations… so it seems less likely that this is a reason.

The solution, obviously, is to comply with the guidelines and make the app free while providing a website or SMS based donation feature. However, most companies simply remove the copy that says the profits will be donated – which allows them past the app store approval, but puts them in my “you’re a shady company and I don’t like you” book…

January 5th, 2012

iChat Plugins

No Comments, iPhone, by Jasarien.

A quick tip:

If you’re developing an iChat service plugin with IMServicePlugin and friends, don’t forget to run this from the command line after you install the plugin:

killall imagent

It appears that in order to actually get your plugin to load, imagent needs to be restarted, and restarting iChat itself isn’t quite enough. It doesn’t look like you need admin privileges to kill imagent so ‘sudo’ isn’t necessary. This also makes it easy to do as part of your build process – just add it to a script that runs after your build.

If you don’t do this after you install new service plugins, iChat will see your plugin (and list it in its services list) but won’t actually load the plugin itself.

August 20th, 2011

JSCoreTextHyperlinkView

No Comments, iPhone, by Jasarien.

Since I’ve posted the JSTokenField project, I might as well post about my other open source pride and joy, JSCoreTextHyperlinkView.

The project includes an example of how to use the core text view. It’s pretty simple – create the view with a 0 height frame, set the attributes, set its text, and then ask it for it’s size so that the height is just correct. It will calculate based on the constraining width, and any padding that you set.

There is also a Twitter specific subclass that enables @usernames and #hashtags to be linkified.

Settable Attributes:

- textAlignment
- textColor
- linkColor
- highlightedLinkColor
- fontName
- fontSize
- paddingTop
- paddingLeft
- backgroundImage
- bgImageTopStretchCap
- bgImageLeftStretchCap

To use CoreTextHyperlinkView in your apps:

Copy The contents of the AutoHyperlinks folder, and the files JSCoreTextView.h & .m and, if you want Twitter username and hashtag support, copy JSTwitterCoreTextView.h & .m too.
Link against the CoreText framework.

August 20th, 2011

JSTokenField

No Comments, iPhone, by Jasarien.

I’ve just made my latest iOS open source project available:

JSTokenField

JSTokenField

JSTokenField

It does it’s best to mimic the recipient field in Mail on the iPhone. Tokens will size themselves to fit their titles, rearrange themselves to fit on a line, expand the field as more tokens are added. You can select individual tokens to remove them without having to delete all the ones in front of it. And finally it supports adding entires from the address book.

A token has a title and a represented object. The represented object is simply an ‘id’ so it can be anything you like. Generally I use a string to hold the number, email address, etc.

Enjoy!

August 12th, 2011

Git Shortcuts

No Comments, Source Control, by Jasarien.

Whenever I clone a repo from Github I’m used to being able to use

git pull

and

git push

on their own to pull and push from origin and to master respectively.

When I set up my own git repo outside of Github, I wondered why these didn’t work out of the box. Executing those commands would give me an error saying Git doesn’t know which branch to merge with…

It turns out you can set up your preferred remote and local branches to pull and push to and from. Just edit the config file inside the .git/ directory in your local repo.

You may find that if you added a remote repo previous the [remote] section will already be present.

[branch "master"]
        remote = origin
        merge = refs/heads/master
 
[remote "origin"]
        url = url/to/my/gitrepo.git
        fetch = +refs/heads/*:refs/remotes/origin/*

August 12th, 2011

Deleting Remote Tags With Git

No Comments, Source Control, by Jasarien.

I’ve recently started favouring Git instead of SVN for my newer projects and one of the things I do religiously is tagging.

Tagging in Git is very easy and simple, but I ran into a small problem. I created a tag and named it incorrectly and pushed it to my remote repo before I noticed the mistake. So I deleted the tag and created a new one with the correct name and pushed it. Then I did a pull to ensure I was completely synced with the remote repo and it pulled down my old tag that I just deleted…

It turns out that in order to delete a remote tag you need to do the following (replace ‘MyTag’ with the name you gave your tag):

git tag -d MyTag
git push origin :refs/tags/MyTag

September 26th, 2010

Parsing JSON With SBJSON

No Comments, Cocoa Touch, iPhone, JSON, by Jasarien.

So the previous post focussed on retrieving data from a webservice – namely Google’s Local Search.

This post will focus on parsing the JSON returned from the webservice.

My personal choice for parsing JSON is the SBJON library. There are others out there such as TouchJSON and YAJL so check them put and decide for yourself.

Let’s start with a quick recap on what JSON is and how it can be used.

Wikipedia says:

JSON (an acronym for JavaScript Object Notation) is a lightweight text-based open standard designed for human-readable data interchange. It is derived from the JavaScript programming language for representing simple data structures and associative arrays, called objects. Despite its relationship to JavaScript, it is language-independent, with parsers available for virtually every programming language.

JSON presents its data as key-value pairs. Each value is referenced by a key name, which is a string. If you were to represent a person in JSON, their name would be referenced by the key “name” like so: “name” : “James”.

So, JSON represents data in a way that can be passed between applications easily. Perfect.

So when parsing data from a webservice, the first thing you should do is figure out your model. Look at an example of the webservice’s response and figure out which bits represent objects, arrays of objects, fields that belong to an object, etc.

But what kinds of data can JSON represent?

Objects are everything between the braces ( { } ).
Strings are enclosed in quotes.
Numbers aren’t enclosed by anything and just appear as numbers, e.g. 12345.
Arrays are enclosed in square brackets ( [ ] ).
Booleans take the form of the words ‘true’ or ‘false’ (without quotes).
Null values are represented as ‘null’ (without quotes).

So an example of JSON using all these data types:

{
     "firstName": "John",
     "lastName": "Smith",
     "age": 25,
     "address": 
     {
         "streetAddress": "21 2nd Street",
         "city": "New York",
         "state": "NY",
         "postalCode": "10021"
     },
     "phoneNumber": 
     [
         {
           "type": "home",
           "number": "212 555-1234"
         },
         {
           "type": "fax",
           "number": "646 555-4567"
         }
     ]
 }

And it’s representation in Objective-C:

#import <Foundation/Foundation.h>
 
@interface Person : NSObject
{
    NSString *firstName;
    NSString *lastName;
 
    NSInteger age;
 
    NSDictionary *address;
 
    NSArray *phoneNumbers;
}
 
@end

You may think we’ve missed out some information, such as the details of the address, and phone numbers. It’s you decision how you model your objects. I’ve chosen to store the address details in a dictionary, each value being referenced by a key name, just as it is in JSON. The phone numbers also stored in dictionaries, but then those dictionaries put into an array.

If you wanted to, you could create another Class named Address and use it to store the address details. This may be a more object-oriented approach and useful if addresses are used in other places throughout your application without needing to be tied to a Person.

So now that you have your object model, you need to get the data out of the JSON and create instances of your model.

SBJSON has a useful SBJsonParser class that can parse an entire JSON object in one line:

SBJsonParser *jsonParser = [[SBJsonParser alloc] init];
NSError *error = nil;
NSArray *jsonObjects = [jsonParser objectWithString:jsonString error:&error];
[jsonParser release], jsonParser = nil;

SBJSON treats JSON objects as dictionaries in Objective-C. Depending on the webservice you may get a JSON object as the top level object or you may get an array. For this reason, objectWithString:error: has id as it’s return type. You can use Objective-C’s dynamism to determine which type of data store the parser as returned, like this:

id jsonObject = [jsonParser objectWithString:jsonString error:&error];
 
if ([jsonObject isKindOfClass:[NSDictionary class]])
    // treat as a dictionary, or reassign to a dictionary ivar
else if ([jsonObject isKindOfClass:[NSArray class]])
    // treat as an array or reassign to an array ivar.

If the webservice only ever returns one of the two representations as it’s top level then you can go ahead and assume it will be either an Array or Dictionary, and not have to worry about checking.

Now you have your JSON data in a format that you can manage via Objective-C. All you need to do now is iterate over the contents of the dictionary/array and create instances of Person to represent them.

One thing that’s important to remember is that literal numbers such as the age value in our Person example will be wrapped in NSNumber objects, so we’ll need to call ‘intValue’ on them to get the number.

NSMutableArrary *people = [NSMutableArray array];
 
for (NSDictionary *dict in jsonObjects)
{
    Person *newPerson = [[[Person alloc] init] autorelease];
    [newPerson setFirstName:[dict objectForKey:@"firstName"]];
    [newPerson setLastName:[dict objectForKey:@"lastName"]];
    [newPerson setAge:[[dict objectForKey:@"age"] intValue]];
    [newPerson setAddress:[dict objectForKey:@"address"]];
    [newPerson setPhoneNumbers:[dict objectForKey:@"phoneNumber"]];
 
    [people addObject:newPerson];
}

And there we have it.

One final thing to take note of. You’ll notice that I used literal strings as key names while creating the Person objects. It might be better for you to determine each key name that you’ll be using and create a string constant for them. That way, when you’re parsing your data, if you misspell firstName, the compiler can throw an error (because it won’t match the name of the constant you created) and save you a lot of time debugging when, for some damn reason, you’re not getting any value for @”firtName”!