Life as Clay

Posts Tagged ‘cocoa

Cocoa Programming for Mac OS X, 4th Edition: Chapter 3 Challenge

leave a comment »

Howdy. I previously wrote some entries about the solutions to the challenges in the Cocoa Programming book, 3rd Edition, by Aaron Hillegass. The 4th edition is good. Like the first edition, however, I find the description of the challenges to be a little vague.

I think he does that on purpose. The solutions usually are simpler than they appear.

The Chapter 3 challenge is, “NSDateFormatter’s setDateFormat: to customize the format string on the date objects in your LotteryEntry class.”.

Here’s what you do.

  • Look for NSDateFormatter in the Xcode documentation. Once you find it, search for the setDateFormat: method. You’ll find that you have to send a string to the method. Perhaps most useful is a link at the top of the class to the “Data Formatting Guide.” Once there, click to the “Date Formatters” page. Aha… here’s where the good info it.
  • Search again for the method name — but only search on this page — for setDateFormat:. You’ll find examples of the type of string that you can use for the date formatter. Copy one of those strings. It will look something like: @"yyyy-MM-dd 'at' HH:mm" or @"yyyy'-'MM'-'dd'T'HH':'mm':'ss"
  • Open LotteryEntry.m in your editor window and find the - (NSString *)description method implementation.
  • What you’re going to do is to replace the formatting that you entered during the chapter with your new format. Your previous method looked like:
- (NSString *)description
{
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setTimeStyle:NSDateFormatterNoStyle];
[df setDateStyle:NSDateFormatterMediumStyle];

NSString *result;
result = [[NSString alloc] initWithFormat:@"%@ = %d and %d",
[df stringFromDate:entryDate],
firstNumber, secondNumber];
return result;
}
  • You want to replace the messages that your sending to your date formatter. Your new method should look like this (with the date string you found):
- (NSString *)description
{
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"yyyy-MM-dd 'at' HH:mm"];

NSString *result;
result = [[NSString alloc] initWithFormat:@"%@ = %d and %d",
[df stringFromDate:entryDate],
firstNumber, secondNumber];
return result;
}

That’s it! Run your program and look at the log to see the new format. You can browse through the documentation a bit more to learn more about creating custom formats.

Written by Clay

January 25, 2012 at 16:14

Posted in Cocoa, Objective-C, Tutorial

Tagged with , ,

Connecting NSOutlineView to Core Data in 10.6 Part 1: Ordered Trees

NOTE: This tutorial is now outdated. I’m leaving it here for posterity, but please know that it may not work.

There are aspects to Cocoa that I find extremely obtuse and difficult to implement. I’m relatively new both to programming and Cocoa, and I suspect that others in the same boat also are frustrated by these steps. The single most frustrating simple thing that I have come across is implementing an NSOutlineView that connects to a Core Data model. There are several ways to approach this problem; primarily with or without Cocoa Bindings and with or without sorting.

There is a good, but outdated tutorial on how to make this work at this link: http://allusions.sourceforge.net/articles/treeDragPart1.php

The primary problem with the tutorials is that it requires the use of private Apple methods, which means that anything you build with it will not be accepted into the Mac App Store. This tutorial draws very heavily on that tutorial, with updated screenshots and code that does not use private APIs. The code also is difficult to read on that page, so it’s updated here in an easier-to-read format. Oh, and one more thing: the example on that page uses a feature of Interface Builder that no longer exists – subclassing within IB.

This tutorial is done with Xcode 3.2.5 on OS X 10.6.6.

The tutorial continues after the break…

Read the rest of this entry »

Written by Clay

February 13, 2011 at 09:31

Cocoa and Objective-C: Up and Running

leave a comment »

I spent the past 3 days reading and working through Cocoa and Objective-C: Up and Running, by Scott Stevenson. I own 5 or 6 “beginner” books about Cocoa and Objective-C. This is one of the better ones, with the condition that it is not for an absolute programming beginner.

Objective-C and Cocoa: Up and Running

There is a lot of theory at the beginning of the book. In fact, I believe it is not until chapter 8 that the first Cocoa / Interface Builder examples come into play. I was fatigued with theory by the time I reached that point, but was thankful for the background (especially the brief C primer) because most of the material is used in the Cocoa examples at some point.

There are a few spelling and code errors in the book, as is typical with programming books, but none of them were showstoppers. (There is one pesky error on p. 262… the line of code that reads @synthesize mainWindow; is not necessary and should be removed or the program will not compile.)

My primary disappointment with the presentation of the material is with the Gallery application in Chapter 9. This is the part where all of the concepts from chapters 1-8 come together. Instead of iteratively constructing the application so that it could be built successfully at checkpoints throughout the chapter, the application requires all of the code and interface builder elements in the chapter before it will compile. That’s a lot of code. It took me several hours to enter all of the code into Xcode. Sure, I know that the code is available online, but it helps me to understand it in context if I type it in while I’m reading it.

Wouldn’t you know, of course, that the application didn’t work when I finished the chapter. I sort of expected that, though, since I had to enter so much code before I could compile to check whether I was on the right track. I had a few small spelling errors that the compiler pointed out to me and I fixed. However, after the code successfully compiled, the application still didn’t work. The only indication of the problem was a cryptic line in the console. I suspected a code problem at first, so I reviewed all of it. The code was fine, so I turned to reviewing the .xib files associated with the application. By that point, I was tired and didn’t have the mental acuity to continue.

I sent an email to the author (via an address provided in the book) and he responded in a timely manner, instructing me to take a more careful look at the .xib files and offering to review my project for me. I appreciate that type of feedback. I thanked him but took to the .xib file and discovered where the error was. After a few minutes of hunting (thanks to the author for direction), I isolated the problem and the application ran.

The chapters that follow the Gallery application are of particular interest to me, about type and drawing. They were a little shallow in their presentation and left we wondering how to combine different graphics appropriately. I’ll have to look for another book to fill those gaps.

Overall, Cocoa and Objective-C: Up and Running is a good introduction to Mac programming for people with a little bit of previous programming experience. This is NOT a good book for an absolute beginner, but should work well for anybody with 4-6 months of experience with other languages under their belt. The book is loaded with material, making it a very good reference to have on hand, too.

Recommendation: Buy Now if you aren’t a total beginner. Buy Later if you need to learn basic concepts of programming first.

(For basics, I recommend Learning Processing, by Daniel Shiffman.)

Written by Clay

August 17, 2010 at 19:47

What I’m going to do

leave a comment »

There’s a theory that people are more likely to complete tasks that they announce publicly. I’m going to give that a shot. I’ve taught myself how to do a variety of beginner to intermediate things in a handful of programming languages. In fact, the most frequently visited posts on this blog are to the solutions that I posted to the Hillegass Cocoa book.

Working through books is both a plus and a minus to me. I get bored with the exercises because they rarely are meaningful — only small simple snippets to teach a concept. What I really would like is a full-fledged tutorial that goes from launching Xcode to completing an application of moderate complexity that serves a useful purpose. This tutorial would explain concepts as it went along; perhaps it would be more of a draw-by-numbers exercise than a standard programming tutorial.

Nevertheless, I have yet to find such a tutorial or book. I therefore am going to use the resources available to me to try to create a simple Cocoa application that serves a useful purpose (to me). Said application will generate population pyramids similar to those in the previous post. I hope to learn more about programming in Obj-C and Cocoa during the process. I’ll post my progress and results here and make the code available on github.

Written by Clay

August 12, 2010 at 17:52

Cocoa Programming for Mac OS X: Chapter 12 Challenge

with 10 comments

Pesky!

This is another challenge that is easy but can trip you up when you test it… The challenge reads:

Create a nib file with a custom About panel. Add an outlet to AppController to point to the new window. Also add a showAboutPanel: method. Load the nib by using NSBundle, and make AppController File’s Owner.

The easy part of this is that you don’t have to create a subclass like you did with PreferenceController. Read the bits about NSBundle and you’ll see that all you have to do is to modify the File’s Owner (AppController) and create the nib/xib file. That’s simple enough.

I initially didn’t understand the purpose of creating an IBOutlet for the About panel. After testing the application, I realized that the implementation of showAboutPanel: allowed for multiple panels to be opened.

Pesky! Read the rest of the post to see the code and instructions.

Read the rest of this entry »

Written by Clay

January 5, 2010 at 22:12

Posted in Cocoa, Code, Objective-C

Tagged with , , ,

Cocoa Programming for Mac OS X: Chapter 11 – Core Data – Depreciated Data Bindings

with 3 comments

Working through the Cocoa book, I successfully built and ran the example Core Data application. All was good until I noticed a build warning, “The ‘data’ binding is depreciated in Mac OS X versions 10.6 and later.” I looked at the discussion forum for the book (which isn’t much of a discussion forum – can’t provide links to other sites) and saw another mention of the problem. The issue comes from using the data binding on the Image Well, as described at the top of page 179 (in the 3rd edition of the book):

Bind the Data (not Value) of the image view to Cars. Choose the controller key selection and the keypath photo.

So, what’s the alternative that doesn’t use depreciated code? I don’t know for certain, but there’s discussion of it at the Mac Rumors forum. It may no longer be possible to create a Core Data application without writing code to implement a Value Transformer, if you want to convert from NSData to NSImage.

I’m sure there are good reasons behind codebase changes like this one. I look forward to understanding enough Obj-C and Cocoa to know what they are.

(Oddly, after doing nothing other than closing and reopening Xcode, I no longer get the build warning, which is even more confusing.)

Written by Clay

December 21, 2009 at 14:27

Posted in Cocoa, Objective-C

Tagged with , , ,

Cocoa Programming for Mac OS X: Chapter 8, Challenge 2

with 3 comments

This challenge is simple — type in the code provided, add the bindings in Interface Builder, and go…  that is, until the “make sure to add sorting!” comment at the end.

Sorting the RaiseMan application that does not use NSArrayController requires only a careful reading of the “For the More Curious: Sorting without NSArrayController” section in Chapter 8. The key sentence here, which I missed several times, is, “An optional table view dataSource method is triggered when the user clicks the header of a column with a sort descriptor:

There are a couple of things to notice and do:

1. tableView:sortDescriptorsDidChange: is a delegate method… so this means that you have to set MyDocument to be the delegate of the table view. Presumably you already did that if you set up the bindings correctly.

2. You need to enter the code that appears just above the “Challenge 1” header on page 135 into MyDocument.m – this is the delegate method called when you click the column header.

3. You cannot use the delegate method code as it appears in the book if you entered the code in Challenge 2, because you have a pointer to an IBOutlet object called tableView and this delegate method waits for a call from the interface element, not from your pointer, if that makes sense. Think about it this way — the flow of information happens in two directions: that coming in from the interface to the method, and that going from the method back to the interface. You’ll receive a compile warning if you call it tableView. Change it to aTableView. (You probably noticed similar changes in the code under Challenge 2.)  When referring to the incoming messages, those should be called aTableView. When referring to outgoing messages, those should be tableView because that is what your IBOutlet pointer is called. Therefore, the final line, [tableView reloadData] needs to remain tableView and not change to aTableView because you now want to call on the IBOutlet pointer to send instructions back to the interface.

4. The line [myArray sortUsingDescriptors:newDescriptors]; needs to contain the name of your array… employees. It should read: [employees sortUsingDescriptors:newDescriptors]; so that it sorts your array.

The final point tripped me up longer than any of the rest of it because I thought that the purpose of the exercise was to avoid using key coding. I was wrong. The point of the exercise is to not use NSArrayController. To sort your columns, you have to have sort descriptors. Those are entered in the same spot as in the previous challenge and the chapter exercise. In other words, when you have the name column in the table selected, the Interface Builder Table Column Attributes should look like this:

The same discussion about compare: vs. localizedStandardCompare: is valid here, so you can change it to the latter if you don’t want Z to appear before a when you sort. Look here for more info. The full code follows the break:

Read the rest of this entry »

Written by Clay

December 17, 2009 at 20:52

Posted in Cocoa, Code, Objective-C

Tagged with , , ,

Cocoa Programming for Mac OS X: Chapter 8, Challenge 1

with 13 comments

Alright! Another challenge where I knew exactly what I wanted to do and spent a lot of time wrestling with the interface.

The challenge is to change the sorting on the RaiseMan column to show the names in the order of the number of characters in them. The hint is to use a key path and the “length” method of strings. Seems straightforward. In code, to find the length of the personName string, I would simply write [personName length]. Let’s see…  key values, paths, selectors, etc…..  What??

The obvious thing to do here is to return to the previous chapter and read about key paths. Except, that doesn’t help at all and may lead to confusion. (I would reference my previous post about the confusion I experience when trying to migrate coding concepts to Interface Builder.)

There’s no point in drawing this out. The proper answer is simply to make the sort key personName.length and the selector to be compare:, like this:

You have to use compare: instead of caseInsensitiveCompare: because there is no case to an integer — no lowercase and/or uppercase to compare.

I tried several other approaches, including different Selectors, and the notation discussed in Chapter 7, such as “… valueForKeyPath@”personName.length];”. I think that my general lack of knowledge of C and my inexperience with Obj-C led me to try everything but the obvious. You see, the discussion of key paths in Chapter 7 only mentioned that they could be used to find attributes of objects. Length is, of course, an attribute of a string, but the challenge mentions length not as an attribute, but as a method of Strings. I took that to mean as a method of NSString. That returned me to the initial problem – how to return the value from [personName length] to the sort key.

In the end, I don’t think that this challenge is much of a challenge because I don’t recall ever learning that I could use a method with dot notation to return an attribute as a key path. My suggestion to the author would be to specifically mention this in the “For the More Curious: Key Paths” section of chapter 7, alongside the mention of “Properties and Their Attributes,” where the author specifically derides the dot syntax and says that he won’t be using it in the book.

Still, though, I haven’t crossed the mental bridge from length being a method and length being a property and/or attribute of NSString. It must be a getter method for NSString, and hence, works with the dot syntax? The Apple developer documentation states that length is a primitive method — does this mean it can be accessed as a getter method?

While I now know that I can use this syntax for strings, I have yet to find a description of why it works or how it applies to other classes and methods. The challenge, therefore, became a guessing game and the learning lesson became frustration.

Written by Clay

December 17, 2009 at 17:53

Posted in Cocoa, Code, Objective-C

Tagged with , , ,

Cocoa sorting: a brief detour

with 2 comments

One of my gripes with most of the programming books that I’ve read is that the early and ‘simple’ lessons about how to sort an array neglect multiple occurrences of the same word, capitalized differently. Cocoa Programming for Mac OS X, 3rd Edition is one of the books that ignores this point. Granted, I have no doubt the author is aware of the issue and easily could address it, but he chose not to in the text. Faced with a similar challenge in a Ruby programming book, I wrote a method that would properly handle such cases.

In the Cocoa book, Chapter 8 starts the reader on the development of the RaiseMan application. Sorting is implemented through a key path in Interface Builder, using the selector caseInsensitiveCompare:. It works great until you do the following:

Granted, the method used is caseInsensitiveCompare:. The documentation lacks a clear explanation of what this does. It sounds self-explanatory. Nevertheless, it annoys me. The first challenge at the end of the chapter is to implement a different type of sorting, using only Interface Builder. Prior to getting to that, I trolled through the documentation to find how to sort in a case sensitive manner. You might think that this would be called caseSensitiveCompare, but it’s not. I don’t know what the appropriate method to use here actually is, but I went with localizedStandardCompare: instead of caseInsensitiveCompare: and ended up with the following:

This is better, but shouldn’t the capitalized items appear before the lowercase items? That’s how it would appear in a dictionary, right? Also, what does localized mean in this context? Finally, why doesn’t the documentation include examples of how sorted/compared items will return? Including such examples would clarify all of this for me.

Therein lies my biggest problem with Cocoa so far. I understand Objective-C. I’m not an expert, by any means, but I get it and I can write foundation scripts without too much of a hassle. Cocoa isn’t clicking with me because I’m struggling to connect the dots between what I see in Interface Builder and what happens in code. For instance, caseInsensitiveCompare: and localizedStandardCompare: are methods. In code, I know how to call a method, how to pass it arguments, etc. Why are these methods called “Selectors” in Interface Builder? The sort key is personName, why isn’t the sort method caseInsensitiveCompare:? That would make more sense to me.

Chapter 8 in the Cocoa book is a deluge of unexplained Interface Builder instructions. Using NSArrayController as a controller object in the MVC framework makes sense but the steps for implementing it are difficult to grasp because what would be clear in written code becomes unclear when entered in separate text boxes in Interface Builder.

Practice makes perfect, I suppose. I’ll keep at it and I look forward to the “A Ha!” moment when it clicks and I can move forward without all of the hand holding.

Written by Clay

December 17, 2009 at 16:08

Posted in Cocoa, Code, Objective-C

Tagged with , ,

Cocoa Programming for Mac OS X Chapter 6: Challenge: Make a Data Source

with 2 comments

It’s been busy around here. I’ve started and stopped this challenge a few times over the course of a week, but finally returned to it yesterday evening. The time away from it actually made it easier. Armed with the knowledge that most of what I needed to know was in the chapter and that the challenge would be easier than the teachings in the chapter, I dove in and tried to keep it simple. I haven’t made it editable yet, but probably will tackle that tonight, since I think it will be simple. The final app looks like this:

Read the rest of this entry »

Written by Clay

December 15, 2009 at 13:58

Posted in Cocoa, Code, Objective-C

Tagged with , , ,

Cocoa Programming: Helper Objects – Challenge: Make a Delegate

with 15 comments

I am enjoying Cocoa Programming for Mac OS X ; good book, well written, pretty easy to follow. Chapter 6 (3rd edition) gets a bit ahead of itself, though. At least for programming newbies it does. Why? Well, the answer to “Challenge: Make a Delegate” is much better at explaining the concept than the examples used in the chapter. The interesting point about the delegate object is that it needs contain nothing other than the delegate method. That’s a far less complicated way to explain delegates than to shoehorn them into the previous projects that included IBOutlets, IBActions, etc. Here’s the skinny:

ALL you need to do is:
1. Start a new Cocoa project
2. Create a new Obj-C class. I’ll use the name WindowTalker.
3. in WindowTalker.h, add the following (which is the sample code from the book):

#import <Cocoa/Cocoa.h>

@interface WindowTalker : NSObject {
}

- (NSSize)windowWillResize:(NSWindow *)sender
					toSize:(NSSize)frameSize;
@end

4. In WindowTalker.m, add the following (which is simpler than the example code in the book):

#import "WindowTalker.h"

@implementation WindowTalker

- (NSSize)windowWillResize:(NSWindow *)sender
					toSize: (NSSize)frameSize
{
	frameSize.width = frameSize.height * 2;
	NSLog(@"The window size is %f wide and %f tall.", frameSize.width, frameSize.height);
	return frameSize;
}

@end

5. Save the files – you’re done with the code.
6. Double-click on MainMenu.xib (or .nib)
7. Click on the header of the window to select it. Go to the inspector and set the size to 200 x 400 or something else in that ratio.
8. Drag a blue object cube to the Doc window.
9. In the inspector panel, set the identity of the blue cube to “WindowTalker” or whatever you named your class.
10. Control-click on the window (that will resize) to get the connections panel. Here you need to tell the Window that the object is its delegate. Herein lies the entire point of this exercise… That object is going to act as the servant to the window to accomplish the proportional resizing. Hence, the window needs to know which object is its servant, aka delegate. So…
11. Drag from the circle next to delegate on the connections panel for the window and release the line on top of the WindowTalker object in the Doc window.
12. Save MainMenu.xib
13. Build and Run your application. Test by dragging the window.

The dragging part in step 11 will look something like this:

Dragging from the connections panel to the blue cube - the mouse is over the blue cube, ready to release

I read through the chapter and followed the instructions and was still forming my idea of what the delegate was when I came to this exercise. My first few shots at it were too complicated – I was trying to do way too much. The concept of the delegate was much clearer to me after I figured this out, so perhaps someday this post will help somebody with the same problem.

Written by Clay

December 4, 2009 at 21:37

Posted in Code, Objective-C

Tagged with , ,

Successfully completed my first solo Cocoa “challenge”

leave a comment »

Written by Clay

December 4, 2009 at 01:42

Posted in Code, Objective-C

Tagged with , ,

Getting back up to speed

leave a comment »

Wow, the flu really knocked me out for about 2 weeks. Tack Thanksgiving and an increased workload onto that and I’ve been away for far too long. I am, however, getting back up to speed. I’ve been working through several of the chapters in “Cocoa Programming for Mac OS X” to get a flavor for whether I would like to pursue Obj-C / Cocoa further. It’s a great book, but there are some inconsistencies with Snow Leopard and the screenshots are from an old version of Xcode, which seems to have moved a good number of option buttons around in the Preferences, etc. My only other concern is that some of the Obj-C used in the book is depreciated by Apple, or so it would appear when I try to look it up in the developer documentation. The code compiles and runs, so I’m not that worried about it, but I would prefer to use the currently accepted code/methods than the depreciated ones. Nevertheless, I’m enjoying it and would love to take the Cocoa for Beginners class at BNR.

If anybody reading this has thoughts about the book and code depreciation, I would love to hear them. I suppose it’s time for a Fourth Edition.

depreciated code?

Written by Clay

December 3, 2009 at 19:46

Posted in Code

Tagged with , ,