Thursday, July 2, 2009
Don't call me an Objectivist...
...but I speak a new language now.
Well, sorta. I write to you on my shiny new MacBook, which I purchased in part because you can't write iPhone applications on non-Macs. I guess I don't resent that. Much. It is a nice machine, although I'm still getting used to all of OS X's quirks.
But never mind the OS: writing an iPhone version of my app means mastering the iPhone SDK and a whole new language, Objective-C. Which was kind of frustrating for a week. Imagine, for a moment, that you're a car mechanic. Now imagine that you move to a new garage, where the cars are totally different, not just the engines but even the doors and the dashboard controls are laid out in some bizarre new arrangement, and instead of your old tools, there's a wall full of all these curvy New Age things that look more like vacuum cleaner parts and art objects than hex wrenches and hammers. That's kind of what diving into the iPhone SDK was like.
But. You are a car mechanic. And ultimately, we're still talking about wheeled vehicles powered by internal combustion engines; so after a bewildering week, during which you often don't even know what questions to ask, you begin to realize that in fact these cars are quite elegantly if counterintuitively designed, and that these tools are well suited to them.
Yeah, so the metaphor got out of hand, sue me. Anyway, I didn't know Objective-C, but I've been writing software professionally for nigh on twenty years now, and it's kind of a weird mixture of C and Smalltalk, both of which I have worked with before. It turns out that it is a powerful and flexible language, and the iPhone SDK's tools and libraries do indeed ultimately make sense.
Don't get me wrong. There are still things I hate. Mostly the hangovers from C. Just like C, object you create requires two files: one where all the code goes, and a "header file" that describes the code. It was a bad idea then, and it's a bad idea now, which is why no modern languages require it. The resulting profusion of files is messy, annoying, completely unnecessary, and provides more places for things to go wrong.
Also, you have to allocate memory by hand, and then be extremely careful to de-allocate it, lest you leak memory and consume all your phone's resources. I shake my head with bewildered contempt. Manual memory management is archaic, clumsy, tedious, and perpetually prone to disaster. Making it part of the iPhone SDK is like having a beautifully renovated marble-and-gold bathroom built atop lead plumbing.
(My understanding is that if you're writing for Macs, you can have automatic garbage collection, like the rest of the civilized world, but such is strongly discouraged on the iPhone. Scarce resources, apparently. But I note that Java development for similarly specced Android phones, with garbage collection - and sans useless header files - works just fine...)
I have also learned that there are subtle pitfalls in the Objective-C environment. I'll concede that this can be true of Java as well, though usually that's when you're dealing with classpaths, less of an issue when doing Android development. But, well, see for yourself. Here's what looks like a garden-variety call to a Settings class:
which should call the "getSearchPageURL" class method on my "Settings" class, which right now is pretty much just a bundle of constants. Here's a simplified Settings.h:
and Settings.m:
Nothing to it, right? Compiled just fine. Did it run? Did it hell. Instead I got
OK, points for the amusing "trouble ahead" warning, but what the hell? I'm just calling a very simple function that does nothing but return a hardcoded string - so what could possibly have gone wrong?
Turns out that function automatically gets abstracted up at runtime into a selector - and for that to work, Settings must extend NSObject. Which is trivially done, of course, but far from intuitive.
Wacko problem number 2: I changed a variable from an NSArray to an NSDictionary, and reworked the code appropriately - no big deal - and suddenly the app was dying with an EXC_BAD_ACCESS call, meaning that I was trying to release the memory of an object I had already released. Muttering foul imprecations about the whole notion of manual garbage collection, I went carefully through my code and found ... nothing. So I Googled. (Which is how I ultimately solved the previous problem, too; but in both cases I had to go well past the first page of results, which is one reason I'm writing this with copious details. Maybe future sufferers will find their way to this post.)
Here are the relevant parts of the header file:
and it turns out that the problematic line in the implementation was this one:
Looks harmless enough, doesn't it? Both urlSuffixes and pageNames are perfectly acceptable NSArrays of NSStrings. So what's the problem?
Well, if you're not familiar with Objective-C, you might be a little gobsmacked to learn that the solution was to change the above line to
Yes, really.
As far as I can tell, the difference is that in the second example, instead of the instance variable being directly modified, the @synthesized auto-generated setter is called, with "retain" as dictated in the @property definition, which prevents the NSDictionary from being released when we exit the method which generates it. Perhaps some people think of this stuff as intuitive. Not me. It's all fixed and working now, but this kind of man-behind-the-curtain stuff makes me a little uneasy.
That said, there's a lot to like. The user-interface stuff, once you figure it out, is (mostly) a joy to work with. You can lay out items visually or programmatically; you get a built-in navigation header and button toolbar, yours for just a few lines of code; it's easy to reach out via HTTP, with a one-line synchronous-call version, a delegated version with fine control, or a compromise somewhere between; and as of the 3.0 SDK, instead of hand-writing SQL code to access SQLite, you can use Apple's Core Data engine to manage all your persistent data. (Which comes with its own problems but overall is definitely more elegant and more powerful.)
Also, while I wouldn't say that I'm fluent in Objective-C yet, I'm now conversant, and I like it a lot when it's reminding me of Smalltalk, and not reminding me of C. You do, however, seem to wind up writing a lot more lines of code than you would in Java to do the same thing. It's like speaking German vs. English.
Overall, though, qualified thumbs up. I still prefer Java to Objective-C, and there are still things that Android can do and the iPhone can't - multitasking is the biggest, and the associated inter-app communication possibilities - while I can't think of any examples of the converse. But I am increasingly a fan of the latter's SDK. What at first looked a bit like a junkyard is now becoming more of a playground.
Well, sorta. I write to you on my shiny new MacBook, which I purchased in part because you can't write iPhone applications on non-Macs. I guess I don't resent that. Much. It is a nice machine, although I'm still getting used to all of OS X's quirks.
But never mind the OS: writing an iPhone version of my app means mastering the iPhone SDK and a whole new language, Objective-C. Which was kind of frustrating for a week. Imagine, for a moment, that you're a car mechanic. Now imagine that you move to a new garage, where the cars are totally different, not just the engines but even the doors and the dashboard controls are laid out in some bizarre new arrangement, and instead of your old tools, there's a wall full of all these curvy New Age things that look more like vacuum cleaner parts and art objects than hex wrenches and hammers. That's kind of what diving into the iPhone SDK was like.
But. You are a car mechanic. And ultimately, we're still talking about wheeled vehicles powered by internal combustion engines; so after a bewildering week, during which you often don't even know what questions to ask, you begin to realize that in fact these cars are quite elegantly if counterintuitively designed, and that these tools are well suited to them.
Yeah, so the metaphor got out of hand, sue me. Anyway, I didn't know Objective-C, but I've been writing software professionally for nigh on twenty years now, and it's kind of a weird mixture of C and Smalltalk, both of which I have worked with before. It turns out that it is a powerful and flexible language, and the iPhone SDK's tools and libraries do indeed ultimately make sense.
Don't get me wrong. There are still things I hate. Mostly the hangovers from C. Just like C, object you create requires two files: one where all the code goes, and a "header file" that describes the code. It was a bad idea then, and it's a bad idea now, which is why no modern languages require it. The resulting profusion of files is messy, annoying, completely unnecessary, and provides more places for things to go wrong.
Also, you have to allocate memory by hand, and then be extremely careful to de-allocate it, lest you leak memory and consume all your phone's resources. I shake my head with bewildered contempt. Manual memory management is archaic, clumsy, tedious, and perpetually prone to disaster. Making it part of the iPhone SDK is like having a beautifully renovated marble-and-gold bathroom built atop lead plumbing.
(My understanding is that if you're writing for Macs, you can have automatic garbage collection, like the rest of the civilized world, but such is strongly discouraged on the iPhone. Scarce resources, apparently. But I note that Java development for similarly specced Android phones, with garbage collection - and sans useless header files - works just fine...)
I have also learned that there are subtle pitfalls in the Objective-C environment. I'll concede that this can be true of Java as well, though usually that's when you're dealing with classpaths, less of an issue when doing Android development. But, well, see for yourself. Here's what looks like a garden-variety call to a Settings class:
NSMutableString *urlString = [NSMutableString stringWithCapacity:128];
[urlString appendString:[Settings getSearchPageURL]];
which should call the "getSearchPageURL" class method on my "Settings" class, which right now is pretty much just a bundle of constants. Here's a simplified Settings.h:
#import <UIKit/UIKit.h>
@interface Settings {
}
+(NSString *) getSearchPageURL;
and Settings.m:
+(NSString *)getSearchPageURL
{
return @"http://wetravelwrite.appspot.com/mb/searchForPage";
}
Nothing to it, right? Compiled just fine. Did it run? Did it hell. Instead I got
2009-07-02 22:48:28.519 iTravelWrite[17002:20b] *** NSInvocation: warning: object 0xaa40 of class 'Settings' does not implement methodSignatureForSelector: -- trouble ahead
2009-07-02 22:48:28.520 iTravelWrite[17002:20b] *** NSInvocation: warning: object 0xaa40 of class 'Settings' does not implement doesNotRecognizeSelector: -- abort
OK, points for the amusing "trouble ahead" warning, but what the hell? I'm just calling a very simple function that does nothing but return a hardcoded string - so what could possibly have gone wrong?
Turns out that function automatically gets abstracted up at runtime into a selector - and for that to work, Settings must extend NSObject. Which is trivially done, of course, but far from intuitive.
Wacko problem number 2: I changed a variable from an NSArray to an NSDictionary, and reworked the code appropriately - no big deal - and suddenly the app was dying with an EXC_BAD_ACCESS call, meaning that I was trying to release the memory of an object I had already released. Muttering foul imprecations about the whole notion of manual garbage collection, I went carefully through my code and found ... nothing. So I Googled. (Which is how I ultimately solved the previous problem, too; but in both cases I had to go well past the first page of results, which is one reason I'm writing this with copious details. Maybe future sufferers will find their way to this post.)
Here are the relevant parts of the header file:
@interface SearchController : UITableViewController{
NSDictionary *searchResults;
}
@property (nonatomic, retain) NSDictionary *searchResults;
and it turns out that the problematic line in the implementation was this one:
searchResults = [NSDictionary dictionaryWithObjects: urlSuffixes forKeys: pageNames];
Looks harmless enough, doesn't it? Both urlSuffixes and pageNames are perfectly acceptable NSArrays of NSStrings. So what's the problem?
Well, if you're not familiar with Objective-C, you might be a little gobsmacked to learn that the solution was to change the above line to
self.searchResults = [NSDictionary dictionaryWithObjects: urlSuffixes forKeys: pageNames];
Yes, really.
As far as I can tell, the difference is that in the second example, instead of the instance variable being directly modified, the @synthesized auto-generated setter is called, with "retain" as dictated in the @property definition, which prevents the NSDictionary from being released when we exit the method which generates it. Perhaps some people think of this stuff as intuitive. Not me. It's all fixed and working now, but this kind of man-behind-the-curtain stuff makes me a little uneasy.
That said, there's a lot to like. The user-interface stuff, once you figure it out, is (mostly) a joy to work with. You can lay out items visually or programmatically; you get a built-in navigation header and button toolbar, yours for just a few lines of code; it's easy to reach out via HTTP, with a one-line synchronous-call version, a delegated version with fine control, or a compromise somewhere between; and as of the 3.0 SDK, instead of hand-writing SQL code to access SQLite, you can use Apple's Core Data engine to manage all your persistent data. (Which comes with its own problems but overall is definitely more elegant and more powerful.)
Also, while I wouldn't say that I'm fluent in Objective-C yet, I'm now conversant, and I like it a lot when it's reminding me of Smalltalk, and not reminding me of C. You do, however, seem to wind up writing a lot more lines of code than you would in Java to do the same thing. It's like speaking German vs. English.
Overall, though, qualified thumbs up. I still prefer Java to Objective-C, and there are still things that Android can do and the iPhone can't - multitasking is the biggest, and the associated inter-app communication possibilities - while I can't think of any examples of the converse. But I am increasingly a fan of the latter's SDK. What at first looked a bit like a junkyard is now becoming more of a playground.
Labels: Apple, doesNotRecognizeSelector, EXC_BAD_ACCESS, iPhone, Objective-C, SDK
Comments:
Thanks for sharing this informative content.,
Leanpitch provides online training in Scrum Master Certification during this lockdown period everyone can use it wisely.
Join Leanpitch 2 Days CSM Certification Workshop in different cities.
CSM online training
CSM training online
<< Home
Thanks for sharing this informative content.,
Leanpitch provides online training in Scrum Master Certification during this lockdown period everyone can use it wisely.
Join Leanpitch 2 Days CSM Certification Workshop in different cities.
CSM online training
CSM training online
Thanks for sharing this informative content.,
Leanpitch provides online training in Agile team facilitation during this lockdown period everyone can use it wisely.
Agile team facilitation
ICP ATF
Team facilitator Agile
Agile facilitator
Team facilitator in Agile
ICAGILE ATF
Leanpitch provides online training in Agile team facilitation during this lockdown period everyone can use it wisely.
Agile team facilitation
ICP ATF
Team facilitator Agile
Agile facilitator
Team facilitator in Agile
ICAGILE ATF
You are providing very good knowledge. It is essential and important information for us and everyone to increase knowledge. Continue sharing your data. Thank you once again. AMGO OH-10
I want to say thanks for beautiful blog sharing with us. Your blog really great resource to update my knowledge 야한동영상
Also feel free to visit may webpage check this link
야설
Also feel free to visit may webpage check this link
야설
This is a smart blog. I mean it. You have so much knowledge about this issue, and so much passion. You also know how to make people rally behind it, obviously from the responses. 한국야동닷컴
Also feel free to visit may webpage check this link
국산야동
Also feel free to visit may webpage check this link
국산야동
Very good blog post about plastering a one bed flat. I am very happy to see this post and interested to find another good post in coming days. Thanks for it 국산야동
Also feel free to visit may webpage check this link
야설
Also feel free to visit may webpage check this link
야설
I feel very grateful that I read this. It is very helpful and very informative and I really learned a lot from it 중국야동넷
Also feel free to visit may webpage check this link
야설
Also feel free to visit may webpage check this link
야설
Embark on a thought-provoking journey through the complex landscape of philosophy and individualism with our latest blog, "Don't Call Me an Objectivist." Join us as we navigate the nuances of Ayn Rand's Objectivism and delve into the perspectives of those who identify with or challenge this school of thought.
lawyers in virginia for reckless driving
lawyers in virginia for reckless driving
Subscribe to Post Comments [Atom]
<< Home
Subscribe to Posts [Atom]
Post a Comment