0

I'm developing an app (by a tutorial, but the tutorial is written for Swift and I'm learning Objective-C. tutorial source

But I have a problem, I'm developing a Custom Controller (RatingController), which works when I only use one of this custom controller in a scene. The Custom controller source is here:

@implementation RatingController

//MARK: Properties
const int spacing = 5;
const int starCount = 5;
UIButton *ratingButtons[starCount];

-(void)setRating:(int)rating{
    _rating = rating;
    [self setNeedsLayout];
}

-(int)getRating{
    return _rating;
}

//MARK: Initialization
- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        //load the images
        UIImage *filledStarImage = [UIImage imageNamed:@"filledStar"];
        UIImage *emptyStarImage = [UIImage imageNamed:@"emptyStar"];

        for (int i = 0; i < starCount; i++) {
            //create button
            UIButton *button = [[UIButton alloc]init];

            //set the images
            [button setImage:emptyStarImage forState:UIControlStateNormal];
            [button setImage:filledStarImage forState:UIControlStateSelected];
            [button setImage:filledStarImage forState:UIControlStateHighlighted|UIControlStateSelected];

            //No additional highlight when switching state
            button.adjustsImageWhenHighlighted = false;

            //hook up the method which should be executed when the user touches a button
            [button addTarget:self action:@selector(ratingButtonTapped:) forControlEvents:UIControlEventTouchDown];

            //add the button the the ratingButton array
            ratingButtons[i] = button;

            //add the button to the view
            [self addSubview:button];
        }
    }
    return self;
}

-(void) layoutSubviews{
    //Set the button's width and height to the height of the frame.
    const int buttonSize = self.frame.size.height;    
    CGRect buttonFrame = CGRectMake(0, 0, buttonSize, buttonSize);

    for(int i = 0; i < starCount; i++){
        buttonFrame.origin.x = (i * (buttonSize + spacing));
        ratingButtons[i].frame = buttonFrame;
    }

    [self updateButtonSelectionState];
}

-(CGSize) intrinsicContentSize{
    const int buttonSize = self.frame.size.height;
    const int width = (buttonSize * starCount) + (spacing * (starCount -1));

    return CGSizeMake(width, buttonSize);
}

//MARK: Button Action
-(void) updateButtonSelectionState{
    for(int i = 0; i < starCount; i++)
        ratingButtons[i].selected = i < _rating;
}

-(void) ratingButtonTapped:(UIButton *) button{
    for(int i = 0; i < starCount; i++){
        if(ratingButtons[i] == button){
            _rating = i + 1;
        }
    }
    [self updateButtonSelectionState];
}

@end

When I put 2 of those custom controllers in 1 scene I can only see the one which is added at the end (in a list only the last List item shows the custom controller) I hope someone can help me.

Thank you very much already!

Bill
  • 4,506
  • 2
  • 18
  • 29
Gilian J
  • 3
  • 2
  • What do you mean by two controllers in one scene? Are you using them in container views? – Phillip Mills Jul 21 '16 at 19:45
  • Like here: https://snag.gy/n0jK1h.jpg every list item should contain the stars – Gilian J Jul 21 '16 at 19:49
  • Could you post the code for your tableview datasource, e.g. cellForRowAtIndexPath. – JingJingTao Jul 21 '16 at 20:39
  • MealTableViewController.m http://pastebin.com/pduLAmeQ MealTableViewCell.h http://pastebin.com/YRRuHCjf MealTableViewCell.m http://pastebin.com/46kxGDfC @JingJingTao Ask if you need any more code. – Gilian J Jul 21 '16 at 20:44
  • @GilianJ: try adding an NSLog in your `layoutSubviews` to display `_rating` and `self.frame` and see if it gives you correct values. – jp2g Jul 21 '16 at 21:26
  • @jp2g I've printed those values, what I see is that the last Item in the array calls layoutSubviews twice instead of once. The _rating value is correct – Gilian J Jul 21 '16 at 21:45

1 Answers1

0

Edit2:

Changed the ratingButton array into a property and mutable array, this resolved the issue.

Edit:

Also check your buttons are being added to your ratingButtons array in your init and that the code in 'updateButtonSelectionState' in working correctly.

Original:

It's worth checking your 'rating' setter, set a break point and check that the correct value is being passed for the first two cells.

Also maybe download the complete example, it's in swift but at least it gives you something to compare against, good luck.

JingJingTao
  • 1,760
  • 17
  • 28
  • The ratingButtons array is filled, when I put a breakpoint at the ratingButtons[i].frame = buttonFrame; line I get this result: https://snag.gy/pCyxKE.jpg And the 'rating' setter works, only the last item in the mealsArray calls the layoutSubviews(); method twice in a row, isn't that weird? – Gilian J Jul 21 '16 at 22:03
  • I guess we expect layoutSubviews to be called three times. Obvious checks, your break point in your init is triggered three times, check the actually frames being set in layoutSubviews. – JingJingTao Jul 21 '16 at 22:13
  • The initWithCoder executes 3 times. The first time layoutSubViews is called all values in the buttonFrame.frame are 0.0 this is unexpected behaviour. The other call values are correct – Gilian J Jul 21 '16 at 22:22
  • Well we're getting somewhere, what are the values of buttonSize and spacing on the first call? If some expected values of 0, hard code them and see what happens. – JingJingTao Jul 21 '16 at 22:30
  • When I print the values of the frame after: ratingButtons[i].frame = buttonFrame; I get this result (4 times) frame origin x:0.000000, y:0.000000, w:44.000000, h:44.000000, frame origin x:49.000000, y:0.000000, w:44.000000, h:44.000000, frame origin x:98.000000, y:0.000000, w:44.000000, h:44.000000, frame origin x:147.000000, y:0.000000, w:44.000000, h:44.000000, frame origin x:196.000000, y:0.000000, w:44.000000, h:44.000000 So actually that method call works. – Gilian J Jul 21 '16 at 22:31
  • Okay that does look right, but I imagine that's for the third cell, what happens for the other cells? You could pastebin your remaining class and I can try debug. – JingJingTao Jul 21 '16 at 22:38
  • I've migrate the project to github, here is the link: https://github.com/gjoosen/FoodTracker – Gilian J Jul 21 '16 at 22:43
  • In apple's Swift project the layoutSubviews method is only called 3times – Gilian J Jul 21 '16 at 22:51
  • I got it to work, it might be that way you store the buttons. Use a mutable array, http://pastebin.com/vGzW417f, try my changes, excuse the UIButton casting. – JingJingTao Jul 21 '16 at 23:13
  • It works! Thank you very much! Should I save all variables the way you did here? – Gilian J Jul 21 '16 at 23:21
  • I would say yes, use properties to store your variables. – JingJingTao Jul 21 '16 at 23:27