I’m in Tampa right now, which puts me well outside Rogers’ regular service area. Since I’m roaming, I always do a happy dance when this happens:
This article also appears in The Adventures of Accordion Guy in the 21st Century.
I’m in Tampa right now, which puts me well outside Rogers’ regular service area. Since I’m roaming, I always do a happy dance when this happens:
This article also appears in The Adventures of Accordion Guy in the 21st Century.
Now that iOS 7 has hit the streets, the non-disclosure agreement that all registered iOS developers is no longer under effect. This means that all of us who’ve been playing with the various beta versions of iOS 7 and Xcode 5 can finally talk about them, as well as their APIs, and their experiences developing for Apple’s new-look operating system. Over the next few weeks, I’m going to talk about as many of the changes to Xcode and iOS as I can, as well as point you to other writers who are covering these topics.
Here’s a look at the iOS 7 reading I’m doing these days:
NSHipster bills itself as “a journal of the overlooked bits in Objective-C and Cocoa”, and it does a good job at that. As with Global Nerdy, they’re going to spend the next few weeks covering what’s new for developers in iOS 7. In this week’s installment, NSHipster covers the following:
NSData
Base64 encodingNSURLComponents
– “Think of it as NSMutableURL.”NSProgress
– “…a tough class to describe. It acts as both an observer and a delegate / coordinator, acting as a handle for reporting and monitoring progress.”NSArray::firstObject
– We’ve got NSArray::lastObject, so why not this?CIDetectorSmile
– Detects smiling faces within an imageCIDetectorEyeBlink
– Detects blinking eyes within an imageSSReadingList
– “Even though the number of people who have actually read something saved for later is only marginally greater than the number of people who have ever used a QR code, it’s nice that iOS 7 adds a way to add items to the Safari reading list…”AVCaptureMetaDataOutput
– “Scan UPCs, QR codes, and barcodes of all varieties with AVCaptureMetaDataOutput
, new to iOS 7.”AVSpeechSynthesizer
– “iOS 7 brings the power of Siri with the convenience of a Speak & Spell in a new classAVSpeechSynthesizer..."
MKDistanceFormatter
– “MKDistanceFormatter
provides a way to convert distances into localized strings using either imperial or metric units.”Ray Wenderlich’s site is one of the go-to resources for iOS developer tutorials, from the articles to the books produced by its writers, including their iOS by Tutorials series. They’ve just released the latest in the series, iOS 7 by Tutorials, a PDF book for intermediate and advanced developers that gets updated often and will feature 25 chapters and hundreds of pages of material. This edition covers features such as UIKit Dynamics, Text Kit, background fetch, and the new “flat” design of IOS 7. Highly recommended if you’ve become comfortable with iOS development and want to make the leap past the beginner level.
iOS 7 by Tutorials is available right now for US$54.00.
If you want to get into iOS game development using Apple’s new game framework, Sprite Kit, iOS Games by Tutorials is for you! It’s aimed at developers from all levels, from beginner to advanced.
iOS Games by Tutorials is available right now for $54.00.
One more Ray Wenderlich goodie, and this one’s free! It’s the “iOS 7 Feast”, a series of articles covering some of the new features in iOS 7, including:
If you weren’t able to get to WWDC this year — and that’s most of you, given that it sold out in less time that it takes to order a fast food meal during the lunch rush — you’ve got another shot at seeing some up-close-and-personal iOS developer talks thanks to the iOS 7 Tech Talks, which will take place in the following cities and dates:
The first day in each city is designated “App Developer Day”, while the second is “Game Developer Day”. Presumably due to demand, if you want to attend, you can pick only one — you can’t attend both. Furthermore, each day in each city will be able to accommodate only 400 people, so there’s a lottery. If you’re an interested registered iOS developer (you have to be one to be eligible to attend), you should apply for the city closest to you, choose which day you want to attend, and you’ll have a chance to go. In order to qualify for the lottery, you have to apply by this Friday, September 27th at 10 a.m. PDT (1 p.m. Eastern), so if you want to apply, apply now!
The good news is that Apple will post the videos from the talks on their Developer site. The bad news is that they won;t go online until after the last talk, which takes place in London on December 18th. Think of it not as a delay, but an early Christmas present!
In the meantime, you can always point your browser here at Global Nerdy, because I’ll be posting all sorts of useful iOS 7 developer stuff from various sources.
And now, the agendas for both the App Developer and Game Developer days…
Start the day with valuable recommendations for your iOS 7 development. Get inspired by the powerful new capabilities of iPhone 5s and gain key insights into creating next-generation apps on iOS 7.
iOS 7 sets a new standard for user interface design excellence and offers many opportunities for crafting immersive, delightful, and memorable user experiences. Discover how layering, tinting, Text Kit, motion effects, dynamics, and animation can make your apps more usable, unique, and intuitive.
Learn the patterns that will help you quickly adopt new technologies and ensure that your app is taking full advantage of the latest devices and iOS capabilities. Dive into the details of moving to 64‑bit and see how your apps can tap into the Apple A7 processor.
Grab a quick lunch and dive into the business of marketing your apps on the App Store. Gain a better understanding of how apps get selected and featured on the App Store and key best practices for getting your app to a larger international audience. Learn how to align your marketing efforts and get details about the latest enhancements to iAd and iTunes Connect.
See how technologies like Text Kit, Dynamics, and Auto Layout make it easy to build flexible, modern interfaces. Gain expanded control over your user interface with powerful new animation APIs to enable custom transitions.
New technologies in iOS 7 introduce many exciting opportunities for your apps. Learn to implement capabilities such as background downloading, silent push notifications, and iBeacon support. Gain valuable insights into how to use these cutting edge technologies while still supporting users who haven’t upgraded yet.
Securing your users’ personal and business information has never been more important and honoring your users’ privacy is paramount. Learn the best and latest techniques for app security and privacy and find out exactly how to use the keychain, data protection, secure transport, and identifier APIs most effectively.
With such a wide variety of frameworks and APIs to choose from in Cocoa Touch, it’s easy to miss some of the real gems. From tips for how to get the most out of Xcode 5 to harnessing the power of the Objective-C language to entire classes you might not have thought about using, everybody is sure to take away practical and useful tips and tricks to make developing iOS apps easier and more productive.
Start the day with valuable recommendations for your iOS 7 development. Get inspired by the powerful new capabilities of iPhone 5s and gain key insights into creating next-generation games on iOS 7.
OpenGL ES provides access to the exceptional graphics power of the Apple A7. See how the innovations in OpenGL ES 3.0 deliver incredible graphics in games and other mobile 3D apps. Learn about advanced effects enabled by the latest API enhancements, and get specific tips and best practices to follow in your apps.
Learn the patterns that can help you quickly adopt new technologies and keep your games on the cutting edge. Understand how to use powerful constructs from UIKit to make your game feel at home on iOS. Dive into the details of moving to 64‑bit and see how your games can tap into the Apple A7 processor.
Grab a quick lunch and then dive into the business of marketing your apps on the App Store. Gain a better understanding of how apps get selected and featured on the App Store and key best practices for getting your app to a larger international audience. Learn to how to align your marketing efforts and get details about the latest enhancements to iAd and iTunes Connect.
Sprite Kit is a powerful graphics framework ready-made for developing 2D action games, platformers, puzzle games, and much more. Dive into the practical workflow of developing a 2D game and learn key details about the Sprite Kit API. Discover how to leverage built-in physics support to make animations look real, and learn about using particle systems to create essential game effects such as fire, snow, explosions, and smoke.
Join us for a deep dive into new technologies in iOS 7 that can enable you to reduce your app’s bundle size, keep your apps in communication with your server, prevent game score tampering, and more. Gain valuable insights into best practices for building networked games. And protect your reputation by following best practices for security and privacy. Learn how to use these cutting edge iOS 7 technologies while still supporting users who haven’t yet upgraded.
Tap into essential technologies to enhance the gameplay experience. Discover new techniques for managing players and tracking scores through Game Center, and get expert advice about the best practices to follow in your titles. Learn about the Game Controller framework and see how to take advantage of exciting new modes of input by adding support for physical game controllers.
Truly outstanding iOS games go beyond addictive gameplay and beautiful graphics by presenting players with interfaces that are thoughtfully designed and carefully implemented. Receive practical advice about UI design and platform conventions that will make your game even more enjoyable.
…wish me luck!
Here’s Funny or Die’s Mac Story, which features Apple products in place of Toy Story’s toys, the iPhone 5S playing the part of Buzz Lightyear, and a special guest appearance from a Microsoft product:
And therein lies the perception hurdle that Apple faces: the fact that most of the improvements in the iPhone 5S are under the hood rather than clearly visible (and often “novelty”) changes, most notably the 64-bit A7 processor, which benchmarks beautifully:
I know, I know, it’s been over a fortnight since I last post a tutorial. Things have been a little bit crazy at work, but I plan to hope to use the next couple of days to get caught up, and then post a new tutorial next week.
In the last installment, I posted another installment of my iOS development tutorial series, iOS Fortnightly: SimpleWeather, a simple weather app that made use of the AFNetworking library to fetch the current weather conditions for any given city from Open Weather Map. If you’d followed the tutorial to the end, you’d have an app that looks like this when immediately after you launch it:
…and here’s what it looks like when displaying the current weather:
It’s nowhere near ready for the App Store, but in a few lines of code, it accomplishes a fair bit. If you’re new to Objective-C, it also covers some unfamiliar territory. This week’s set of articles will expand on the Simple Weather app. In this one, I’ll explain those parts of the code that might not be familiar to the novice iOS developer, namely Objective-C’s blocks and properties.
The meat of the SimpleWeather app is in the
Weather
class’ getCurrent:
method. It makes the call to Open Weather Map’s API, and it does so with this line:
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:weatherRequest success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { weatherServiceResponse = (NSDictionary *)JSON; [self parseWeatherServiceResponse]; } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { weatherServiceResponse = @{}; } ];
AFJSONRequestOperation
is a class in the AFNetworking library for requesting and retrieving JSON data from a given URL. It has a single method, a class method called JSONRequestOperationWithRequest:success:failure:
. Here’s what its declaration looks like:
+ (AFJSONRequestOperation *)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest success:(void ( ^ ) ( NSURLRequest *request, NSURLResponse *response, id JSON ))success failure:(void ( ^ ) ( NSURLRequest *request, NSURLResponse *response, NSError *error , id JSON ))failure
JSONRequestOperationWithRequest:success:failure:
is a method that makes a request for some JSON from a given URL and:
Here are the method’s parameters:
Parameter Name | Description |
---|---|
urlRequest |
A NSURLRequest object representing our request for the current weather from Open Weather Map. |
success |
A function that should be executed if the operation was a success, meaning that the requested JSON object was successfully retrieved. |
failure |
A function that should be executed if the operation was a failure. This could mean that requested JSON object was not successfully retrieved, or that it was successfully retrieved, but couldn’t be parsed as JSON. |
The urlRequest
argument is pretty straightforward, but the success and failure arguments look more complicated. They’re block literals, and to talk about them, we need to talk about blocks.
If you’re reasonably well-versed in JavaScript, it’s quite likely that you’re familiar with anonymous functions. Here’s a quick and dirty example: an anonymous function that takes two numbers and returns their sum, stored inside a variable named doSomething
:
var doSomething = function(firstNumber, secondNumber) { return firstNumber + secondNumber; } alert(doSomething(2, 3));
In Ruby, there are a couple of types of anonymous functions: procs and blocks. Procs are the anonymous function type that you can bind to a local variable, which is close to the spirit of anonymous functions in JavaScript and Objective-C. Here’s the Ruby version of the anonymous function from the example above:
doSomething = Proc.new {|firstNumber, secondNumber| firstNumber + secondNumber} puts doSomething.call(2, 3)
And now, the Objective-C version:
int(^doSomething)(int, int) = ^(int firstNumber, int secondNumber) { return firstNumber + secondNumber; }; NSLog(@"%d", doSomething(2, 3));
It’s not all that different from the JavaScript and Ruby versions; it’s just that Objective-C requires explicit type information. Let’s take a look at the left side of the assignment first:
int(^doSomething)(int, int)
Here’s where cdecl comes in handy. It’s a site that translates declarations and casts from “C gibberish to English” and vice versa, comes in quite handy.
Enter int(^doSomething)(int, int)
into cdecl. cdecl will translate it as “declare doSomething
as block (int, int)
returning int
“. This in turn can be interpreted as “doSomething
is a variable containing an anonymous function that takes two int
s and returns an int
“.
Now let’s look at the right side of the assignment:
^(int firstNumber, int secondNumber) { return firstNumber + secondNumber; };
With the exception of the ^
character in front of the parameters, it looks like a like a standard function definition.
JSONRequestOperationWithRequest
‘s Block Parameters, success
and failure
Let’s look at JSONRequestOperationWithRequest
‘s success
parameter, which expects a block that should be executed if the JSON request operation is a success. Here’s its type:
(void ( ^ ) ( NSURLRequest *request, NSURLResponse *response, id JSON ))
This means that it expects a function that expects three parameters of type NSURLRequest *
, NSURLResponse *
, and id
, and doesn’t return anything. Here’s what we’ll pass to it:
^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { weatherServiceResponse = (NSDictionary *)JSON; [self parseWeatherServiceResponse]; }
It does two things:
NSDictionary *
, and stores it in the instance variable (or, as they like to say in Objective-C, ivar) weatherServiceResponse
. Note that the block “knows” about weatherServiceResponse
parseWeatherServiceResponse
, which extracts the data from the JSON retrieved from Open Weather Map and puts them into the instance variables behind the class’ properties.Let’s now look at JSONRequestOperationWithRequest
‘s failure
parameter, which expects a block that should be executed if the JSON request operation is a failure. Here’s its type:
(void ( ^ ) ( NSURLRequest *request, NSURLResponse *response, NSError *error , id JSON ))
This means that it expects a function that expects four parameters of type NSURLRequest *
, NSURLResponse *
, NSError *
and id
, and doesn’t return anything. Here’s what we’ll pass to it:
^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { weatherServiceResponse = @{}; }
Right now, we’re not worrying about what to do in the event of a failure, so for the moment, the failure
block simply sets weatherServiceResponse
to be an empty dictionary.
Consider the first line in the parseWeatherServiceResponse
method:
_cloudCover = [weatherServiceResponse[@"clouds"][@"all"] integerValue];
If you look around the class, you’ll find that the variable _cloudCover
hasn’t been declared anywhere. Yet Xcode hasn’t thrown up any error messages, and it colour-codes it as it would any declared variable. What’s going on here?
It turns out that there’s a little behind-the-scenes magic that takes place whenever a @property
is declared. If you look in Weather.h, you’ll see this declaration:
@property (nonatomic, readonly) NSInteger cloudCover;
Implicit in this declaration is this corresponding line in the class’ .m file:
@synthesize cloudCover = _cloudCover;
This line doesn’t actually appear in the .m file, but it’s effectively there thanks to a little compiler magic. @synthesize
itself does its own magic; it creates an invisible corresponding instance variable and invisible “getter” and “setter” methods. Implicit in the line above is this instance variable declaration:
NSInteger _cloudCover;
and these methods:
- (NSInteger)cloudCover { return _cloudCover; } - (void)setCloudCover:(BOOL)newValue { _cloudCover = newValue; }
Speaking of properties and ivars, take a look at the order of the ivars in parseWeatherServiceResponse
, which lives in Weather.m:
- (void)parseWeatherServiceResponse { // clouds _cloudCover = [weatherServiceResponse[@"clouds"][@"all"] integerValue]; // coord _latitude = [weatherServiceResponse[@"coord"][@"lat"] doubleValue]; _longitude = [weatherServiceResponse[@"coord"][@"lon"] doubleValue]; // dt _reportTime = [NSDate dateWithTimeIntervalSince1970:[weatherServiceResponse[@"dt"] doubleValue]]; // main _humidity = [weatherServiceResponse[@"main"][@"humidity"] integerValue]; _pressure = [weatherServiceResponse[@"main"][@"pressure"] integerValue]; _tempCurrent = [Weather kelvinToCelsius:[weatherServiceResponse[@"main"][@"temp"] doubleValue]]; _tempMin = [Weather kelvinToCelsius:[weatherServiceResponse[@"main"][@"temp_min"] doubleValue]]; _tempMax = [Weather kelvinToCelsius:[weatherServiceResponse[@"main"][@"temp_max"] doubleValue]]; // name _city = weatherServiceResponse[@"name"]; // rain _rain3hours = [weatherServiceResponse[@"rain"][@"3h"] integerValue]; // snow _snow3hours = [weatherServiceResponse[@"snow"][@"3h"] integerValue]; // sys _country = weatherServiceResponse[@"sys"][@"country"]; _sunrise = [NSDate dateWithTimeIntervalSince1970:[weatherServiceResponse[@"sys"][@"sunrise"] doubleValue]]; _sunset = [NSDate dateWithTimeIntervalSince1970:[weatherServiceResponse[@"sys"][@"sunset"] doubleValue]]; // weather _conditions = weatherServiceResponse[@"weather"]; // wind _windDirection = [weatherServiceResponse[@"wind"][@"dir"] integerValue]; _windSpeed = [weatherServiceResponse[@"wind"][@"speed"] doubleValue]; }
In this method, I’m extracting data from the JSON objects returned by Open Weather Map, so they’re ordered from that perspective: by the keys of the top-level dictionaries in alphabetical order: clouds
, coord
, dt
, main
, name
, rain
, snow
, sys
, weather
, wind
. Those dictionaries’ elements are also listed in alphabetical order by key. The idea is to make things easy to find when programming with Open Weather Map’s API in mind.
The order of the corresponding @properties
exposed in Weather.h is different. Here, I also want things to be easy to find, but I also want to abstract away any details about the format in which Open Weather Map returns its info. Instead, I want an order that’s useful for when you just want the weather, so I’ve used comments to break the properties into three groups: place and time, qualitative, and quantitative.
// Properties // ========== // Place and time @property (nonatomic, copy, readonly) NSString *city; @property (nonatomic, copy, readonly) NSString *country; @property (nonatomic, readonly) CGFloat latitude; @property (nonatomic, readonly) CGFloat longitude; @property (nonatomic, copy, readonly) NSDate *reportTime; @property (nonatomic, copy, readonly) NSDate *sunrise; @property (nonatomic, copy, readonly) NSDate *sunset; // Qualitative @property (nonatomic, copy, readonly) NSArray *conditions; // Quantitative @property (nonatomic, readonly) NSInteger cloudCover; @property (nonatomic, readonly) NSInteger humidity; @property (nonatomic, readonly) NSInteger pressure; @property (nonatomic, readonly) NSInteger rain3hours; @property (nonatomic, readonly) NSInteger snow3hours; @property (nonatomic, readonly) CGFloat tempCurrent; @property (nonatomic, readonly) CGFloat tempMin; @property (nonatomic, readonly) CGFloat tempMax; @property (nonatomic, readonly) NSInteger windDirection; @property (nonatomic, readonly) CGFloat windSpeed;
As with the ordering in parseWeatherServiceResponse
, the objective is to make things easy to read and find, but this time, I’m doing so not from the perspective of a programmer trying to get data from the Open Weather Map API, but a programmer trying to get data from an instance of the Weather
class.
In case you missed them, here’s a list of the previous articles in this series:
My article from April 30th, Delusional CEO of Company Scrambling for Distant Third Place Says They’ll Be the “Absolute Leader” in Five Years, has been getting crazy hits since yesterday morning, thanks to its money quote:
“In five years, I see BlackBerry to be the absolute leader in mobile computing — that’s what we’re aiming for.”
Of course, we all had to keep in mind that as CEO, Heins’ job is to play the part of the cheerleader, boost confidence in his company and not say things like “O-M-G, we’re so dead.”
However, industry pundits have a different job: to read the tea leaves and call ’em as they see ’em. Here are some notable predictions that I saved in my bookmarks for a later date…
On The Street on March 21, 2012, Jim “Mad Money / Bear Stearns is fine” Cramer, said that although RIM’s share price was dropping at the time, that it was the right time to buy:
A mere eight days later — March 29, 2012 — he’s singing a slightly different tune: “Things have passed [RIM] by, just the way Nokia got passed by”:
Why I Think RIM Will Succeed…The QNX Powered Comeback, published in BerryReview on September 12th, 2011, includes these gems:
10 Solid Reasons RIM Will Make a Comeback roots for the home team, which I can get behind. For the longest time, RIM was a source of Canadian pride, and one of the examples I’d cite in a speech I’d open with “Since Alexander Graham Bell, Canada has always punched above its weight class in communications technologies.”
However, when I first read this article, it lost me at its first reason for a RIM comeback: “Developers believe in BB10”. It turns out that these were developers working for RIM: “I personally know several developers who are still working for RIM and who are not the least bit interested in jumping ship.” That’s because you don’t jump ship before something you’ve worked on ships; you do it afterwards. Otherwise, you don’t have as good an answer when interviewing at your next gig and the “So what was the last project you worked on?” question comes up.
The rationale in the article RIM Could Rise on Wings of BlackBerry 10: Pro comes from delusional National Bank analyst Kris Thompson: “”We don’t want to bet against the dollars flowing to the stock,” and “They have 80 million subscribers today. A lot of us are very loyal. Think about the business users that like to generate a lot of emails during the day: it’s very difficult to do that on a lot of the competing platforms with a virtual keyboard.”
He does emphasize that the investments that were leading to a rising stock price — one that he predicted could go as high as $20 (it did hit $17.90 on January 22nd) — are “speculative” and not based on “fundamentals”.
Rob Enderle, the analyst whom Dell hired to help them with their efforts in taking on Apple with making an MP3 player and getting into music — an effort even more forgotten than Microsoft’s Zune — bet on the wrong horse again when he explained Why 2013 is RIM’s BlackBerry Year. His wrongness is best summed up in the second-last paragraph of the article:
I’ve had some time to talk to RIM about its upcoming platform, and it appears to address each one of these shortcomings with a vengeance. BlackBerry 10 is based on an OS that is used to operate machinery. RIM started with a business oriented core and then addressed consumer needs—as opposed to the more common approach of putting a business façade over a device that was targeted first at consumers.
Of course, the PC industry in which Rob plays (and often gets so, so wrong) got started by going consumer-first, then adding the business stuff later. They were either hobbyist machines like the Apple II and TRS-80, and even the original IBM PC was created by the dismissively-named “Entry Level Systems Division”, which hinted that it was something to tide you over until you got a big-boy computer like one of their mainframes or minis.