所以我按照本教程
现在这就是我的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,并且循环仍然存在。
我真的不确定为什么会这样 - 有人可以帮忙吗?
答案 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;