Borkware Miniblog

July 22, 2010

QFF: Kitchen MVC, part 1

Filed under: programming, Questions From Friends — Mark Dalrymple @ 2:08 pm

I got a question a couple of weeks ago under the subject “Cross File Method Calling” from a friend who was struggling with Model/View/Controller. Like a lot of stuff, it’s easy to look at a concept like MVC, grasp the contents, and then have your brain go into vapor lock when faced with empty source files. This F# major scale only has six sharps in it. It looks pretty easy on paper. Then you try to play it on the bassoon. Oh my.

We had a nice chat that turned into more “how to reduce dependencies” rather than full-blown “here is MVC in all of its glory”. Specifics have been changed to protect the cool project he’s working on.

I have this: KitchenCombatViewController.m – I create 4 new UIViews: OvenView, FrigeView, PantryView, and BlenderView. These know how to draw themselves, I can layer them and hide/unhide them as needed. Works well.

Now in the touches routine in BlenderView, I want to call a method in another file, like setNeedsDisplay in PantryView. I can make an instance variable that points to it, but I don’t know how to initialize it to point to the PantryView.

Let’s take a step back. Here’s what I saw with the first sentence:

mvc-1.png

The next statement, having BlenderView talk to PantryView, would look like this

mvc-2.png

Which would work OK now. But as software evolves, you’ll find other places to do the same trick. “FrigeView will need to tell the OvenView this. And then the BlenderView will also need to tell the FrigeView that.” And before you know it, you’ve got a pretty complex web of interactions:

mvc-3.png

It might not happen immediately. It might not happen until the next version or two as you add features, but as you add more dependencies between objects, it becomes easier to add even more dependencies. Wonder what happens if you add another view into the mix later? You’ll probably end up with another N connections. And if you’re not careful with memory management, you’ll get retain cycles.

What you want to do is to reduce the number of individual points of contact between the moving pieces. The KitchenCombatViewController already knows about the four views. It creates, layers, shows and hides them after all. So it would be a good place for that logic:

mvc-4.png

Notice that the relationship between the controller and the views has become two-way. The views need to know about the controller so they can tell the controller “hey something Interesting happened to me. Other folks may or may not want to know about it”. But notice that there are much fewer direct interconnections between objects. If you need to have FrigeView’s touch handlers tweak the OvenView, it’s a line or two of code in the Combat controller rather than setting up a direct dependency relationship between the two.

Also, if you add a new view type, say a SinkView that needs to be updated as combat progresses, you don’t have to touch any of the other views. This last point is huge. You can extend the capabilities of your system without having to touch a lot of other places in the code. That’s fewer changes that could introduce bugs. Less chance of forgetting some detail, like “oh yeah, touches in the FrigeView really needs to tweak the SinkView too”.

That makes sense, but I’m not seeing how I do that “tell the combat controller” that something interesting happened?

That’s in part 2, attack of the code.

July 15, 2010

QFF: id and NSFastEnumeration

Filed under: programming, Questions From Friends — Mark Dalrymple @ 2:48 pm

Do I remember correctly that id is a pointer, like a void*?

Yep. It’s a pointer to an objective-C object, but not necessarily an NSObject.

So, id* is a pointer to a pointer?

Yep. Like a void**.

I’m looking at the fast enumeration protocol

I was wondering where this was coming from :-)

- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *) state
                                   objects: (id *) stackbuf
                                     count: (NSUInteger) len;

So it’s expecting you to return an array of object pointers?

If you want. When this method gets called, objects will already be a buffer (presumably on the caller’s stack) that will hold len pointers. You can fill this with your data structure’s contents to be iterated over. You can also return a pointer to your own storage via the state structure’s itemsPtr:

typedef struct {
    unsigned long state;
    id *itemsPtr;
    unsigned long *mutationsPtr;
    unsigned long extra[5];
} NSFastEnumerationState;

July 14, 2010

QFF: NSDictionary and Autorelease

Filed under: programming, Questions From Friends — Mark Dalrymple @ 2:36 pm

I occasionally get Questions From Friends over mail or AIM or IRC.  Usually they’re simple things and quick to answer.  I figured I’d put the answers here too in case anyone’s really bored on a rainy sunday afternoon.

besides autoreleasing the memory, what is the difference between the following two statements?

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];

Nothing really.

why would I ever NOT want to autorelease? Seems like the 2nd statement is easier

If you’re going to be immediately hanging on to it, the autorelease is wasted work,
or if you’re doing it inside of a tight loop – it’s better to get rid of it immediately rather than let a bunch of stuff accumulate in an autorelease pool. Of course, you can make and drain your own pool inside of your loop. Autorelease pools are pretty fast. But if you have a big spike of memory, say by accumulated autoreleased objects waiting for the grim reaper, that’ll push out things like mapped-in code segments, which may need to be brought back in later on. And on the phone, cycles count again, so it’s a hair more efficient to avoid autorelease. Just make sure you don’t accidentally forget to release it when you’re done.

July 13, 2010

Help menu search as shortcut button

Filed under: off-topic, Random — Mark Dalrymple @ 12:45 pm

Ever find yourself wanting a short-term shortcut button for something in an application, especially something buried a couple of levels down in menus?  I’ve been using the Help menu search field to essentially pre-cache a menu item for quick access.

Specifically, when I work on the newsletter for my community orchestra, I have all the submitted stories in one Pages™®© document and the final newsletter in another document.  I strike out stories as I move them over. I can tell what’s been finished, but I don’t destroy what’s there in case I need to undo or refer to something.  There’s no toolbar button that I could find for strikeout, so I just search for ‘strike’ in the menus. Now when I want to strike out some text I just go to the help menu and hit the first useful item.

 

Help menu in Pages with 'strikethrough' selected

Create a free website or blog at WordPress.com.