iphone视图上的无限循环

时间:2013-11-26 01:29:10

标签: ios objective-c infinite-loop

所以我按照本教程

http://www.raywenderlich.com/1768/uiview-tutorial-for-ios-how-to-make-a-custom-uiview-in-ios-5-a-5-star-rating-view

现在这就是我的AppDelegate的样子

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    RateViewController* rater = [[RateViewController alloc]initWithNibName:@"RateView" bundle:nil];
    self.window.rootViewController = rater;

    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

我的RateView.h -

    @class RateView;

@protocol RateViewDelegate
-(void)rateView:(RateView *)rateView ratingDidChange:(float)rating;
@end



@interface RateView : UIView

@property(strong,nonatomic)UIImage* fullSelectedStar;
@property(strong,nonatomic)UIImage* notSelectedStar;
@property(strong, nonatomic)UIImage* halfSelectedStar;
@property (assign, nonatomic)float rating;
@property(assign) BOOL editable;
@property (strong) NSMutableArray* imageViews;
@property(assign,nonatomic) int maxRating;
@property(assign) int midMargin;
@property(assign)int leftMargin;
@property (assign) CGSize minImageSize;
@property (assign) id <RateViewDelegate> delegate;

@end

我的RateView.m -     #import&#34; RateView.h&#34;

@implementation RateView
@synthesize fullSelectedStar = _fullSelectedStar;
@synthesize notSelectedStar = _notSelectedStar;
@synthesize rating = _rating;
@synthesize editable = _editable;
@synthesize imageViews = _imageViews;
@synthesize maxRating = _maxRating;
@synthesize midMargin = _midMargin;
@synthesize leftMargin = _leftMargin;
@synthesize minImageSize = _minImageSize;
@synthesize delegate = _delegate;


- (void)baseInit {
    _fullSelectedStar = nil;
    _notSelectedStar = nil;
    _rating = 0;
    _editable = NO;
    _imageViews = [[NSMutableArray alloc] init];
    _maxRating = 5;
    _midMargin = 5;
    _leftMargin = 0;
    _minImageSize = CGSizeMake(5,5);
    _delegate = nil;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self baseInit];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder{
    if((self = [super initWithCoder:aDecoder])){
        [self baseInit];

    }

    return self;


}

- (void)refresh{
    for(int i = 0; i < self.imageViews.count; ++i){
        UIImageView *imageView = [self.imageViews objectAtIndex: i];
        if(self.rating >= i+1){
            imageView.image = self.fullSelectedStar;
        } else if( self.rating > i){
            imageView.image = self.halfSelectedStar;
        } else{
            imageView.image = self.notSelectedStar;
        }
    }
}


- (void)layoutSubViews{
    [super layoutSubviews];
    if (self.notSelectedStar == nil) return;
    float desiredImageWidth = (self.frame.size.width - (self.leftMargin*2) - (self.midMargin*self.imageViews.count)) / self.imageViews.count;
    float imageWidth = MAX(self.minImageSize.width, desiredImageWidth);
    float imageHeight = MAX(self.minImageSize.height, self.frame.size.height);

    for (int i = 0; i < self.imageViews.count; ++i) {

        UIImageView *imageView = [self.imageViews objectAtIndex:i];
        CGRect imageFrame = CGRectMake(self.leftMargin + i*(self.midMargin+imageWidth), 0, imageWidth, imageHeight);
        imageView.frame = imageFrame;

    }
}

- (void)setMaxRating:(int)initialMaxRating{
    self.maxRating = initialMaxRating;
    for(int i = 0; i < self.imageViews.count; i++){
        UIImageView *imageView = (UIImageView *)[self.imageViews objectAtIndex: i];
        [imageView removeFromSuperview];
    }

    [self.imageViews removeAllObjects];

    for(int i = 0; i < initialMaxRating;i++){
        UIImageView *imageView = [[UIImageView alloc] init];
        imageView.contentMode = UIViewContentModeScaleAspectFit;
        [self.imageViews addObject:imageView];
        [self addSubview:imageView];
    }

    [self setNeedsLayout];
    [self refresh];
}

- (void)setNotSelectedStar:(UIImage *)initialNotSelectedStar {
    NSLog(@"Pointer is %@",initialNotSelectedStar);
    self.notSelectedStar = initialNotSelectedStar;
    [self refresh];

}

- (void)setHalfSelectedStar:(UIImage *)image{
    self.halfSelectedStar = image;
    [self refresh];
}


- (void)setFullSelectedStar:(UIImage *)initialFullSelectedStar{
    self.fullSelectedStar = initialFullSelectedStar;
    [self refresh];
}

- (void)setRating:(float) initialRating{
    self.rating = initialRating;
    //this needs to post to an url
    [self refresh];

}


-(void)handleTouchAtLocation:(CGPoint)touchLocation{
    if(!self.editable) return;

    int newRating = 0;

    for(int i = self.imageViews.count -1; i >=0; i--){
        UIImageView* imageView = [self.imageViews objectAtIndex: i];
        if(touchLocation.x > imageView.frame.origin.x){
            newRating = i+1;
            break;
        }
    }

    self.rating = newRating;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInView:self];
    [self handleTouchAtLocation:touchLocation];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInView:self];
    [self handleTouchAtLocation:touchLocation];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    [self.delegate rateView:self ratingDidChange:self.rating];
}

@end

分别是我的RateViewController.h和RateViewController.m -

RateViewController.h -

@interface RateViewController : UIViewController <RateViewDelegate>
@property (weak, nonatomic) IBOutlet RateView *rateView;
@property (weak, nonatomic) IBOutlet UILabel *statusLabel;

@end

RateViewController.m -

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.rateView.notSelectedStar = [UIImage imageNamed:@"kermit_empty.png"];
    self.rateView.halfSelectedStar = [UIImage imageNamed:@"kermi_half.png"];
    self.rateView.fullSelectedStar = [UIImage imageNamed:@"kermit_full.png"];
    self.rateView.rating = 0;
    self.rateView.editable = YES;
    self.rateView.maxRating = 5;
    self.rateView.delegate = self;

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)rateView:(RateView *)rateView ratingDidChange:(float)rating{
    self.statusLabel.text = [NSString stringWithFormat:@"Rating: %f",rating];
}

现在setNotSelctedStar方法中存在无限循环。我在self.notSelectedStar = initialNotSelectedStart上放了一个断点,然后尝试踩踏,但它只是循环并再次打印出指针。

我注释掉了[自我刷新] - 没有效果。我还以为是因为我错误地访问了图像,所以我将其设置为nil,并且循环仍然存在。

我真的不确定为什么会这样 - 有人可以帮忙吗?

3 个答案:

答案 0 :(得分:3)

你所有的setXXX方法都错了,他们再次调用自己。它应该设置ivar不再调用适当的setter

- (void)setNotSelectedStar:(UIImage *)initialNotSelectedStar {
    NSLog(@"Pointer is %@",initialNotSelectedStar);
    _notSelectedStar = initialNotSelectedStar;
    [self refresh];

}

- (void)setHalfSelectedStar:(UIImage *)image{
    _halfSelectedStar = image;
    [self refresh];
}


- (void)setFullSelectedStar:(UIImage *)initialFullSelectedStar{
    _fullSelectedStar = initialFullSelectedStar;
    [self refresh];
}

- (void)setRating:(float) initialRating{
    _rating = initialRating;
    //this needs to post to an url
    [self refresh];

}

_notSelectedStar是一个变量。 _notSelectedStar = image是直接分配,没有其他副作用。

self.notSelectedStar正在调用属性的setter / getter,与[self notSelectedStar][self setNotSelectedStar:image]相同,这是一个可能产生副作用的方法调用。

答案 1 :(得分:0)

这是因为setNotSelectedStar的实现会调用自己。

改变这个:

- (void)setNotSelectedStar:(UIImage *)initialNotSelectedStar {
    NSLog(@"Pointer is %@",initialNotSelectedStar);
    self.notSelectedStar = initialNotSelectedStar;
    [self refresh];

}

为:

- (void)setNotSelectedStar:(UIImage *)initialNotSelectedStar {
    NSLog(@"Pointer is %@",initialNotSelectedStar);
    _notSelectedStar = initialNotSelectedStar;
    [self refresh];

}

答案 2 :(得分:0)

这是因为setter方法中的这一行:

self.notSelectedStar = initialNotSelectedStar;

self.notSelectedStar,在表达式的左侧,与

相同
[self setNotSelectedStar:initialNotSelectedStar];

因此,您以递归方式调用该函数。将该行更改为:

_notSelectedStar = initialNotSelectedStar;