Adding a Preferences Window to Your Application
Pages: 1, 2, 3, 4, 5, 6, 7
At this point awakeFromNib looks like the following:
- (void)awakeFromNib
{
NSBundle *bundle;
NSString *path;
NSArray *identifiers;
NSArray *checkBoxesArray;
prefs = [[NSUserDefaults standardUserDefaults] retain];
tableColumns = [[NSMutableDictionary alloc] init];
recordsFile = [NSString stringWithString:@"~/Library/Preferences/AddressBookData.plist"];
recordsFile = [[recordsFile stringByExpandingTildeInPath] retain];
if ( [prefs arrayForKey:@"Addresses"] != nil )
records = [[NSMutableArray alloc] initWithArray:[prefs arrayForKey:@"Addresses"]];
else if ( [[NSFileManager defaultManager] fileExistsAtPath:recordsFile] == YES )
records = [[NSMutableArray alloc] initWithContentsOfFile:recordsFile];
else
records = [[NSMutableArray alloc] init];
// Load the identifiers array from the bundle resources
bundle = [NSBundle mainBundle];
path = [bundle pathForResource:@"Identifiers" ofType:@"plist"];
identifiers = [[NSArray alloc] initWithContentsOfFile:path];
// create the check boxes dictionary to easily refer to controls in prefs window
checkBoxesArray = [NSArray arrayWithObjects:firstNameCB, lastNameCB, emailCB, homePhoneCB, workPhoneCB, mobilePhoneCB, nil];
checkBoxes = [NSDictionary dictionaryWithObjects:checkBoxesArray forKeys:identifiers];
[self addInitialColumnsForIdentifiers:identifiers];
if ( [prefs arrayForKey:@"User Columns"] != nil ) {
userColumns = [[NSMutableArray alloc] initWithArray:[prefs arrayForKey:@"User Columns"]];
[self initializeTableWithColumns:userColumns];
} else {
userColumns = [[NSMutableArray alloc] init];
[firstNameCB setState:NSOnState];
[lastNameCB setState:NSOnState];
[emailCB setState:NSOnState];
[homePhoneCB setState:NSOnState];
}
}
Finally, implement 'setColumn'
With the first two parts of our strategy in place, we can now easily add and remove columns in response to the user changing the preferences, and have these changes preserved in the user's preferences. All of this is done in the method setColumn. Since we didn't create new Controller files from Interface Builder, we have to add setColumn by hand. Let's look for a moment at this method to gain a clearer idea of how we're going to proceed with this implementation.
The method definition should be added to Controller.m:
- (IBAction)setColumn:(id)sender
{
}
Recall how we connected six different buttons to this single action message. The idea is that whenever the user switches one of those preference check boxes, setColumn will be invoked, and we'll be able to identify which check box was changed given the information provided in the sender argument, and thus determine which table column to add or remove. The distinguishing characteristic of the sender object that allows us to do this is the title of the button, which we've conveniently made to be the same as all of the column identifiers, which are also the same as the keys in the tableColumns dictionary! We can get the title string by sending a title message to the sender, and then we can store this string in a local variable, identifier:
NSString *identifier = [sender title];
Once we have the name of the column we're working with, we need to determine whether we should remove the indicated column or add it to the table view; this depends on the state of the button after it has been clicked. Check boxes have two possible states by default: NSOnState and NSOffState. We can obtain the state of the sender check box by sending it a state message, whose return value we can compare to the constants NSOnState and NSOffState to determine our course of action. After putting all of these pieces together, here is the implementation of setColumn:
- (IBAction)setColumn:(id)sender
{
NSString *identifier = [sender title];
NSTableColumn *column = [tableColumns objectForKey:identifier];
if ( [sender state] == NSOnState ) {
[tableView addTableColumn:column];
[self saveTableColumnPrefs];
} else if ( [sender state] == NSOffState ) {
[tableView removeTableColumn:column];
[self saveTableColumnPrefs];
}
}
So in the first line of this method we took the title of the sender button, and stored it in the NSString variable identifier. In the next line, we declare a temporary NSTableColumn variable, column, which we assign to the object returned from tableColumns that has the key-matching identifier.
Finally we check to see what the state of the check box is after the user has clicked it. If it is NSOnState, then we add the column to the tableView, and if it is NSOffState, we remove the column from the table view. The second if statement is actually a little redundant -- it could have just been an else statement because if it's not in NSOnState, then it must be NSOffState. However, I prefer the more explicit version -- just a personal preference.
Final thoughts
With that the basic framework of adding and removing columns both at start up based on saved preferences, and during runtime based on changing preferences is set. In the end, we have added five methods to our application, and we have extensively modified awakeFromNib. These five methods are:
addColumnForIdentifer:addColumnsForIdentifiers:initializeTableWithColumns:setColumnsaveTableColumnPrefs
The project folder for the final application in this column can be downloaded here.
As a final bit of housekeeping in this column, you should go into the dealloc method and add any necessary releases to the instance objects we've created and used.
|
|
This code will add and remove the columns, almost like we want it to. There are several things about this implementation that makes it incomplete in the sense that we're not going to get a good-looking table out of this. Primarily this is because the code does not take into account the widths of the columns If we fix this, then our setup could be quite good.
An obvious first enhancement to this code would be to store in user defaults more information than just a list of columns. We could instead store an array of dictionaries, where each dictionary has the potential to describe in detail how the user has each column configured.
For example, this dictionary could have a key named @"Identifier" that returns the identifier string of the column (which is the information contained in our original list). A second possible key that would greatly enhance the looks of our table is a key @"Width", which would allow us to store and restore the widths of the columns. The possibilities of further attributes to store go on. We could have a key-value pair to store how text should be aligned in the title or the column, or we could have another key-value pair that stores a Boolean, which might indicate whether a column should be editable. I leave the addition of these features to the reader. The source code for the next column will show my solution to this issue.
Speaking of the next column, we will be learning how to enhance our interface using that wonderful Mac OS X innovation -- sheets. See you next time!
Michael Beam is a software engineer in the energy industry specializing in seismic application development on Linux with C++ and Qt. He lives in Houston, Texas with his wife and son.
Read more Programming With Cocoa columns.
Return to the Mac DevCenter.
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 24 of 24.
-
Column Width
2004-02-01 18:03:47 wkanoff@cablespeed.com [Reply | View]
Does anyone know how to set thee column width when you insert a new column?
-
Question about opening windows
2002-08-09 14:45:32 uglyface [Reply | View]
I'm trying to write an application which has more than one window in it. I want a certain button to open a window, but unfortunately I can't get that to work. I've tried several different things:
[setupWindow makeKeyAndOrderFront:self];
[setupWindow makeKeyAndOrderFront:nil];
[setupWindow makeKeyAndOrderFront:setupWindow];
[setupWindow makeKeyAndOrderFront];
I have setupWindow defined as:
IBOutlet id setupWindow;
This is the outlet that I created by dragging the wire from the instantiated object to the window bar that has the close, miniaturize, and make big buttons on it.
Another peculiarity is that I have to define setupWindow in the file that I need to use it in. For some reason, importing the header file doesn't seem to work.
If you wish to reply to this, please e-mail the reply to robinson.6642osu.edu, thank you. By the way, this is the best Cocoa tutorial I have seen yet. The tutorials provided by Apple are too simple, and are in .pdf form. I really hate .pdf files.
-
Java Version - Solution
2002-06-02 18:55:49 jsumnertx [Reply | View]
As with the other examples, here's my java solution.
1) One thing that got me in this one is that you can (and need to have) awakeFromNib(). Previously, I was doing all of the work in the object constructor but I moved it to awakFromNib so there would be access to the preference panel checkbox objects.
2) Interestingly, in order for awakeFromNib to be called, the controller must inherit from NSObject, not Object. So, I had to change things to use Object (btw, you can do a copy and paste of a class in Interface Builder.. That helped)
So, here's the new code.
/* Controller */
import com.apple.cocoa.foundation.*;
import com.apple.cocoa.application.*;
public class Controller extends NSObject {
NSTextField emailField; /* IBOutlet */
NSTextField firstNameField; /* IBOutlet */
NSTextField lastNameField; /* IBOutlet */
NSTextField homePhoneField; /* IBOutlet */
NSTextField mobilePhoneField; /* IBOutlet */
NSTextField workPhoneField; /* IBOutlet */
NSButton emailCB;
NSButton firstNameCB;
NSButton lastNameCB;
NSButton homePhoneCB;
NSButton mobilePhoneCB;
NSButton workPhoneCB;
NSTableView tableView; /* IBOutlet */
NSMutableArray records;
NSUserDefaults prefs;
NSMutableDictionary tableColumns;
NSDictionary checkBoxes;
String recordsFile;
String kIdentifierArray[]={"First Name", "Last Name", "Email", "Home Phone", "Work Phone", "Mobile Phone"}; // NOT null-terminated. Uses java Strings
NSMutableArray userColumns;
// Controller()
void awakeFromNib()
{
prefs = NSUserDefaults.standardUserDefaults();
tableColumns = new NSMutableDictionary();
recordsFile = "~/Library/Preferences/AddressBookData.plist";
recordsFile = NSPathUtilities.stringByExpandingTildeInPath(recordsFile);
java.io.File rf=new java.io.File(recordsFile);
if (prefs.arrayForKey("Address")!=null)
records = new NSMutableArray(prefs.arrayForKey("Address"));
else if (rf.exists()==true)
records = new NSMutableArray(readFileIntoArray(recordsFile));
else
records = new NSMutableArray();
// NSArray identifiers=new NSArray(kIdentifierArray);
NSBundle bundle=NSBundle.mainBundle();
String path=bundle.pathForResource("Identifiers","plist");
NSArray identifiers=readFileIntoArray(path);
String identarray[]=new String[identifiers.count()];
identifiers.getObjects(identarray);
NSButton kButtonArray[]={firstNameCB, lastNameCB, emailCB, homePhoneCB, workPhoneCB, mobilePhoneCB};
checkBoxes=new NSDictionary(kButtonArray, identarray);
this.addInitialColumnsForIdentifiers(identifiers);
if (prefs.arrayForKey("User Columns") !=null){
userColumns = new NSMutableArray(prefs.arrayForKey("User Columns"));
this.initializeTableWithColumns(userColumns);
}
else {
userColumns=new NSMutableArray();
firstNameCB.setState(NSCell.OnState);
lastNameCB.setState(NSCell.OnState);
emailCB.setState(NSCell.OnState);
homePhoneCB.setState(NSCell.OnState);
}
}
NSArray readFileIntoArray(String path)
{
NSArray loadedRecords=null;
try{
java.io.File file = new java.io.File(path);
NSData data = new NSData(file);
loadedRecords = (NSArray)NSPropertyListSerialization.propertyListFromXMLData(data);
}
catch (Exception e)
{
loadedRecords=null;
}
return loadedRecords;
}
public void initializeTableWithColumns(NSArray identifiers)
{
NSTableColumn column;
String identifier;
java.util.Enumeration e=tableView.tableColumns().objectEnumerator();
while ((column=(NSTableColumn)e.nextElement())!=null){
tableView.removeTableColumn(column);
}
e=identifiers.objectEnumerator();
while ((identifier=(String)e.nextElement())!=null){
column=(NSTableColumn)tableColumns.objectForKey(identifier);
tableView.addTableColumn(column);
NSButton button=(NSButton)checkBoxes.objectForKey(identifier);
button.setState(NSCell.OnState);
}
}
public void addInitialColumnForIdentifier(String identifier)
{
NSTableColumn newColumn;
newColumn = new NSTableColumn();
newColumn.setIdentifier(identifier);
newColumn.headerCell().setStringValue(identifier);
newColumn.headerCell().setAlignment(NSText.CenterTextAlignment);
newColumn.headerCell().setEditable(true);
tableColumns.setObjectForKey(newColumn, identifier);
}
public void addInitialColumnsForIdentifiers(NSArray identifiers)
{
// uses java enumerator
java.util.Enumeration e=identifiers.objectEnumerator();
String identifier;
while ((identifier=(String)e.nextElement())!=null){
this.addInitialColumnForIdentifier(identifier);
}
}
public NSDictionary createRecord()
{
NSMutableDictionary record = new NSMutableDictionary();
record.setObjectForKey(firstNameField.stringValue(), "First Name");
record.setObjectForKey(lastNameField.stringValue(), "Last Name");
record.setObjectForKey(emailField.stringValue(), "Email");
record.setObjectForKey(homePhoneField.stringValue(), "Home Phone");
record.setObjectForKey(workPhoneField.stringValue(), "Work Phone");
record.setObjectForKey(mobilePhoneField.stringValue(), "Mobile Phone");
firstNameField.setStringValue("");
lastNameField.setStringValue("");
emailField.setStringValue("");
homePhoneField.setStringValue("");
workPhoneField.setStringValue("");
mobilePhoneField.setStringValue("");
return record;
}
public void addRecord(Object sender) { /* IBAction */
records.addObject(createRecord());
tableView.reloadData();
saveData(records);
}
public void setColumn(NSButton sender) {
String identifier=sender.title();
NSTableColumn column=(NSTableColumn)tableColumns.objectForKey(identifier);
if (sender.state()==NSCell.OnState){
tableView.addTableColumn(column);
saveTableColumnPrefs();
}
else if (sender.state()==NSCell.OffState){
tableView.removeTableColumn(column);
saveTableColumnPrefs();
}
}
public void deleteRecord(Object sender) { /* IBAction */
if (tableView.numberOfSelectedRows() == 0)
return;
NSApplication.beep();
int status = NSAlertPanel.runAlert("Warning!", "Are you sure you want to delete the selected record(s)?", "OK", "Cancel", null);
if ( status == NSAlertPanel.DefaultReturn ) {
NSMutableArray tempArray = new NSMutableArray();
NSEnumerator enumerator = tableView.selectedRowEnumerator();
Integer item;
item = (Integer)enumerator.nextElement();
while ( item != null ) {
tempArray.addObject(records.objectAtIndex(item.intValue()));
item = (Integer)enumerator.nextElement();
}
records.removeObjectsInArray(tempArray);
tableView.reloadData();
saveData(records);
}
}
public void insertRecord(Object sender) { /* IBAction */
int index = tableView.selectedRow();
if (index >= 0)
records.insertObjectAtIndex(createRecord(), index);
else
records.addObject(createRecord());
tableView.reloadData();
saveData(records);
}
public int numberOfRowsInTableView(NSTableView aTableView){
// I had to add this check because this method was getting
// called before awakeFromNib for some reason
if (records!=null)
return records.count();
else
return 0;
}
public Object tableViewObjectValueForLocation( NSTableView aTableView, NSTableColumn aTableColumn, int rowIndex){
NSDictionary theRecord;
Object theValue=null;
theRecord = (NSDictionary)records.objectAtIndex(rowIndex);
if (theRecord!=null)
theValue = theRecord.objectForKey(aTableColumn.identifier());
return theValue;
}
private void saveData(NSArray records)
{
this.saveArrayToFile(records, recordsFile);
prefs.setObjectForKey(records, "Address");
prefs.synchronize();
}
private void saveArrayToFile(NSArray array, String filename)
{
try
{
java.net.URL fileURL=NSPathUtilities.URLWithPath(filename);
NSData data = NSPropertyListSerialization.XMLDataFromPropertyList(array);
data.writeToURL(fileURL, true);
}
catch (Exception e)
{
// put up a dialog
int status = NSAlertPanel.runAlert("Warning!", "Unable to save data", "OK", null, null);
}
}
private void saveTableColumnPrefs()
{
NSTableColumn column;
java.util.Enumeration e=tableView.tableColumns().objectEnumerator();
userColumns.removeAllObjects();
while ((column=(NSTableColumn)e.nextElement())!=null)
{
userColumns.addObject(column.identifier());
}
prefs.setObjectForKey(userColumns,"User Columns");
}
}
-
Java Version - Solution
2003-08-30 15:46:48 anonymous2 [Reply | View]
Who wants your Java? Why can't you learn and use Objective-C, please? Must we continue to put up with your pretentiousness? -
Java Version - Solution
2004-01-01 01:56:57 anonymous2 [Reply | View]
I would not consider myself to be ultra-efficient in objective-c, but I would at least be able to transfer the java over to objective-c because it is quite similar in many ways. So, the java solution is fine to me. Figure it out...
-
Avoid insertion of empty record
2001-12-29 19:09:15 michele [Reply | View]
In order not to insert an empty record, I've inserted the following statements at the beginning of insertRecord:
// Check if the new record is not empty
if ( ([[firstNameField stringValue] isEqualToString: @""]) &&
([[lastNameField stringValue] isEqualToString: @""]) &&
([[emailField stringValue] isEqualToString: @""]) &&
([[homePhoneField stringValue] isEqualToString: @""]) &&
([[workPhoneField stringValue] isEqualToString: @""]) &&
([[mobilPhoneField stringValue] isEqualToString: @""]) )
{
return;
}
-
Avoid insertion of empty record
2003-08-30 15:50:51 anonymous2 [Reply | View]
Cute, but too lugubrious. Use length and the logical or || operator. Will cost less code and will execute much faster. You've got && throughout your snippet - meaning the machine HAS to go through and evaluate each one.
Besides, your logic is upside down. You are checking for what you DON'T want to find, instead of what you DO want to find.
Make your logid aright. THIMK a bit. ;P
-
Clear Fields
2001-12-29 19:07:04 michele [Reply | View]
I've added the following function, so that the fields are cleared after adding and inserting a new entry:
- (void) clearField
{
[firstNameField setStringValue:@""];
[lastNameField setStringValue:@""];
[emailField setStringValue:@""];
[homePhoneField setStringValue:@""];
[workPhoneField setStringValue:@""];
[mobilPhoneField setStringValue:@""];
}
The function is called at the very end of addRecord and insertRecord. Thus, there is no empty entry added.
-
confounded
2001-12-15 16:47:17 blueskyz [Reply | View]
Great series so far. I wish I hadn't gotten off to such a late start. Hope you're checking back here. Don't want to go to next article until I'm good-to-go here.
I, too, am getting the error:
2001-12-15 16:25:11.050 AddressBook[1775] *** -[NSCFArray addObject:]: attempt to insert nil
I've looked all over (yeah right!) and can't find where i'm not synched with my names. I'm betting that's my problem.
Can you outline for me where I should have names that match. They seem to match everywhere I've looked.
Can't figure out the debugging process so I'm unable to narrow down the problem.
Thanks.
-Phil -
confounded
2001-12-29 19:14:11 michele [Reply | View]
Check for the following statement near the end of awakeFromNib:
checkBoxesArray = [NSArray arrayWithObjects:firstNameCB, lastNameCB, emailCB, homePhoneCB, workPhoneCB, mobilePhoneCB, nil];
You notice that there is a:
mobilePhoneCB
in the array, but the name in Interface Builder and in the propertyList is:
mobilPhoneCB (no e).
Change this ant it'll work.
-
other types of preferences
2001-10-29 17:02:34 dhuntsin [Reply | View]
This article was very helpful in setting up a preferences window, and in showing how to handle preferences stored as Strings, but what about a more simple example, using other types of preferences.
For instance, what if I had a simple preference panel that stored an int and a BOOL. I am fairly new to XML, so what would the XML look like. Also, how would my awakeFromNib differ from the method in the above example?
Thanks! -
other types of preferences
2003-08-30 15:55:33 anonymous2 [Reply | View]
Don't worry about the XML. Plist XML stores data as dictionaries - look inside one for yourself. All you need to (and should) do is interface with NSDictionary and NSMutableDictionary. Check those two classes out and most of your questions will be answered. Cheers.
About this tutorial: Personally I think readers would rather see a tutorial on how to create those new fangled prefs boxes we see in Mail and Safari.
-
address book lost functionality in pb10.1
2001-10-04 23:01:30 psheldon [Reply | View]
Entered into table fields with double click, typing and enter key gesture and then quit . There wasn't an automatic save on enter . Whazah? Wait . I used Mike's code to start clean on the last column . Maybe, I thought, the flaw losing functionality was in the last code before the column . I tried my code that had worked and it still misbehaved .
Well, I want to see the next column and so may start clean with new code from Mike so I don't stray too far . That means he'll have to debug his code in the new project builder . The old project builder doesn't work anymore and new project builder is supposed to work with old source , but didn't . I hope Mike and Oreilly guys got their 10.1 project builder earlier than me so I can have that column soon .
;-)
-
only lost functionality in pb10.1
2001-10-04 23:09:04 psheldon [Reply | View]
The old built ap worked .
I had controlled experiments where I copied project folders and then rebuilt in those copied folders. The original folders had ap in the build subfolder and that worked (directory environment to save in hadn't changed) . So project builder changed .
-
integrated class browser
2001-10-04 09:22:01 psheldon [Reply | View]
http://developer.apple.com/devnews/
In item [11] indicates an integrated class browser and I wonder whether this will be over and beyond help with its links and what beyond would mean . I've seen a class browser in Apple's object oriented pascal and, as I vaguely recall, it looked like what we see in interface builder . What one would mean in project builder , I don't know .
I could imagine over and beyond , eg. popups at class names that launch help pages or ways of taking notes in code to make these popups to help pages, perhaps your own help pages, normal pasting from help pages without using internet explorer rather than the help ap.
-
integrated class browser observed
2001-10-04 22:27:27 psheldon [Reply | View]
My developer cd finally came in and , when I read the pdf file , I learned that the integrated class browser was something new for 10.1, no remention of that in interface builder . A classes tab discloses a hierarchy of classes in your program. It looks like a bunch of headlines with disclosure triangles. Click on any headline and you get to the top line of that class description in header files. Apple has commented those top lines! There was other hypertext stuff . It looked like the help viewer without the search window was right in the project builder with a popup button showing you where you have been in both text and html , ie. bookmarks . Also, there was code warrior type of popup bookmarks to the tops of your procedures and methods in your current file.
-
Uncaught Exceptions! Help!
2001-09-22 21:17:50 kperry8 [Reply | View]
OK, I've compared my code to the your downloaded example, and its nearly identical from what I can tell, except for minor style differences. However, I always get the following errors when I try and run the app:
AddressBook[1384] An uncaught exception was raised
AddressBook[1384] *** -[NSCFArray addObject:]: attempt to insert nil
AddressBook[1384] *** Uncaught exception: <NSInvalidArgumentException> *** -[NSCFArray addObject:]: attempt to insert nil
AddressBook.app has exited with status 255.
I used the debugger and this is where the exception occurs:
(This is part of the -initializeTableWithColumns method)
// add columns from the argument array
e = [identifiers objectEnumerator];
while ((identifier = [e nextObject])) {
column = [tableColumns objectForKey:identifier];
[tableView addTableColumn:column]; <--ERROR HERE
[[checkBoxes objectForKey:identifier] setState:NSOnState];
}
Can someone help me? Thanks! -
Uncaught Exceptions! Help! bug feedback
2001-09-26 14:05:52 psheldon [Reply | View]
There is this NS alert procedure written in the apple speech synthesis example, I believe. It is supposed to give information when something there goes wrong. You could easily modify it for your code to see if what Mike Beam suggests is correct .
The senior programmer with the joke taught me about such an IDebug procedure I could make on another programming platform, Data Generals AOS, long ago . -
Uncaught Exceptions! Help!
2001-09-25 20:04:51 Michael Beam |
[Reply | View]
right off the bat it looks as though the error actually lies in the tableColumns dictionary. That is, for some identifier there is not a key for it in tableColumns and nil is returned by
[tableColumns objectForKey:identifier]
You might want to double check that all of you identifiers and table column names, etc are all the same. If you're still having problems post back and i'll scratch my head some more...
Mike -
Uncaught Exceptions! Help!
2001-09-25 13:43:52 psheldon [Reply | View]
I started drafting a reply that wasn't much help.
Maybe my writing will get better and more inspirational if I look at it for several days. I don't know .
I had a senior programmer who once said "you whine and complain when your compiler gives you little information in your syntax errors, wait until you have problems like mine" . She then grimaced and said what her problems were , execution errors involving fundamental theory and being so good that she was constantly assigned to debug other people's programs and downgrade languages to make things readable for them .
This wasn't an answer to my ambitions, but if I tried real hard I realized that she was making a joke to make things a bit easier to take .
;-)
-
please refine my cocoa semantics
2001-09-22 19:02:30 psheldon [Reply | View]
Well , I have finished this column . It was a long time until I could try "letting the hammer fall" and compiling . Because of the extreme modularity of the code , I rapidly got through my typos and omissions . That was an experience ! Hey , I have learned wisdom here !
Item 1 :
p.5 wrote - (void)setColumn:(id)sender;
should it not instead read , as it did p.16
- (IBAction)setColumn:(id)sender;
is there a difference ?
Item 2 :
p.16
NSTableColumn *column = [tableColumns objectForKey:identifier];
Does this really mean :
(NSTableColumn *) column = [tableColumns objectForKey:identifier];
* is not actually an operator to right on column (acting before assignment) ,
it actually acts to the left on NSTableColumn to make that a pointer to NSTableColumn
(acting again before assignment)
and the assignment is then pass by reference :
column = [tableColumns objectForKey:identifier];
Item 3 :
In addition, is the first entity of any [], that is "a" of [a b], always a pointer ?
-
please refine my cocoa semantics
2001-09-25 20:00:52 Michael Beam |
[Reply | View]
Item 1:
IBAction is actually the same as void, so they're _somewhat_ interchangeable, although in my case it was a slip up in this monster of a column. IBAction as a data type is actually used so that Interface Builder can parse headers that you create. That is, if you create a class header that contains all of your outlets and actions, you can drop that into you nib file window in IB, and IB will create a new class based on your header with all of the appropriate outlets and actions. It knows which items are outlets and which are actions by the IBAction and IBOutlet "tags"
Item 2:
Yes, the * is part of the data type, not the variable name. It indicates that the variable is a pointer to whatever type of object is indicated.
Item 3:
and yes, as far as i know and in my experience, "a" is always a pointer since that i how we work with objects in Objective-C. If anyone know a case where this is not true, please share it with us!
Hope that helps!
Mike -
please refine my cocoa semantics
2001-09-26 14:08:16 psheldon [Reply | View]
Thanks. -
please refine my cocoa semantics
2001-09-27 07:50:56 Michael Beam |
[Reply | View]
You're welcome






