Corbin's Treehouse - Corbin Dunn, Santa Cruz, CA
Plug Bug
Treehouse
Photography
Videos
Projects
Unicycling
About

Archive for the 'Apple' Category

WWDC 2015: Improving the Full Screen Window Experience


For the past 10 years I’ve given a talk at every Apple World Wild Developer Conference (WWDC). Well, except for one. That was 2007 when I was busy working on UIKit for the iPhone 1.0.

Apples is now posting our videos online without requiring an Apple developer account. So, everyone can check out my video for this year’s session #221 on their site:

Screen Shot 2015 06 12 at 7 18 41 PM

 I talk about how to implement Full Screen in Cocoa desktop applications, including some new tiling features in OS 10.11. Most the full screen information applies to all OS X versions that support full screen (I think 10.7 and higher). I also discuss Title Bar Accessory View Controllers — this feature requires 10.10 or higher. During the second half my colleague Taylor Kelly comes up and discusses how to do some cool dynamic layouts.

We also have a demo app showing off the features: Exhibition – An adaptive OS X App


SPORE


I got a new video game for the Mac – spore! I really wanted to give it a try last night, but my DVD drive stopped working on my MacBook Pro. Luckily, there are known hacks posted on the web for how to turn on the “Remote Disk” sharing that was added for the MacBook Air. This let me install it at working using one of the DVD drives on one of my other machines. I would have done it at home, but the two other Macs at home are still PPC running Tiger.

Photo 17.jpg


Why the API? NSTableView -preparedCellAtColumn:row:


I think I’ll do a few articles on why certain API was introduced in Leopard.

I’ll start with one of the new methods in NSTableView:

/* Returns the fully prepared cell that the view will normally use for
 drawing or any processing. The value for the cell will be correctly set, 
 and the delegate method 'willDisplayCell:' will have be called. You can 
 override this method to do any additional setting up of the cell that is 
 required, or call it to retrieve a cell that will have its contents properly 
 set for the particular column and row.
*/
- (NSCell *)preparedCellAtColumn:(NSInteger)column row:(NSInteger)row;

What is this method and what is it useful for? There are many reasons why it is useful, and they all are based on this fact: *all* of NSTableView’s operations that involve a cell at a particular row/column will be filtered through this method. Previously, NSTableView would have various internal methods and ways of obtaining the cell and there was no single spot where everything filtered through. Now there is.

This means:

1. You can acquire a “fully prepared” cell that is ready to draw — either in the NSTableView itself, or somewhere else. Somewhere else? Yes — an example where AppKit does this is for expansion tool tips, which draw in a separate tool tip window and in a view that is not actually an NSTableView. You might also want to access the “fully prepared” cell to generate a drag image when you override:

- (NSImage *)dragImageForRowsWithIndexes:(NSIndexSet *)dragRows 
	tableColumns:(NSArray *)tableColumns 
	event:(NSEvent*)dragEvent 
	offset:(NSPointPointer)dragImageOffset;

2. You can override the method to modify the cell. Think about this in a simple way, and it means you could easily bold odd rows without having to use -willDisplayCell:. Depending on how your code is setup, it might make more sense to do this work in the view, as opposed to the controller (via the delegate).

3. You can return an entirely different cell. Let’s say you want to have one cell that doesn’t change for one particular row; well, you can just always return that same cell, and it will always be used. You might want to do this if that particular cell has some sort of important state (such as an animation), which you don’t want to have to keep resetting or managing. Another example is for showing highlighting when you mouse over the cell.

Take this example from WWDC that I wrote a few years ago: PhotoSearch. Look at TrackableOutlineView.m, and you’ll see that the cell which is being tracked (ie: mouse is over it), is always returned from preparedCellAtColumn:row:. This was important from an abstraction perspective; the cell will get a single -mouseEntered: from the tracking area, and the same cell will eventually get a -mouseExited: — this allows the cell to set and maintain its own state, without forcing the delegate or NSTableView to save off the state and always reset it at draw time.

Why does this demo copy the cell, and not just use the single cell that is shared from the [tableColumn dataCell]? I mean, if the cell gets a mouseEntered:, and the tableView redraws *just* that cell, then things will work out fine, right? Yes — but if something else triggers any other row to redraw, then your tracked cell will be used, and it currently has the wrong state in it. That would be bad, and it would draw the wrong thing.

4. Another reason this method is useful is for type selection. When you type select, and NSTableView is attempting to find a row, it can acquire a fully prepared cell (including setting the stringValue, calling -willDisplayCell on the delegate, and setting up bindings). The stringValue of the cell can then be compared for type-selection to find a match. But, you wonder, isn’t that doing too much work for just matching on the string? Yes — for any decent sized table, you should implement this delegate method to directly return information from your model:

- (NSString *)tableView:(NSTableView *)tableView 
	typeSelectStringForTableColumn:(NSTableColumn *)tableColumn 
	row:(NSInteger)row;

5. Finally, another reason for the API; there is no easy way to know what the value of a cell will be if you are using bindings. Now, you can find out by using this method, since it will fill the cell’s content with bound values (if there are any).

Anyways, my first entry of “Why the API”. More to follow…hopefully.


natural vista


image818834989.jpg
Posted from: http://maps.google.com/maps?ll=37.3355,-122.0307


Greener AAPLs


I’m quite happy that my work promotes green living.


Xcode code completion and your code


How can you become a faster Cocoa programmer? One way is to adequately name your variables, enums and classes.

Let’s start with enums and take an example from something new to NSTableView in Leopard. This is copied from NSTableView.h with the comments stripped out for clarity.

enum {

NSTableViewSelectionHighlightStyleRegular = 0,

NSTableViewSelectionHighlightStyleSourceList = 1,

};

typedef NSInteger NSTableViewSelectionHighlightStyle;

– (NSTableViewSelectionHighlightStyle)selectionHighlightStyle;

– (void)setSelectionHighlightStyle:(NSTableViewSelectionHighlightStyle)selectionHighlightStyle;

There are several things to notice here, some of which are important to you. The most important thing (in my opinion) is the common prefix. Notice that the enum values fully contain the enum type name. Why? The answer is code completion, which you should be using. It is much easier to remember one key portion of the name than to remember all values. In this case, the key thing to remember is “selection”.
As a programmer working with NSTableView you know you want to change the selection highlight style, but you don’t remember the option for the specific style you want. You know the Cocoa convention is setFoo, so you type:

[tableView set

And hit escape (or whatever key combo invokes code completion for you. For me, I remapped the key to ctrl-space, since I was used to Delphi and Visual Studio. But, I also use escape).
You see this result:

TableViewSet_CodeComplete.png

and start typing “sel” to see the result you want:

TableViewSetSelResult.png
Which inserts this template:

TableViewSetTemplate.png
Now, I’m surprised, but most people don’t realize that they can type ctrl-/ (or maybe alt-/ depending on your key bindings) to select the placeholder and type over it. Memorize that keystroke, and use it.
Now, the common prefix name comes in really handy with code completion — just start typing in the type that the placeholder tells you and you’ll see what options you have:

TableViewSetOptions.png
In essence, you only have to remember “sel”, and from there you can derive exactly what option you want using code completion. Less memorization, and faster programming.
Unfortunately, a lot of Cocoa came along before code completion, and doesn’t follow this convention. But if you look at a new UI framework (ala: UIKit for the iPhone), you’ll find this pattern throughout it. It makes programming very fast with fewer trips to the header to find out what you need.

The bottom line: use a common prefix, wherever you have a list of options. Also note that the NSTableViewSelectionHighlightStyle has the prefix NSTableView, since it only applies to NSTableView. But, the property name is “selectionHighlightStyle”, since it doesn’t make sense to replicate the type name there.


WWDC 2008


WWDC 2008! Howdy to my fellow Cocoa Developers. Take a look at the conference schedule: http://developer.apple.com/wwdc/schedules/ and be sure to come to my talk! Tuesday at 10:30 AM, iPhone for Mac Developers.

If you have *any* Cocoa questions, come to the Cocoa labs! I’ll be working the labs this week, so find me (or any of the other great apple engineers) and ask questions!

Edit: if you go to: http://developer.apple.com/wwdc/students/ you can see a picture of me from last year — I have the Leopard print hair:

Picture 1.png


Maker Faire 2008


I was lucky enough to not only attend this years Maker Faire, but I also got to participate as a volunteer! I was a model in the Fashion Show put on by the Swap-O-Rama. Our friend Ashley is a marvel at all things fabric. She constructed some amazing articles of clothing for us to wear.

Here’s the set of pictures:

Maker Faire 2008

And a preview:


Cocoa: willDisplayCell delegate method of NSTableView, [NSCell setTextColor], and “source lists”


Mac OS 10.5 added a “source list” highlighting style to NSTableView, with the API below for your reference:

enum {

NSTableViewSelectionHighlightStyleRegular = 0,

NSTableViewSelectionHighlightStyleSourceList = 1,

};

typedef NSInteger NSTableViewSelectionHighlightStyle;

– (NSTableViewSelectionHighlightStyle)selectionHighlightStyle;

– (void)setSelectionHighlightStyle:(NSTableViewSelectionHighlightStyle)selectionHighlightStyle;


Source lists should have bold text when the item is selected, and NSTableView attempts to auto-format the cell’s contents to automatically do this for you, as seen in this screen shot for the selected item in the open panel source list:

However, the code that does this formatting does so by converting the ‘stringValue’ of the cell to an attributedStringValue that has the bold text. This is done *before* calling the delegate with “willDisplayCell”. The delegate gets the final say of how it looks in “willDisplayCell”, but this can cause unexpected results if you want to do something like this:

– (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

if(row == 0) {

[cell setTextColor: [NSColor redColor]];

} else {

[cell setTextColor: [NSColor blackColor]];

}

}

The problem with the above code is that it is *too late* for the coloring to be correctly applied to the cell if it is selected. The work around is easy; you need to color the cell text earlier, and a perfect place to do that is in the new 10.5 delegate method “dataCellForTableColumn:”

– (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

NSTextFieldCell *cell = [tableColumn dataCell];

if(row == 0) {

[cell setTextColor: [NSColor redColor]];

} else {

[cell setTextColor: [NSColor blackColor]];

}

return cell;

}

Cool. Have fun.


Overriding shortcut keys in the NSOpenPanel or NSSavePanel


It recently came up where someone needed to override some of the default shortcut keys in the NSOpenPanel or NSSavePanel. This is quite trivial to do. First off, the “easy way” would be to add a hidden NSPopUpButton in an accessory view that has the appropriate shortcuts. However, that won’t override the defaults (ie: cmd-r == reveal in finder, cmd-i == finder info window, cmd-a == select all, etc). To override these, you would subclass the appropriate panel:

@interface MyOpenPanel : NSOpenPanel

@end

@implementation MyOpenPanel

– (BOOL)performKeyEquivalent:(NSEvent *)theEvent {

NSLog(@”…test”); // an example of where you would do your key testing

return [super performKeyEquivalent:theEvent];

}

@end

You would then use it via something like:

[MyOpenPanel openPanel]


Easy to do…



(c) 2008-2017 Corbin Dunn

Corbin's Treehouse is powered by WordPress. Made on a Mac.

Subscribe to RSS feeds for entries and comments.

19 queries. 0.222 seconds.