0

i'm building an app in Xcode where there are a 81 textviews in the NIB, each with a sequential name, so box1, box2, box3, box4 etc.

When doing data manipulation i want to be able to use the data in each box to add to an array for example. What i would like to be able to do is put this in a loop, so for example something like:

NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i=1; i<82; i++) {
    [array addObject: [Indirect("box" & i).text];
}

Similarly when outputting back to the textviews, i want to be able to loop from the array rather than referring to each textview independently. so something like:

for (int i=1; i<82; i++) {
    indirect("box" & i).text = [array objectAtIndex:i];
}

Any ideas? Sorry if this is obvious - fairly new to the game.

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
  • 1
    Not an Xcode question. It's really a question about developing using the Cocoa framework. – Almo Apr 26 '12 at 13:34

3 Answers3

1

Consider the MVC design pattern. Your calculation shouldn't be based directly off the views (the UI) but rather off some state in the controller, which is set by the views. Each time a field is edited, it notifies your controller via target/action or via Cocoa Bindings. When that happens, the controller updates your data model (in your case, that means it updates the computation and probably reflects the result in another part of the UI - the "total" field).

Joshua Nozzi
  • 60,946
  • 14
  • 140
  • 135
  • Sorry, i don't see the relevance. The user inputs values into the textview which then need to be manipulated and then resent to the same textviews. If it was just one text view then you would just do something like: int i = [NSNumber numberWithInt: [[box1 text] intValue]]; int j = i*2; box1.text = [NSString stringWithFormat:@"%d", j]; But i have 81 similar textviews - i don't want to have to do this manipulation 81 times.... – user1358791 Apr 26 '12 at 15:33
  • 1
    @user1358791: The relevance is that you should not be using views as data storage. The controller is the object that should directly own the strings/numbers/whatever, not have to fetch them from a specific set of views when it needs them. How many views you have is irrelevant, and nobody is suggesting that you write 82 separate assignment statements. – Peter Hosey Apr 26 '12 at 16:44
1

In Cocoa, there are two ways to do it:

  1. Add all of the fields to an array in awakeFromNib. Enjoy writing 82 addObject: messages.
  2. Remove the fields from the nib and create them in a loop in code, adding each one to an array. (This is what I'd do.)

Once they're in an array, you can refer to them by index, same as you do with the strings.

But you mention that you're accessing the fields' text property. This only exists in Cocoa Touch, not in Cocoa. If you're using Cocoa Touch, then you have a third option:

  • Replace your 82 outlets with an outlet collection.

The value of an outlet collection property is an array, so you get to create your fields in the nib but still refer to them by index into the array in the code.

On the other hand, I'd probably still create them in code, even though I'm more pro-nib than most Cocoa Touch devs. Part of it is habit (I'm still almost entirely a Mac developer), but part of it is the DRY principle. If I create the fields in a loop in code, I can describe all of the fields exactly once, along with the ways in which they differ. I won't have the risk of changing one field and forgetting (or even just having) to update the others, or of going to change all the fields (again) and forgetting to change one.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
1

I would handle this using the tags: you can set them from 1 to 81 in the nib (look for the field under Control).

Then in -awakeFromNib you can call [self viewWithTag:i] inside a for loop.

It's definitely less work than individual outlets, and I think even simpler than an outlet collection – filling in the number means you don't have to connect outlets for all the text fields.

paulmelnikow
  • 16,895
  • 8
  • 63
  • 114