Cocoa Samurai

Saturday, June 06, 2009

See you at WWDC!

wwdc_intro.png


I am taking just a few minutes to write this in the middle of packing my things for WWDC. This will be my 3rd time going to WWDC and my last time officially as a student.

packing.png


Already I have learned a great deal of things from the previous times i've gone. I've made an effort to get up earlier to get used to what will be a normal time to get up in a different time zone. Also I know Kevin Hoctor has said this several times and now I totally agree with him after trying 2x in a row... don't go to all the sessions. This event is a social event as much as a learning event, in the past I literally went to mostly sessions and didn't really leave any session and boy did I pay the price for it mentally and physically. It's very tempting to try and go to all the sessions and try to leech off every little bit of information you can from the Apple presenters, trust me you'd do good to take a break and besides you'll learn more from reviewing the videos after the conference. One of my goals is this year is to try and network more, I have business cards now and I plan to try and take breaks from sessions. If you see me, feel free to say hi!

me.png


This year there are a bunch of people from Twitter that I really want to meet. I plan to attend the SFMacIndie party on Sunday night, but beyond that I don't have a whole lot set in stone right now. Overall I am really excited this year and can't wait to arrive in San Francisco tomorrow! I'll see you there!

top photo from http://www.flickr.com/photos/hexholden/2564484035/

Saturday, April 18, 2009

Distributed Version Control & Git [Part 2]

dvcs.png


In Part I of Distributed Version Control & Git, I showed you why you should switch to Distributed Version Control and explained part of what makes Git a compelling Distributed Version Control System.

In Part 2 and the final part of this miniseries, I show you an overview of git and the basics and guide you through how you setup a git repository, doing commits, branches, merging, resolving merge conflicts with filemerge and show you the apps that come with git and GitX.



I also want to draw your attention to the fact that there are some excellent & much more detailed git tutorial videos that go into much more detail at GitCasts

Here are some more interesting resources

GitX

GitCast Videos
Setup Initialization & Cloning
Normal Workflow
Interactive Adding
Git Log
Browsing Git Objects
Branching & Merging
Rebasing
Distributed Workflow
Empty Branches
RailsConf Git Talk
Git Submodules
Git Diff

Monday, April 13, 2009

Distributed Version Control & Git [Part 1]

dvcs.png


This is a video based off a talk I gave on Distributed Version Control for the Des Moines Cocoaheads and gave an example of how to use it in the context of git. The premise of my talk was showing why you should switch to distributed version control and showing off some cool things it can do. Today I seriously believe that with few rare exceptions do we really need centralized version control, in addition Subversions merging is broken and these distributed systems tend to do branching & merging in a much more pleasant manner that actually makes things enjoyable. Literally when you start using Distributed Version Control you tend to start making a lot of branches and do many more merges, it becomes you do commits and merges when you want to vs doing them in some regularity because you fear your version control system might make things harder if you don't commit or merge now.



Check in later for Part 2 where I demonstrate some features in git in another screencast... for now here are some things to get you started

Git Homepage

The way I'd recommend people install Git
Git OS X Installer (Google Code Project)

Git Cheat Sheet

Gitx App

Pragmatic Programmers: Pragmatic Version Control Using Git [Book]

Linus Torvalds Google Tech Talk on Git

Randal Scwartz Google Tech Talk on Git

Thursday, March 26, 2009

Global Keyboard Shortcuts with Carbon Events

If your new to Cocoa you've probably not heard of Carbon, on the other hand if you've been developing for the Mac for a while now you've probably at least heard of Carbon and if you're really experienced you've probably used carbon. If you've used carbon at all this article really isn't for you. What I want to do is gently introduce you to carbon events, the 1 scenario where we'd use it for in terms of cocoa apps, why Cocoa Events can't handle this one scenario and why Carbon Events can, and how to implement it in a Cocoa Application.

Why Carbon Events
There is a specific scenario I had in mind as to why you would use Carbon Events ( actually if you have a Cocoa app it's a you have to use Carbon Events), the scenario is this: you have a Cocoa application and you know your customers will be running it but it will not be the active application running in the foreground, your customers may be looking at Mail, NetNewsWire, Xcode, etc basically some other application than yours and yet you still want to receive a keyboard shortcut key pressed event. How do you do this? Not with Cocoa, in its current form it's literally impossible. Here's why

Cocoa Events works as such, according to the Cocoa Event Handling Guide it says "In the main event loop, the application object (NSApp) continuously gets the next (topmost) event in the event queue, converts it to an NSEvent object, and dispatches it toward its final destination. It performs this fetching of events by invoking the nextEventMatchingMask:untilDate:inMode:dequeue: method in a closed loop. When there are no events in the event queue, this method blocks, resuming only when there are more events to process."

It then goes on "After fetching and converting an event, NSApp performs the first stage of event dispatching in the sendEvent: method. In most cases NSApp merely forwards the event to the window in which the user action occurred by invoking the sendEvent: method of that NSWindow object. The window object then dispatches most events to the NSView object associated with the user action in an NSResponder message such as mouseDown: or keyDown:. An event message includes as its sole argument an NSEvent object describing the event."

cocoasamurai_nsevent_window_button.png


So in other words the NSApplication has an event queue and receives an event (1) converts it into NSEvent objects (2) which it then forwards to a Window (3) which then dispatches the event to the view associated with the user action calling on it -mouseDown:(NSEvent *)event, -keyDown:(NSEvent *)event, etc (4).

This is great, but if our application is running in the background there is no way our Window will receive events. Cocoa Events simply does not allow for a regular cocoa application to be in the background and receive keyboard events. Now I could go on to further explain NSResponder and how it events could then go onto the menu's after exhausting all possible views in a window that could respond to an event, but that's another article onto itself. The point is our app is a regular cocoa app and it has a window and menu's, but we know our application is not going to have focus and thus won't have a window that can forward events or even application menu's to receive events, but we still want to receive an event and invoke some sort of functionality.

There are plenty of examples of this: OmniFocus has a quick entry window which you can invoke from anywhere, applications like Quicksilver use Carbon Events so you can invoke them anywhere from in Mac OS X. These are both Cocoa applications, but they depend on Carbon Events to give them notifications of global keyboard shortcut events. Conceptually Carbon events is vastly different from Cocoa Events. When I first finally got a Carbon Events example working it seemed very strange compared to Cocoa Events, it was more like there is a stream of events going by in the system and you install something to indicate a interest in a particular kind of event. If that event matches the specific event you are looking for then your code is called and you have a global keyboard shortcut. So how do we do this?

Setting up a project

In Xcode, go ahead and create a new Cocoa application. At this point if you build in go all you will have is a small window and an application that does nothing. Now go to File->New File and create a plain Cocoa class and call it AppController. Then click on the disclosure triangle by the Frameworks folder and then right-click on Linked Frameworks and go to Add -> Existing Frameworks and in your SDK add "Carbon.Framework."

At this point this should be all you have for AppController.h
#import <Cocoa/Cocoa.h>





@interface AppController : NSObject {



}

@end


Now in AppController.m add
#import <Carbon/Carbon.h>

and implement -(void)awakeFromNib

and you should have
#import "AppController.h"

#import <Carbon/Carbon.h>



@implementation AppController



-(void)awakeFromNib

{

}



@end


Now the next thing we need to do is add the declaration for our method which will handle the global keyboard shortcut. Above the "@implementation AppController" add the following line
OSStatus myHotKeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData);

this method will be the rough equivalent of implementing say -(void)mouseDown:(NSEvent *)event in a cocoa class. The Carbon Event handler will pass the EventHandlerCallRef (next event handler reference), EventRef (roughly equivalent to NSEvent) arguments to us. If we were doing really deep Carbon Events work then we might also be interested in all the arguments, but for this simplistic task all we need is the EventRef reference.

Into the guts of Carbon Events
Now we've set the foundation so now lets go to work in the awake from Nib method. Add the following code to the top of the awakeFromNib Method
    EventHotKeyRef myHotKeyRef;

    EventHotKeyID myHotKeyID;

    EventTypeSpec eventType;


Now lets understand these new variables.

EventHotKeyRef : The documentation is pretty descriptive about this "Represents a registered global hot key." In essence we have this reference so we can unregister it later if we want to.

EventHotKeyID : Again "Represents the ID of a global hot key." This is where you'll set some things to uniquely identify your global keyboard shortcut.

EventTypeSpec : "Describes the class and kind of an event." Passing in this reference after setting the class and kind of event tells the event handler what type of event this is.

So lets set the EventTypeSpec reference
    eventType.eventClass=kEventClassKeyboard;

    eventType.eventKind=kEventHotKeyPressed;


This will tell the event handler we are looking for a keyboard event and that a hot key was pressed. Now add

    InstallApplicationEventHandler(&myHotKeyHandler,1,&eventType,NULL,NULL);


this installs our event handler method we declared earlier, but haven't implemented yet, so when this event happens it will call our code. Now we need to uniquely identify our hotKey...

    myHotKeyID.signature='mhk1';

    myHotKeyID.id=1;


If you just intend on having only 1 global keyboard shortcut then this doesn't matter too much, but if you intend on having multiple global keyboard shortcuts then the id will matter greatly, it's what you will use to uniquely identify each specific event in the method we will implement shortly.

    RegisterEventHotKey(49, cmdKey+optionKey, myHotKeyID, GetApplicationEventTarget(), 0, &myHotKeyRef);


This is what actually registers our global shortcut. In Essence it's arguments are (1) the key code to the key you will use in combination with (2) modifier keys to create your global keyboard shortcut and (3) the Application Event Target which the GetApplicationEventTarget() method retrieves for us and finally (4) the EventHotKeyRef we declared earlier which gives us a reference to this keyboard shortcut we are registering. In this case it registers the spacebar (int 49) plus the command key and option key. So when Command+Option+Spacebar is hit our global keyboard shortcut will be triggered.

It's important to note that you cannot register the same key combination twice within the same application and have it trigger both methods, however multiple applications can register for the same global keyboard shortcut and Carbon events will trigger events in both applications. I decided to test this by duplicating the keyboard shortcut I use for OmniFocus quick entry which for me is Control+Option+Space Bar

    RegisterEventHotKey(49, controlKey+optionKey, myHotKeyID, GetApplicationEventTarget(), 0, &myHotKeyRef);


and woola the OmniFocus quick entry Window and my event both triggered
multiple_apps_1_carbon_event.png


Now the hard part is behind us all we need to do is implement the method

OSStatus myHotKeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData)

{

    NSLog(@"YEAY WE DID A GLOBAL HOTKEY");

    

    return noErr;

}


What if we want to handle multiple global keyboard shortcuts?

OSStatus myHotKeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData)

{

    EventHotKeyID hkRef;

    GetEventParameter(anEvent,kEventParamDirectObject,typeEventHotKeyID,NULL,sizeof(hkRef),NULL,&hkRef);

    

    switch (hkRef.id) {

        case 1:

            NSLog(@"Event 1 was triggered!");

            break;

        case 2:

            NSLog(@"Event 2 was triggered!");

            break;

    }

    

    return noErr;

}


Well then you have to use GetEventParameter() as such to get the EventHotKeyID which you can then get it's ID code and handle the event appropriately. This would also involve creating a 2nd hot key and setting it's id to 2, 3,etc..

Key Code
The only thing left is the integer key code I mentioned earlier. I talked to Eric Rocasecca and Jim Turner from Startly (who make QuicKeys which I think would use Carbon Events, but evidently they use their own system) about this and they had a magazine with a reference of all the key codes in it, I didn't have this and didn't want to bother hunting down an old rare magazine. Several Google searches later I found an old app called AsyncKeys! which tells you the integer code of any key you press. I downloaded it a long time ago, but I did turn up a couple locations that actually had a download as the original site appears to be long gone (really sorry but I can only find .sit files): http://asynckeys.mac.findmysoft.com/ and if you Google around you can find other download locations.

Here are some random key codes
Spacebar 49
a = 0
1=18
F1 = 122
Left arrow = 123
Down arrow = 125
Right arrow = 124
Up Arrow = 126
Enter = 36
Backspace = 51
` = 50
and I could go on and on...

Conclusion
Essentially we saw a brief intro into how Cocoa Events work, saw how carbon events work, installed an event handler in our application, registered a global hot key and saw how to handle multiple global hot keys. This is a narrow use scenario, not many apps will need to use this, but if you want to activate a particular function and your application is Cocoa and running in the background, this is the best way you achieve this functionality. I really wouldn't recommend digging into Carbon more as Apple is moving to deprecate it and as a Cocoa developer you should be finding that you'll need carbon less and less as time goes on.

Sunday, March 15, 2009

Book Review: Pragmatic Thinking & Learning

prag_cover.pngIn what may be become the first in a series of reviews, I thought i'd share some of my thoughts and some insights into various Computer Science/Programming/Developer related books. I am always reading something so I thought i'd provide some thoughts on these books as I read them.

Pragmatic Thinking & Learning is a book that I came across in an unusual way, basically Bill Dudney said he was reading it on twitter, posted a couple updates on his progress and then never really mentioned it again. I was getting done reading Predictably Irrational and the book left me very fascinated about Psychology. I have taken Psychology class, but Predictably Irrational brought it down to a practical level and showed how it applied in the real world with behavioral economics. In that same spirit Pragmatic Thinking & Learning is to Programming & Learning what Predictably Irrational is to behavioral economics.

It's a fascinating journey through behavioral theory, cognitive science, neuroscience and some psychology, all while you are learning how your brain is wired and how it all works. Don't let these science terms make you think it's some boring study on how our brains work, as the title says it's Pragmatic Thinking & Learning. In essence it takes you through how your brain works and then quickly applies it to the real world and offers more of a framework for how you can begin to apply the principals presented. Through the tips and studies in this book you gain a lot of unique insight into problem solving, for example how do you teach someone how to play tennis with only 20 minutes of time? One of the things that makes this book somewhat unique is that it forces you to stop every so often and do an activity or think about something. For example I meditated for 5 minutes today, where I don't think I've really ever been instructed on meditation, and I liked doing it so i'll probably continue trying meditation for a while and observe what differences it makes in my day.

It's also not just the author making a case for an opinion, there are many citations throughout the book to external resources or studies on a particular subject. It offers some very good tips on things from how to keep yourself organized, how to think out solutions to problems, how as a developer you can try and recover from being interrupted when your in "the zone" and many other things like that. I was surprised when I saw the Rubber Duck debugging technique online one day and then came to read about it later that evening in the book. The book presents a case for something and then tries to get you thinking and get you involved in actively applying that to your situations.

My only complaint is the author mentions using a personal wiki to keep things organized and keeps showing he is on a mac and never mentions VooDooPad which I use everyday. I got started using VooDooPad as a way to keep my School notes organized and now I use it for a lot more things, including notes about Cocoa, specific Classes, personal things,etc, it's essentially a Wiki in a convenient self contained document.

Overall it's a nice collection of information on how our brains work, techniques to solve problems, how you can learn information or a skill faster and find techniques that work better for you individually. It's been a surprisingly good read and I am glad I bought it because Im sure I'll reference it from time to time from now on.

Wednesday, February 25, 2009

On Safari 4's Tab Design & UI

Untitled.png


Everybody has been bashing Safari 4's Tab design like crazy and so I thought I'd try and be a sane middle of the ground response, offering my honest opinion here.

Honestly I am a bit mixed on them, one would think that seeing Google Chrome with this type of UI that I would be prepared for a User Interface like this. So What's different?

chrome_tab.jpg


Well one thing I noticed is that Google Chrome has a background which the tabs are placed on. I can't say I am a fan of this as it reminds me of the MS Windows MDI interface I have a disdain for. It makes it look like there is a larger encompassing container holding all the tabs together which it may have in the data structure design in the application logic, however the user doesn't really need to see this unless it offers something that makes the overall UI more usable. Contrast that with Safari's tabs...

Picture 5.png


...which literally are at the top of the window and in which the tabs appear to exist without any encompassing container. In principal I agree with Apple on redesigning the interface. To me it makes more sense as it looks like Safari's tabs are literally like file folders where the whole interface is contained inside the bounds of the tab vs the older style tab UI used by older versions of Safari and shared with other browsers like Firefox and Camino where just the web view is inside the tab and the UI happens to adjust/switch to reflect to whatever the web view for the tab contains (i.e. the location bar suddenly switching it's url text when switching to a new/different tab.)

Picture 7.png


However my likes of principals and general use are different. I think the reason I (and many people) don't like the new tabs may be that it appears initially that the tabs have gotten a lot smaller. However when comparing the 2 tab styles it appears they are about the same size.

One thing that does annoy me about the interface is the deceptive tab resize icon...
Picture 5.png

I say deceptive because it's the same icon (just rotated 90 degrees) that shows in the bottom right of each window on Mac OS X to indicate a drag area where you can click your mouse and drag the icon to resize your window. However on Safari 4 this only allows you to reorder your tab and drag it left to right and out of the window to create a new window, whereas clicking on the tab text is the same as clicking on the window itself and allows you to drag the window around. Really I think this is annoying only in their choice of icon. My First impression of this was that it would allow me to resize the tab width in the window.

Another annoying thing is that the title bar is now suddenly complicated with a bunch of tabs. Leave it to Apple to try and simplify the user interface, but there is a balance between reducing the area that UI controls take up and a simplistic user interface, It feels like by merging the tabs and title bar into 1 control that the User Interface as a whole has gotten more complex, for 1 thing is now you can never really see the whole title of a webpage when it's in a focused tab and has and significant length for its title. It almost feels like this could work, but the UI control itself isn't quite polished yet like it's missing something if this is the direction that Apple is going to proceed in.

Picture 6.png


One thing I LOVE that Apple has done that is so stupidly simple & brilliant is the extended tab list. I love that Safari introduces this simple concept of shading the rows in the menu that aren't visible so you know what is and isn't visible. I really hope other browsers copy this concept.

Conclusion
Overall I am still mixed, I honestly think every browser sucks at something that makes it just short of perfect, however for me Safari ( with Webkit Nightly ) sucks the least and therefore is the best browser for me at the moment. However I don't stop using Camino, Firefox & now OmniWeb, they all have their purposes, just not as my primary browser. The thing to remember is that Safari 4 is a BETA yes I know it's not polished, but last I checked that's what Public Betas are for. Safari 4 will get better and maybe we will adjust to this new style of tabs at the top of the Window and it may become an accepted standard in browsers, however only time will tell and if you really don't like the new tabs you can always just change them with a hidden preference. For now I think I need a few more days to a week to get at a real deep sense of if I like the new tabs or not. Also another interesting trend is more eye candy in the browser ( Top sites and cover flow for history ), I can't wait to see where Apple takes this.

Google Chrome CC screenshot http://flickr.com/photos/brullonulla/2826039336/sizes/o/

Wednesday, February 18, 2009

NSConference

nsconference_block.png


If you haven't heard already Scotty is putting together a Mac Developer conference for Europe called NSConference which will be April 16-17 in Hatfield, UK. I would love to go to this, but I am at an odd stage where I am still really a student and am trying to figure out what I am going to do to transition to a full time job in Mac Development, so $1,000+ for a few days in Europe is really beyond my means at this point. However I fully support conferences like this, WWDC and C4 where developers can get together, socialize and learn from each other and exchange ideas and information. Plus I have talked to several of the speakers who will be at the conference (either in person or online) and they are all top notch mac developers, I can only hope that Scotty publishes the videos (like C4) so I can watch them later on after the conference has ended. I am totally jealous of anybody going to NSConference for 2 big reasons (1) I've never been outside the United States (not by choice, I really want to get outside the US sometime) and (2) The sessions and workshops look like fantastic things I'd want to learn about from UI Design desicions, designing custom controls, foundations of Objective-C, etc. If you haven't thought about it already I'd suggest you look into it and head to NSConference.

NSConference in the US?

Also Scotty appears to soliciting feedback for a possible conference like NSConference in the US. If you would want something like that please give him your honest and constructive feedback here: http://cocoadev.com/forums/comments.php?DiscussionID=731