Showing posts with label ObjC. Show all posts
Showing posts with label ObjC. Show all posts

Tuesday, September 22, 2009

Quicktime X A/V Controls

I've been (very slowly) working my way through Stanford's CS193P iPhone development course available on iTunes U.

iTunes is a pretty good client for watching the lectures. It keeps track of where you were and if you're like me and your lecture viewing is frequently interrupted (i.e., kids), that can be a pretty useful feature.

But one of the things that it won't do is allow you to speed up the playback (at least I don't think it will). So when the instructors are talking about due dates, late assignments, and other housekeeping that doesn't really apply to you, it can be frustrating to watch through it in realtime. So if you can live without iTunes' ability to track progress, simply go find the movie on your hard drive (right click and select "Show in Finder") and open it up in QuickTime Player.

In Leopard open the "A/V Controls" window in QuickTime 7 and set the playback speed (up to 3x). After installing Snow Leopard I was sad to see that the A/V Controls window was missing from QuickTime X so I assumed you had to use the optional QuickTime 7 installation. But tonight I tried option clicking the fast forward button in the QuickTime X Player and discovered that instead of increasing the playback speed to 2x, 4x, or 8x when you repeatedly click the button, it incrementally increases the playback speed by 0.1x up to a maximum of 8x!

So there you go. Save some time and learn some iPhone development too.

Sunday, March 09, 2008

The iPhone SDK

I don't own an iPhone and since I'm in Canada I can't even buy an iPhone from Apple even if I wanted to, but that hasn't tempered my enthusiasm for the new iPhone SDK.  Like so many thousands of others I downloaded the SDK as soon it was available, installed it, and then started coding away.  I'm sure more experienced Cocoa developers were able to quickly bang out something cool, but not me.  It took me a bit longer to get the mandatory "Hello World" running, but nonetheless, my previous Objective-C/Cocoa investigations definitely came in handy.  I think one of my mistakes was thinking that the videos Apple put up would help me.  IMHO, don't bother.  Go right for the developer documentation in XCode instead.

Alas, I can't really say that much about the SDK.  I clicked through one of those license agreements and I'm sure that there's something in there that forbids me from revealing anything too juicy.  But I think it suffices to say that I'm still enthusiastic about where this is going.  I think the iPhone (even though I don't have one yet) is a great bit of technology and once in the hands of people in the enterprise who suffer at the other craptaculous mobile devices out there, they'll definitely start demanding stuff.  And that's where I fit in.  I'm excited to see how this all evolves and hope I'm ahead of the curve at least momentarily. ;-)

Saturday, November 03, 2007

Ruby Cocoa

RubyCocoa and the Scripting Bridge are two software development technologies bundled with Leopard. The app presented here demonstrate how to create a native Mac interface written in Ruby that communicates with iTunes via Applescript. It does nothing more than display the iTunes version number.
  1. Create a "Ruby-Cocoa Application" from the "New Project" dialog in XCode
  2. Add a "Ruby NSObject subclass" to the project called "ITunesController"
  3. Add an ib_outlet for a text field and an ib_action called "show_version" to the ITunesController ruby class.
  4. Generate an Objective-C header file that scripting bridge can use to communicate with iTunes. Use the two terminal command, sdef and sdp, within your project folder like this: "sdef /Applications/iTunes.app | sdp -fh --basename iTunes"
  5. Add the header file to your project.
  6. Add "ScriptingBridge.framework" to your project.
  7. Open "MainMenu.nib" in Interface Builder and add a button and a label to the Window. Also instantiate an NSObject subclass.
  8. Set the NSObject's class to "ITunesController". (You may need to select the "Read Class Files..." menu item to get ITunesController to show up as a valid option)
  9. Wire the button to your controller's "show_version" method and wire the controller's text_field outlet to the label.

Here's what my project looks like:


Here's what my Ruby "ITunesController" class looks like:

require 'osx/cocoa'

include OSX
class ITunesController < NSObject
ib_outlet :text_field
def show_version(sender)
iTunes = SBApplication.applicationWithBundleIdentifier:'com.apple.iTunes'
@text_field.setStringValue("iTunes version: #{iTunes.version}")
end
ib_action :show_version
end

Here's what the app looks like:


Now you should be able to run the project and get the iTunes version number displayed in your own application. Yeah, the end result is kind of lame but the journey was pretty cool. The interesting bits for me were:
  1. My Ruby class extends Cocoa's NSObject class.
  2. The class methods ib_outlet and ib_action are parts of the Ruby DSL for doing Cocoa development with Ruby.
  3. The RubyCocoa framework makes it really simple to swap out Objective-C for Ruby when doing Cocoa development.
  4. Everything else is the same. I still use XCode for my controllers and model and still use Interface Builder to graphically build my GUI and bind it to my code. The only difference is that I get to use Ruby and all of its beauty to get the job done.
  5. The downside is that I don't get anything too useful in the way of code completion while in XCode. Still might be worth it if you really dig Ruby.

Tuesday, April 03, 2007

Objective-C 2.0

Being a bit of a Mac-head and programmer to boot I've taken various looks at writing native Mac OS X apps withe XCode (the IDE), Cocoa (the frameworks), and Objective-C (the language). In general I've come away relatively happy with the toolset. But I must admit, I've filed my own share of enhancement requests with Apple. The top of my list was refactoring support in the IDE. I know it probably sounds lame to the hard core coders but after developing with Java for so long I just expect it and perhaps more embarassingly I feel I need it. Global regex search and replace just doesn't cut it. Secondly, I dislike all the boiler-plate "noise" that appears in your code to declare properties (instance var & accessor/mutator methods) and all the manual memory management.

Well Apple's been looking around at the competition and listening to feedback and judging by their website (here and here) and a few message boards (like this one), Apple has a lot in store for developers. Objective-C 2.0 sports Garbage Collection for the first time, some syntactical sugar for iterating over collections, and a nice simple way of declaring properties. XCode provides refactoring (YAY!) and more enhancements to keep your eyeballs on the code while editing and debugging. And even Interface Builder got cleaned up a bit and exposes nice simple ways of using core animation in Leopard. I'm looking forward to seeing it all in action.

BTW: I read on the RubyCocoa mailing list a few months ago that it might be bundled with Leopard too. Writing Mac OS X apps with Ruby... very cool... Have to wait and see if that one happens.

Wednesday, September 27, 2006

Digg, Ruby, & Cocoa

I recently discovered that Digg allows you to simplify story submission for readers by placing a "digg this" link on your website. That sounded like a reasonable thing to do for my blog entries and after reading Guy Kawasaki's blog about it, I decided to give it a whirl. It wasn't long before I found myself wanting to automate the generation of the anchor tag. So I immediately ran off to my Ruby editor and generated a little script:

require "erb"
include ERB::Util

title, description, url, topic = ARGV[0], ARGV[1], ARGV[2], ARGV[3]
puts <<EOS

<a href="http://adigg.com/submit?phase=2

&url=#{url_encode(url)}

&title=#{url_encode(title)}

&bodytext=#{url_encode(description)}

&topic=#{url_encode(topic)}">

<img src="http://digg.com/img/badges/91x17-digg-button.gif"

width="91" height="17" alt="Digg!" border="0" />

</a>

EOS


That worked reasonably well, but then I started thinking back to all the stuff I learned about Mac OS X software development with Cocoa and decided that I should really wrap up my cute little Ruby script with a Cocoa GUI!

So I immediately opened XCode, generated a Cocoa application, and started messing around with Interface Builder. Here's what I came up with:



From Interface Builder I stubbed out my controller class (MVC after all!) and wired the button to an action method. I also decided to use Cocoa Bindings to wire the text fields to NSString properties in my model without any code. Now since my model only needed to expose four string properties (one for each field in my window) I chose to cheat a bit and just added the four properties to the controller.

Since Objective-C doesn't have automatic memory management, you typically manage the memory allocation and deallocation in the accessors. Fortunately Accessorizor came to my rescue and generated that code for me. So the only thing left for me to code was to pass my four text values to my Ruby script. A simple Google search resulted in this page on Cocoa Dev Central that describes how to call the 'ls' unix command from Cocoa. I quickly adapted it for calling my Ruby script. The one change I made was that I added my Ruby script to my XCode project as a resource so that it would be included in the application bundle at build time. So I added this line for finding it:

NSString *path = [[NSBundle mainBundle] pathForResource:@"digg" ofType:@"rb"];


Finally I decided it would be nice to just put the generated anchor tag on the clipboard when I click on the "Digg It" button. So I perused my "Cocoa Programming For Mac OS X" book and added these three lines:

NSPasteboard *pb = [NSPasteboard generalPasteboard];
[pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self];
[pb setString:string forType:NSStringPboardType];


and voila:


Digg!

Monday, August 08, 2005

Tiger Development

After installing Mac OS X Tiger, and restoring applications and user data, my next job was to install development tools.

Java

On the Java side: I'm a bit perplexed why Apple doesn't ship their Java 5 implementation with Tiger. As far back as I can remember they've always shipped the latest and greatest. But this time I had to download. No big deal, but it's hidden on their website. I expected to be able to go to connect.apple.com (their developer website) click on "Downloads>Java" and it would be there. But no, only the Java 5 docs are there. Instead I had to go to the general Mac OS X website and go to the downloads section in there and search for it.

Anyway, that was only a minor annoyance. I was able to download it and install it without any trouble. My next problem was that Java 5 wasn't made the default VM. So I had a little more googling to do before I discovered a couple symlink changes would make everything happy. In the end I have all my Java apps and IDEs (i.e., Eclipse) working with the new Java 5 VM and all is well a week later.

Cocoa

Next thing was a move to XCode 2.1. I downloaded it and installed it without any issues (there was a nice big link on the Apple's developer connect website). I was able to open all my Cocoa projects, recompile and run without issue. So then it was time to move onto seeing what's new in Cocoa in Mac OS X. There's quite a bit, but the one that instantly attracted me was the visualization tools in XCode.

I've always been a big fan of modelling tools and the diagrams they create. I always find it easier to express ideas in a picture and it's always easier to look at a diagram rather than gobs of source code to figure out what someone else was thinking. Well apparently Apple feels the same way. XCode now gives you the ability to generate class diagrams from your source code (Java, Objective-C or C++). And these diagrams aren't static either. As you change things in code the diagrams reflect those changes. Fortunately, they look and behave like UML class diagrams so the symbols are pretty familiar.

Apple also uses this new diagram facility in something they call CoreData. Essentially you create an entity relationship diagram that describes the data that your application maintains and then at runtime, the core data framework will use this metedata to store and retrieve user data in an XML file or a SQLite database. Couple this with the Cocoa Bindings framework, which allows you to bind object properties to UI widgets, and you have some great facilities for building data-centric applications. Now that the persistence and UI parts of the application are taken care of by the Cocoa frameworks you are left to concentrate on the business logic. The big limitation in CoreData right now is that it's XML and SQLLite only. That means if you want to create a multiuser application with an enterprise database server you're out of luck. Secondly, even if it did allow you to go against an Oracle or Sybase server I don't think the tools are really designed for fine grained control over the object relational mapping or the queries that are generated. But I don't want to diminish the productivity of this framework in addressing the the single user data persistence problem. If I was developing a desktop Mac OS X application, I'd be all over this. Here's a nice little tutorial that you may find interesting.

There is also a nifty little feature that allows you to drag and drop an entity from the diagram into a window in Interface Builder and generate a default UI. Apple says you can use this feature to quickly create a starting point for your application or to quickly generate an application to exercise your data model. I was impressed that I could create a fully functioning application that maintained data with no code in just a few minutes!

Thursday, July 21, 2005

Bundles

Last night I upgraded my versions of Firefox and Thunderbird on Mac OS X. And then at work I did the same thing on Windows XP. The installation went pretty smoothly on both so maybe to most users the differences wouldn't be that significant but for someone like me who cares about little things like this, it showcased what I think is a pretty big features of Mac OS X, Bundles.

From Apple's developer documentation:
A feature integral to Mac OS X software distribution is the bundle mechanism. Bundles encapsulate related resources in a hierarchical file structure but present those resources to the user as a single entity. Programmatic interfaces make it easy to find resources inside a bundle. These same interfaces form a significant part of the Mac OS X internationalization strategy.

Basically it's a folder that looks like a file. It's a very simple but extremely effective method of hiding the details from the user. Most of the time, when you install an application in OS X you open a disk image and drag the application icon, the bundle, to some location on your hard drive. Then you double click it to run it. If you don't like where you put it then you drag it somewhere else. If you decide the app sucks you throw it (the one thing) in the trash. You don't use an installer or uninstaller.

On Windows on the other hand, it's never that simple. You almost always run an installer and then god knows what happens. While it's true that some Mac apps require an installer, especially if they need access to protected areas on the disk, it's the exception rather than the rule.

Like I said at the beginning, maybe most people wouldn't think this is a big deal but there is something quite satisfying about the installation/deinstallation process on a Mac. It's simple and obvious and you know what happened.

Thursday, July 14, 2005

Cocoa

When I originally created this blog I named it after Apple's Frameworks for creating Mac applications, "Cocoa". At the time, I was working my way through Aaron Hillegass's book Cocoa Programming for Mac OS X. Since Apple gives away its development tools for free with their OS I had previously played around with it. But for one reason or another I found myself leaving OS X development and instead investigating technologies more closely related to Java (the language I use at work). I also recently spent a couple months looking at C# and .NET. But finally I'm back to looking at Cocoa and think I'm ready to compare Cocoa to Java and C#. Like my C# review so many months ago (February 2005) I'll try to comment on the things that make Cocoa different from Java.

But first of all, some history. Cocoa development is done in a language called Objective C (objc for short). It was invented in 1983 by Brad Cox at Stepstone. It is described as a thin layer on top of C so unsurprisingly, anything you can do in C you can do in Objective C. The so called "thin layer" adds Smalltalk-like syntax to add object-oriented features. Objective-C uses the open-source GCC (GNU Compiler Collection) and so people can program in Objective C on any platform. I've even written a small command line program on Windows just to prove that it can be done.

Secondly, Mac OS X's (and Cocoa's) heritage is NextStep. After Steve Jobs left Apple he founded NeXT computer in 1985 and in many ways created a computer that was ahead of its time. Part of that vision, often overshadowed by the media's attention to the hardware, was the object oriented application development environment called NextStep, based on Objective-C. This set of libraries (or frameworks) was ported to several platforms (Intel, PA-RISC, SPARC, etc.) during its lifetime and became known as OpenStep in a deal with Sun MicroSystems. When Apple eventually bought Next in 1996, the NextStep frameworks became known as Cocoa. To this day the classes in the framework all begin with the abbreviation NS. Interestingly, part of Next's work in the early 90's to make NextStep portable (specifically to Intel) is what is enabling Apple to switch the Macintosh's processor from PowerPC to Intel with such little trouble.

Namespaces and File structure
  • By convention, the interface is placed in a header file (*.h) and the implementation is placed in a file with the "m" extension (*.m). This violates the spirit of the DRY principle (Don't Repeat Yourself) because the method names are now in two places. But on the upside the class's logical public interface is easily communicated through the header file. It also gives you a way of protecting your source code while still allowing third parties to use your frameworks. Java and C# both suffer from being easily decompiled.
  • There are no namespaces in ObjC. Instead a naming convention suggests using an abbreviation at the beginning of each class name (e.g., all the Apple class names begin with "NS").
Misc
  • Like Java and all other C-based languages other than C#, Cocoa uses camelCase instead of PascalCase.
  • ObjC frequently uses the at-symbol (i.e., @) to differentiate ObjC functionality from standard C functionality.
  • Object references look like C pointers. (see next bullet point)
  • NSString is one of the most commonly used classes in Cocoa. Like Java, it stores immutable Unicode strings. Use the @-symbol in front of a C string to create an NSString instance. (e.g., NSString *name = @"Cocoa";)
  • C's printf String formatting functionality is included with NSString's factory method stringWithFormat:. The NSLog() function for printing to console also supports printf-type functionality. (BTW: Java finally got around to supporting this with Java SE 5.)
  • Like C#, ObjC uses a colon (:) for subclassing instead of Java's extends keyword
  • ObjC also uses the colon (:) for implementing an interface instead of Java's implements keyword.
  • Class methods are denoted with the plus-symbol (+) instead of Java's static keyword.
  • Instance methods are denoted with the minus-symbol (-).
  • Visibility identifiers are nearly the same as Java's except they use an @-symbol in front (i.e., @public, @protected, @private). And like Java, the default is @protected when it's not explicitly defined. The biggest difference is that methods are always public. Private-like methods are created by excluding them from the class's @interface.
  • Exception handling is the same in ObjC as in Java with the keywords @try, @catch, @finally, @throw except exceptions are not part of the method signature (like C#). Exceptions were new in Mac OS X 10.3 (Panther) so I doubt that they are utilized all that frequently.
  • Like Java, ObjC uses an #import keyword to include references to the classes that it uses.
  • Like Java, the Cocoa framework is a singly rooted class hierarchy starting with NSObject.
  • An interface in Java is known as a protocol in ObjC
  • instead of Java's instanceof, NSObject has several methods for accomplishing similar functionality, isKindOfClass:, isMemberOfClass:, conformsToProtocol:
Method Syntax
  • ObjC methods define labels for each parameter. For example, an instance method for a Person class might look like this:
    • - (Person *)initWithFirstName:(NSString *)first Last:(NSString *)last;
    • This method returns a Person instance and takes two NSString parameters.
    • The first parameter is described by "initWithFirstName:".
    • The second parameter has the label "Last:".
    • The full method name is: "-initWithFirstName:Last:"
  • Using Smalltalk-like messaging syntax you would cause this method to be invoked with something like this:
    • [person initWithFirstName:@"Bob" Last:@"Builder"];
    • More generically [object methodName:param1 Label2:param2];
    • The nice thing about this calling syntax is that it's easy to tell from the calling side what each parameter is for whereas in traditional C, Java, and C# you need some documentation to help out.
    • Like Java, each method call is dynamically looked up and invoked.
  • ObjC's object oriented features are based on Smalltalk. As a result, the idea of invoking an object's method is better phrased as "sending a message to an object". In ObjC it is completely valid to send a message to an object that cannot respond to it and you will receive no error. This stands in stark contrast to Java's strong type checking at compile time. When coming from a Java background this seems strangely odd, but as you become accustomed to this dynamic behavior you soon begin to recognize its power.
  • There is a special ObjC type called id that is a pointer to an object of any class. By judicious use of id and ObjC's dynamic message mechanism you can avoid a lot of typecasting that is so prevalent in Java code. Naturally you can (and should) use the variables and parameters of the types you are expecting but in some cases where the type cannot be known ahead of time the id type is very valuable and produces succinct easy to understand code.
Memory Management
  • To create an instance of an object use alloc (e.g., [Person alloc];)
  • ObjC's constructors are responsible for initializing instance variables. The default constructor is init. Constructors that take parameters use init as a prefix.
  • Typically alloc and init are called together (e.g., [[Person alloc] init];
  • ObjC does not include any kind of automatic memory management. There is no garbage collector. Instead Cocoa uses reference counting. You use the instance methods retain and release to increment and decrement the reference count. When the count reaches zero the object is freed.
  • The alloc method automatically increments the reference count by one.
  • ObjC's destructor is dealloc. It is responsible for releasing instance variables that point to objects.
  • There is a second instance method that you can use to express your intention to release an object called autorelease.
    • GUI Cocoa application automatically instantiate NSAutoReleasePool.
    • It is this object that becomes responsible for actually releasing your object at some point in the future.
    • This autorelease mechanism allows you to return new objects from a method and is frequently employed by class factory methods (e.g., [NSString stringWithString:@"This will create an autoreleased copy"];)
    • If the calling method does not retain the returned object then it will be automatically released.
    • It is the event loop in a GUI application that creates and destroys release pools.
  • In practice this memory management scheme is more error-prone than languages with garbage collection and requires diligence to implement properly. However, memory releases happen relatively frequently and the application's memory footprint is more predictable and manageable.
Inheritance
  • Use super to refer to superclass methods or variables.
  • Use self to refer to the instance's method or variables.
  • Constructors should call the super constructor first. (e.g., -(Person *) init{if (self = [super init]){/*initialize variables*/} return self;}
  • Destructors should call the super dealloc last (e.g., -(void)dealloc{/*free instance variables*/[super dealloc];}
Properties
  • ObjC is similar to Java in using accessor and mutator methods to get and set private instance variables. The only difference is that the get methods are named the same as the instance variable.
  • I prefer C#'s and Delphi's ability to declare properties as first-class citizens. I believe it makes the code easier to read.
  • Java didn't include operator overloading because it typically gets abused in practice. ObjC doesn't include it either but having seen C#'s and Ruby's implementations I think if used properly it could make code more readable (I say "could" because I haven't used either extensively and hesitate to say with certainty)
Selectors
  • When using Java's Swing components (a.k.a., GUI Controls) you typically register an event listener with each component to be informed when the user interacts with it (e.g., clicks on a button). Because each listener must conform to a specific interface you end up creating a lot of anonymous inner classes. The code's intention is lost in the overly-verbose mechanics. Even if the IDE is generating this stuff for you, it's still ugly.
  • ObjC's selector specifies the signature of a message and is not bound to any particular class.
  • Create one using @selector( selectorName )
  • Or use NSSelectorFromString(@"selectorName:") to create one from a string.
  • You can programatically invoke a selector using one of the performSelector:, performSelector:withObject: variants in NSObject.
  • InerfaceBuilder, the tool for creating user interfaces for Cocoa applications, uses selectors in the target/action paradigm to graphically wire visual controls to methods that look like - (IBAction) methodName:(id)sender; with absolutely no code.
Collections
  • Cocoa has NSArray, NSSet, and NSDictionary and their mutable counterparts, NSMutableArray, NSMutableSet, and NSMutableDictionary which are functionaly similiar to Java's List, Set, and Map interfaces and various implementations.
  • Cocoa uses NSEnumerator to traverse a collection's members which is similar to Java Iterator.
  • Cocoa doesn't have any of the syntactic sugar of Java or C#, such as Java's enhanced for loop but because of ObjC's dynamic messaging infrastructure the need for typecasting isn't nearly as onerous so perhaps it's not needed.
Categories
  • An interesting feature of ObjC called categories, is its ability to dynamically add methods to existing classes even if you don't have the source code for those classes. Now when you think "Why didn't they add a method that does blah blah blah", you can just add it yourself!
  • mixins provide a similar feature in Ruby.
  • NSObject also has a method called poseAsClass: which allows a subclass to stand in for its superclass. This subclass can override superclass methods and add new methods.
Summary

ObjC has no garbage collector and doesn't generate bytecode which are two pretty big features of Java and C# but regardless it has just about everything that those other languages have plus more. It is a good solid object oriented time-tested application framework and unlike Microsoft with its .NET framework, Apple "eats its own dogfood". It uses Cocoa extensively to build its applications (e.g., GarageBand, iPhoto, iCal, iChat, Mail, etc). I've been fairly happy with the toolset although I wish refactoring support was available in XCode (which is also at least partially built with Cocoa). Next step is to go into building a "real" application, stay tuned...

Wednesday, February 02, 2005

All In The Family

What do Java, C#, Objective-C and Smalltalk all have in common? They're all in the same family!