Challange: Changing Colors


#1

Hi,

I added the following code to the solve the challange:

HypnosisView.h

HypnosisView.m

This makes stripeColor accessible other objects.

HypnosisViewController.m, - (void)accelerometer:(UIAccelerometer *)meter didAccelerate:(UIAcceleration *)accel

[code]
… [hv setYShift:yShift];

float r, g, b;
r = [accel x] / 2 + .5;
g = [accel y] / 2 + .5;
b = [accel z] / 2 + .5;

[[hv stripeColor] release];

[hv stripeColor] = [UIColor colorWithRed:r green:g blue:b alpha:1];
[[hv stripeColor] retain];

// Redraw the view …[/code]
The assignment of the new UIColor causes a build error: LValue required as left operand of assignment.

When I change the code to the dot notation, I can build and run the app with no problems.

I don’t understand why I get the error.


#2

Hi,

@synthesize will generate a stripeColor method (getter) and a setStripeColor method (setter).

so to get the equivalent of hv.stripeColor = [UIColor colorWithRed:r green:g blue:b alpha:1];

you would use:

	[hv setStripeColor:[UIColor colorWithRed:r green:g blue:b alpha:1]];

Gareth


#3

Thanks Gareth,

sometimes the solutions is so simple. :smiley:


#4

Your solution is a lot more elegant than mine. Mine works, but now that I see yours, I feel stupid :confused:

Anyhow, this is what I did…

I created three new float instance variables to my HypnosisView

xColor, yColor, zColor

In my accelerometer:didAccelerate method of my HypnosisViewController I did the calculation using the data from the accelerometer using a few if statements…

	float xColor = 0;
	float yColor = 0;
	float zColor = 0;
	
	if ([acceleration x] > 0)
	{
		xColor = 1;
	}
	
	if ([acceleration y] > 0)
	{
		yColor = 1;
	}
	
	if ([acceleration z] > 0)
	{
		zColor = 1;
	}
	
	[hv setXColor:xColor];
	[hv setYColor:yColor];
	[hv setZColor:zColor];

Now, back in my HypnosisView I assigned the stripeColor as follows…

	stripeColor = [UIColor colorWithRed:xColor
								  green:yColor
								   blue:zColor
								  alpha:1];
	 
	[stripeColor setStroke];

I REALLY like how you just divided the data by 2 and added .5. I can’t believe I didn’t think about doing that! I feel like a newb coder. I also like that you just synthesized the setters and getters for stripeColor. I can’t believe I didn’t think about doing that!

This is why I complete all of the challenges and read the forums. I learn a lot and I’m really digging this book. Certain things are just becoming to be 2nd nature.


#5

We were all “newbs” once and we all feel stupid when we see someone do something better than us.

The person that challenges themselves while humbly marveling at that “next level” of skill is the person that makes it to that next level.

You’re on the right track.


#6

I had done pretty much the same thing and I wanted to know what went wrong.

I tried leaving the rgb values in the model and tried calling another method to use those values to create a new stripeColor. I read the accel values in the VC and based on their “value” i would pass different rgb values to the model’s method. I did think about setting the stripeColor as a property before i got into this mess. Anyway, it didnt work.

Hypnosis.h

float r,g,b;

@property each one

Hypnosis.m
@synthesize r,g,b;

-(void)changeStripeColorOnRotateWithR:(CGFloat)r G:(CGFloat)g B:(CGFloat)b{
// this calls to change the stripe color
NSLog(@“new color values received…%f, %f, %f”,r,g,b);
[stripeColor release];
stripeColor = [UIColor colorWithRed:r/256.0 green:g/256.0 blue:b/256.0 alpha:1.0];
[stripeColor retain];
[self setNeedsDisplay];
}

HypnosisViewController.m

[hv setXShift:10.0 * [accel x]];
[hv setYShift:-10.0 * [accel y]];
if ([accel x] < -1.0) {
// call changeStripColorOnRotation
[hv changeStripeColorOnRotateWithR:[accel y] G:0.0 B:0.0];
[hv setNeedsDisplay];

} else if ([accel y] >= -1.0) {
	//call changeStripColorOnRotation
	[hv changeStripeColorOnRotateWithR:0.0 G:[accel y] B:0.0];
	[hv setNeedsDisplay];

} else if ([accel z] >= -1.0) {
	//call changeStripColorOnRotation
	[hv changeStripeColorOnRotateWithR:0.0 G:0.0 B:[accel z]];
	[hv setNeedsDisplay];

}

Could someone tell me why?


#7

My solution:

HypnosisView.h

[code]#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface HypnosisView : UIView {
UIColor *stripeColor;
float xShift, yShift;
}
@property (nonatomic, assign) float xShift;
@property (nonatomic, assign) float yShift;
@property (nonatomic, retain) UIColor *stripeColor;

@end[/code]

HypnosisView.m

@implementation HypnosisView @synthesize xShift, yShift, stripeColor; ...

HypnosisViewController.m

[code]…
float r, g, b;
r = [acceleration x] < 0 ? 0 : 1;
g = [acceleration y] < 0 ? 0 : 1;
b = [acceleration z] < 0 ? 0 : 1;

[hv setStripeColor:[UIColor colorWithRed:r green:g blue:b alpha:1]];

…[/code]

IIUC using the retain attribute in the property declaration for the stripeColor instance variable results in an accessor method being generated that releases the existing value of the variable before retaining and assigning the new value.


#8

Thanks for the explanation on this Adam. I had very similar code but the stripeColor property was (nonatomic, assign) and the app was crashing. I understood that the UIColor was autoreleased so I added a retain in HypnosisViewController.m which stopped the crash but threw up a memory leak warning, Now things make sense!