0

I have 10 different labels, Score1 through Score10. Is there any way to access them like an array. For example ScoreX, with an x in a for loop.

4 Answers4

0

If you want those explicitly as an array you can create your own array. Alternatively, you can create single IBOutlet Collection mapped to labels

Vishal Kardode
  • 961
  • 2
  • 8
  • 25
0

The problem with IBOutletCollection is that the order of the array is not guaranteed. As mention in the nshipster article the order roughly corresponds to the order in which they are connected in the story board but there has been instances across different instances of Xcode wherein that has not held up. So using IBOutletCollection is not a good idea.

Instead you should use a combination of IBOutletCollection and tags.

  1. Define a IBOutletCollection of UILabel in your view controller. @property (nonatomic, strong) IBOutletCollection(UILabel) NSArray *labels;
  2. Connect your labels to this collection.
  3. Set the tag for each of the labels according to the correct order that you want them referenced.
  4. In viewDidLoad or awakeFromNib iterate thru the IBOutletCollection array and sort that array by their tag.
  5. If you have defined properties Score0 to Score9 you can assign them according to their tags. Alternatively if you have an array Scores[] then you can assign the corresponding labels to the array items during sorting.

Then you will be able to access it using the index.

Another different strategy is to use UIStackView. If your labels are arranged vertically or horizontally then you can embed them in a stack view and then use the arrangedSubviews array to access the labels. It appears that the order of the array matches the order in which they are arranged in the stack view.

In response to the comment here's one solution that you can use.

  1. Create a structure inside the ViewController

struct ScoreLabels { let view:UIView! subscript (index:Int) -> UILabel? { return view.viewWithTag(index) as? UILabel; } }

  1. Your Score property should be of time ScoreLabels. Also it should be computed property which returns a instance of the ScoreLabels passing the VC's view.

    var Score:ScoreLabels { return ViewController.ScoreLabels(view: self.view) }

  2. Now you can access the label as Score[index]. Make sure that your index is 0-based.

You can also avoid creating a structure by defining the subscript directly in the ViewController and changing view to self.view and using self[index]

One simplest solution is to define a function and call i t as Score(0), Score(1), Score(2) etc.

func Score(index:Int) -> UILabel? { return self.view.viewWithTag(index) as? UILabel }

ObjC implementation You can implement this method in your ViewController.

- (id)objectAtIndexedSubscript:(NSInteger)idx
{
    return [self.view viewWithTag:idx];
}

Then you can access the label as self[index] where index is the tag of your label.

If you don't want to do this in the ViewController then you can define a custom class to which you pass the VC's view as a parameter and then use the Score property as follows.

@interface ScoreLabels : NSObject
@property (nonatomic, assign) UIView *parentView;
@end

@implementation ScoreLabels
-(id)initWithView:(UIView *)view {
    self = [super init];
    if (self != nil) {
        self.parentView = view;
    }
    return self;
}
- (id)objectAtIndexedSubscript:(NSInteger)idx
{
    return [self.parentView viewWithTag:idx];
}
@end

In your view controller define a property

@property (nonatomic, strong) ScoreLabels *Score;

and initialise it with the VC's view

self.Score = [[ScoreLabels alloc] initWithView:self.view];

And access it as

UILabel *label = (UILabel *)self.Score[1]; label.text = @"Your string";

Pradeep K
  • 3,671
  • 1
  • 11
  • 15
  • ok, I think I set all the tags for the labels, but I still don't know how to access them in the viewDidLoad. The name of the property is `Score` and all the labels have tags 1 through 10. – Mason Satnick Mar 01 '16 at 16:04
  • I think you typed your response in swift... I'm using Objective-C – Mason Satnick Mar 01 '16 at 17:24
  • Added ObjC implementation in the answer – Pradeep K Mar 02 '16 at 04:04
  • I was able to use `for (int x=0; x<10; x++)` `[[self.Score objectAtIndex:x] setText:[NSString stringWithFormat:@"%i. %li",x+1, (long)Scores[x]]];` and `self.Score = [self.Score sortedArrayUsingSelector:@selector(tag)];` to sort it – Mason Satnick Mar 03 '16 at 12:21
-2

You could assign tags and then -viewWithTag in a loop to find you labels.

Gerd K
  • 2,933
  • 1
  • 20
  • 23
  • That may be so, especially for folks not used to IB. However IBOutletCollection isn't perfect either, as the order in it is not guaranteed. – Gerd K Feb 29 '16 at 15:15