How to approach programmatically creating view objects?
I am building a simple game for 2-4 players in Coco开发者_开发技巧a. This is my first Cocoa app, so not being familiar with the libraries, I am probably doing a lot of weird things. If you see anything that could be done better, just say so.
The first step requires user to choose number of players from NSPopUp and that data is pulled into an int. I create an array and loop in a number of player objects.
- (IBAction)startGame:(id)sender {
// Get value of playersPopup into a string
NSString *playersReturn = [[NSString alloc] initWithString:[playersPopup titleOfSelectedItem]];
// Convert that string to an int
numberOfPlayers = [playersReturn intValue];
// Create an array
playerArray = [[NSMutableArray alloc] init];
// Create a counter
int i = 0;
// While counter is less than number of players, create player object and add to array
while (i < numberOfPlayers) {
// Create a player object
Player *player = [[Player alloc] init];
// Add player to array
[playerArray addObject:player];
// Increment
i++;
}
}
It's a bit weird because all the objects have the same name. I'm not sure how to programmatically give the objects a title using the counter like player1, etc, but its easy enough to pull them by key from the array with objectAtIndex. That would be part 1 of my question: in Cocoa how do I use the counter in naming the objects? Because from what I gather if I did:
player *player[i] =
it would create arrays of that object when all I want to do is call it player1 etc.
Second question is: I have another view where, after the player objects are created, user sees NSTextFields to input names for the players. Given that I should declare the IBOutlets in the AppDelegate, I'm not sure how to provide for a range 2-4 players. I can declare all 4 outlets and just use two, and then just programmatically hide unused textfields. But it seems like there ought to be a way to just create the outlets and view objects based on how many players has been selected. I mean I have that int for the whole AppDelegate so I should use it somehow.
If someone wouldn't mind pointing me a good direction, that would be awesome! I really enjoy programming in Cocoa, but it's kind of a different world at this point. I knew there would be a learning curve, but it's just really different from .net!
Thanks guys!
-Alec
It's a bit weird because all the objects have the same name. I'm not sure how to programmatically give the objects a title using the counter like player1, etc, but its easy enough to pull them by key from the array with objectAtIndex. That would be part 1 of my question: in Cocoa how do I use the counter in naming the objects?
You don't. Except for a few classes that provide API specifically for naming the object (e.g., NSThread), there is no way to name an object.
What you're talking about is declaring variables, which hold pointers to objects. These variables are separate from the objects themselves; you can even have multiple variables all pointing to the same object. Naming a variable does not affect anything about the object it may point to.
Because from what I gather if I did:
player *player[i] =
it would create arrays of that object when all I want to do is call it player1 etc.
No, it would declare a variable named player
as holding a C array of i
pointers to player
objects. It would also be hairy if not invalid, since you're using the name player
for two different things (a class and a pointer variable).
Suppose you got your wish, and could create a bunch of variables named player0
, player1
, player2
, etc. How would you work with all of them? More to the point, how would you work with each of them? How would you give each view a different player? How would you lay out each view into a different place? How would you send messages to a single specific view that needs updating?
The correct solution to your problem is a second NSMutableArray: This one, of views. Put the views into that array just as you put the model objects into the players array. You can maintain the arrays such that each index refers to a model object in one array and the corresponding view in the other array—so, for example, if you receive an action message, you'd look up the index for that view in the views array, then get the model object by that index in the players array to respond to the action.
A more robust variation of that solution, but also more work, would be to loop over the array of views searching for one that has a specific player. This solution wouldn't require them to have the same order, and would enable you to handle the (shouldn't-happen) case of a player view whose player has gone missing from the model array. But, as I said, it's more work—both for you and for the program (i.e., it's slower). I'd probably just do the parallel array.
I mean I have that int for the whole AppDelegate so I should use it somehow.
You don't need it.
For one thing, it's the wrong type. The correct type for indexes into and counts of NSArrays is NSUInteger
.
More importantly, once you have added all the players, that number contains the number of players. You can obtain that information almost as easily by sending the players array a count
message. If you maintain separate knowledge of how many players you have, it's one more thing that can go wrong, by your adding or removing a player and forgetting to update your own count variable.
Cut out that variable. When you need to know how many players you have, just ask the array.
As for limiting how many players you add: Copy the number of players to a local variable, and count it down. When it reaches zero, you've added all the players you need to. Alternatively, you could cut that out, too, add two players to start with, and enable the user to add as many other players as they want.
精彩评论