Corbin's Treehouse - Corbin Dunn, Santa Cruz, CA
Plug Bug

The 'Cocoa' Category

Tricks for fast Bluetooth LE data transfers

I’ve been using the Adafruit LE friend to do some data transfer tests. With the basic setup, I was sending 1 kB of data in about 9.5 to 10 seconds. That is horribly slow! About 100 bytes per second.  I did some research and found a couple of good links. This link about BLE discusses using the Nordic nRF chip and mbed to send data to a peripheral (i.e.: from the computer to the device). This link about sending data from the peripheral has some good tips when going in the other direction.   I gave up trying to get the Adafruit LE friend to be... [read more]

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:  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... [read more]

NSTableView Tips: Doing Animations with Core Data

For my “Cyr Wheel Pattern Editor” app I am using CoreData and an NSTableView. However, I’m sort of “manually” doing bindings for the array content itself to get animations in the View Based NSTableView. Here’s what my model looks like: The CDPatternSequence has a children array of CDPatternItems: @interface CDPatternSequence : NSManagedObject @property (nonatomic, retain) NSOrderedSet *children; @end Now, if you have Xcode generate the standard code you might have noticed the standard NSOrderedSet accessors aren’t implemented for you; this is a bug in CoreData, but here is a good post on stack overflow about it. The minimal implementation I... [read more]

NSTableView Tips: View Controller per row

Sometimes you may find your application has rather complex rows, and you want an NSViewController to manage each row in a “View Based” NSTableView. This is fairly easy to do, and I did it in my Cyr Wheel pattern editing application. My “Cell View” that I want for each row was designed in Xcode like: A simple NSViewController subclass: @interface CDPatternItemViewController : NSViewController // the thing we are editing @property(weak) CDPatternItem *patternItem; @end The controller code is what is interesting. I use an NSWindowController subclass, and keep an array of the view controllers: @interface CDPatternEditorWindowController () { @private NSMutableArray *_patternViewControllers;... [read more]

NSTableView Tips: Not delaying the first responder

I have a little home-brew Cocoa app for making Cyr Wheel patterns. The UI is built with an NSTableView and looks like this: Now normally when you try to directly click on one of the NSTextFields the table will first select the row. Then a second click will allow you to start editing. For most tables, this is the behavior you want. For something like what I have, I want to avoid this, and allow the first responder to go through. This can easily be done by subclassing NSTableView and overriding: - (BOOL)validateProposedFirstResponder:(NSResponder *)responder forEvent:(NSEvent *)event { return YES; //... [read more]

Implementing delete in an NSTableView

I’ve seen many ways to implement delete in an NSTableView. Many are good. Many hardcode references to something they shouldn’t, and those are bad. Here’s an easy way: Subclass NSTableView and override keyDown: - (void)keyDown:(NSEvent *)theEvent { // handle delete unichar key = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; if (key == NSDeleteCharacter && self.selectedRow != -1) { [NSApp sendAction:@selector(delete:) to:nil from:self]; } else { [super keyDown:theEvent]; } } This just lets the responder chain take care of it. Your window controller can easily handle it by just implementing delete: - (IBAction)delete:(id)sender { if (self.tableView.selectedRowIndexes.count > 0) { [_tableView beginUpdates]; [[self _patternSequence] removeChildrenAtIndexes:self.tableView.selectedRowIndexes];... [read more]

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... [read more]

Cocoa programmers: avoid writing to the user defaults when you don’t need to

[Edit: ecto ate this post, so I’m typing it in again!] I discovered that a lot of applications will unnecessarily write to NSUserDefaults. This causes your app to hit the disk when it shouldn’t, and is a slight performance penalty. AppKit is also susceptible to this problem; if you hit cmd-O to bring up the open panel in any application, you will see it writing things to the user defaults, when it probably doesn’t need to do so. I’m working on fixing that, and you should to! So, how do you do it? It is easy — just add a... [read more]

Getting rid of the undo warning in Xcode after saving

One of the most annoying dialogs in Xcode is the undo warning dialog you get when attempting to undo after a save. I do this all the time, and I hate the warning. Luckily, there is a user default to turn it off: defaults write XCShowUndoPastSaveWarning NO

Wake up and smell the cocoa

Your most important breakpoint in Cocoa

…..drumroll please…and it is…is: objc_exception_throw. You should always have this breakpoint setup in any Cocoa or Cocoa Touch app that you are building. How do you do it? In Xcode, Run -> Show -> Breakpoints and double click on a new breakpoint. Type it in, ie: Exceptions in cocoa are, well, exceptional. If your app is throwing them, then you should fix them.

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... [read more]

WWDC 2008

WWDC 2008! Howdy to my fellow Cocoa Developers. Take a look at the conference schedule: 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: you can see a picture of me from last year — I have the Leopard print hair:

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... [read more]

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... [read more]

Leopard: PhotoSearch demo app now live

PhotoSearch, a demo app I wrote for WWDC a few years ago, is now live: It demonstrates some cool custom cell stuff that is only available on Leopard.

Instruments on Leopard: How to debug those random crashes in your Cocoa app

Update: Sept 9, 2009: Mac OS 10.6 Snow Leopard now has this feature built into Instruments! In Xcode, choose “Run -> Run with Performance Tool -> Zombies”, and repeat your steps that cause the crash. Easy as pie. Read on if you don’t have Snow Leopard… Mac OS 10.5 Leopard has a great new developer app called Instruments. It can easily be used to debug those “random crashers” in your application caused by too many -release or -autorelease calls. Let’s see how. If you want to follow along, download this project: Open it up in Xcode. The nib has... [read more]

New Leopard user features – Open and Save Panels

Leopard, the new Mac OS 10.5, is out! There are a lot of new features, but not everything is mentioned on the features page. Here are some of the cool “power user” features which you may not know about: The Open and Save Panel (implemented in Cocoa, also known as the NSSavePanel and NSOpenPanel) 1. There is a new Icon View mode with options: However, the way to change the icon size to be small (as seen above) isn’t obvious. Click and hold down on the icon view segmented cell and a popup will occur: 2. You can now insert... [read more]

NSBrowser, bindings, and a custom cell class

Hi Cocoa Programmers, There is a small bug in NSBrowser if you use bindings and want a custom cell class. Typically, you would do something like this in your awakeFromNib: - (void)awakeFromNib { [iBrowser setCellClass:[ImageTextBrowserCell class]]; } However, if you are using bindings, it won’t work. The cells that were archived out in the nib file will not have the proper class. So, you have to nudge NSBrowser a bit to get it going: - (void)awakeFromNib { [iBrowser setCellClass:[ImageTextBrowserCell class]]; [iBrowser loadColumnZero]; } Just a quick tip in case you run into this!

Xcode debugging tips

It might be nice to note a few Xcode debugging things that I tend to do. Frequently, I’ll want to break on a specific symbol, like -[NSException raise] Well, there are several ways to do this. One way is to drop to GDB and type “b -[NSException raise]”. Another way is to bring up your breakpoints window in Xcode and add a symbolic breakpoint: and type in the same thing, “-[NSException raise]”. But wait! You can be lazy. Just type “raise” and Xcode will then prompt you to select the right symbol: You can also do this for a generic... [read more]

People! Use your keyboard (shortcuts) for menus.

Mac OS X has some GREAT keyboard access. One spectacular thing is the ability to access all items (unlike windows, where you have to have a defined shortcut for each item, and you easily run out of items). First, go to the System and change the keyboard shortcut from Ctrl-F2 to Cmd-F2. Cmd-F2 is so much easier to hit than Ctrl-F2. Next, use it! Being from Windows, when I first used it I didn’t realize how it works. Basically, it is doing type-selection; ie: you type the word you want it to go to. So, people are amazed at... [read more]

Xcode tips and tricks — fast method finding

Inside of Xcode, I’ll want to quickly go to a method implementation. If you hit Cmd-F and do a find for the method name (or the start of it), you will frequently get hits for calls of the method instead of just the implementation. There is a quick way to find the implementation: Hit Cmd-F and type: “)methodName”. The left paren will match only the implementation (provided you don’t put a space after it…which you shouldn’t do anyways). I picked up this little tidbit by watching Troy Stephens code around. Thanks Troy!

NSOutlineView: reloadData and crashes in reloadData

A note to NSOutlineView Cocoa programmers: It has never been safe to call reloadData while an outlineView is doing a reloadData. What the heck does that mean? Well, if you call reloadData, a whole bunch of delegate/datasource methods will be called, such as outlineView:numberOfChildrenOfItem:, outlineView:isItemExpandable:, etc. Well, if in those delegate methods you accidentally call reloadData again, bad things can happen. Specifically, you will probably get a crash in NSOutlineView. More often than not, this is done by an accidental side effect, but it is something to be aware of. On Leopard, I will make NSOutlineView more resilient to this... [read more]

WWDC: Beyond Buttons and Sliders: Complex Controls in Cocoa

Come to WWDC this year! I’ll be giving a great talk on advanced control and cell creation with Cocoa: 120 Beyond Buttons and Sliders: Complex Controls in Cocoa Learn how you can quickly and efficiently create sophisticated Cocoa user interface elements for your application. Get practical guidance on how to extend Cocoa control objects like the table view and outline view using your own custom cells, and how to customize menus in a variety of ways. Copied from: WWDC 2006 – Session Descriptions

Cocoa: modal NSColorPanel dialog.

Hi all, I’ve seen some people request how to do a modal color panel. Well, carbon has GetColor(..) which ultimately uses the same NSColorPanel. So, you can set it to begin a modal session before you call GetColor(..). Here’s a code snippet: #import <Carbon/Carbon.h> – (IBAction)buttonClick:(id)sender {     NSColorPanel *colorPanel = [NSColorPanel sharedColorPanel];     NSModalSession session = [NSApp beginModalSessionForWindow:colorPanel];          RGBColor inColor = {128, 128, 128};     RGBColor outColor = {0, 0, 0};     Point point = {0, 0};     if (GetColor(point, “\p”, &inColor, &outColor)) {         NSColor *color... [read more]

[NSColorPanel isContinuous] and [NSColorWell isContinuous]

A quick comment about these two properties: [NSColorPanel isContinuous] and [NSColorWell isContinuous]. Generally, you want these two things to be in sync. Whenever the color changes in the NSColorPanel, the color in the NSColorWell will update. However, the action in the NSColorWell will sometimes not be sent, since it isn’t the thing controlling the mouse. If you set isContinuous to NO on an NSColorWell, but do not call [[NSColorPanel sharedColorPanel] setContinuous:NO], then the color panel is going to keep sending messages to the color well, but the action will never be sent! The bottom line: make the two properties match!

Xcode shortcuts to finding a file.

Cocoa Developers: While programming with Xcode, I’ve developed several habits to make me a faster programmer. I’ll share these tidbits with you. 1. Use Cmd-Shift-D to quickly open files that you know the names to. I’ll know that I want to open a particular file, such as NSTableView.m. So, I hit cmd-shift-d to bring up the “Open Quicky” dialog and type in nstableview (note that I don’t use the correct case, or extension, and it still works): This will work for framework header files too. 2. Use Cmd-Alt-UpArrow to switch from the header to the implementation file. I use this... [read more]

Cocoa: NSArrayController and two tableview’s

Hi Cocoa Developers, Tip of the day: Don’t bind two NSTableView’s to a single NSArrayController instance. Bugs will happen! More specifically, attempting to multi-select rows will not work properly — the two tableviews will fight for the selection. Eventually, this may be changed, but for now, in Tiger, it does not work, so don’t do it! EDIT: This will work, as long as the allowsMultipleSelection value is the same on both tableviews.

Cocoa: Targeting the entire tableview in a drop operation

Hi Programmers. If you are doing drag and drop in an NSTableView with Cocoa, you can use the following method in your “validateDrop” datasource method to retarget the row it is going to: – (void)setDropRow:(int)row dropOperation:(NSTableViewDropOperation)op; The documentation is missing something. If you specify a row of -1 and a dropOperation of NSTableViewDropOn, it will target the entire tableview, as opposed to an individual row.

Cocoa: drop down menu buttons

In Cocoa, it is pretty easy to use an NSButton that creates a drop down menu. One of the key-tricks to making it appear to be an NSPopUpButton is to set the [NSCell sendActionOn:]. Generally, menus are displayed on mouse down, not up. Normally, the action for a button is sent on mouse up. To get around this, you can simply access the cell of your button and tell it to send the action on mouse down: [[mybutton cell] sendActionOn:NSLeftMouseDownMask]; Cool!

(c) 2008-2017 Corbin Dunn

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

Subscribe to RSS feeds for entries and comments.

57 queries. 0.639 seconds.