Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Game Development

Reply
 
LinkBack Thread Tools Display Modes
Old 02-19-2011, 10:42 PM   #1 (permalink)
Registered Member
 
Join Date: Feb 2011
Posts: 13
ebarmes is on a distinguished road
Default Need advice on moving a UIView

Ok so I'm designing a game that has moving views that need to receive touch input. As far as I can tell a view won't register the touchesBegan: method while running the animateWithDuration: method. Also I have a game loop like this


- (void)viewDidLoad {

displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update:)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop]
forMode:NSRunLoopCommonModes];

[super viewDidLoad];
}

-(void) update:(CADisplayLink*)displayLink {}


but if I ask my game loop to move the view like this
aSubview.frame.origin.y -= 5;
where aSubview is an initialized instance of a subclass of UIView
I get the error Lvalue required as left operand of assignment

So I guess my question is can anyone tell me which way is easier/better for moving a UIView while keeping the touchesBegan: method active (using animateWithDuration: or using my game loop) and also how to get either of these ways to work. Thanks for any help and direction.
ebarmes is offline   Reply With Quote
Old 02-19-2011, 11:02 PM   #2 (permalink)
Registered Member
iPhone Dev SDK Supporter
 
smasher's Avatar
 
Join Date: Jul 2008
Location: San Mateo, CA (San Fran)
Posts: 3,858
smasher will become famous soon enough
Default

Code:
aSubview.frame.origin.y -= 5;
That code - and the error message you get - is the same you'd see for this code. It's a little hard to see why though:
Code:
10 = 10 + 5;
Objective-C uses the same syntax - dot syntax - for properties that C uses to access structs. This causes confusion when you mix the two. In your case aSubview is an object, and you are using the "frame" property. The contents of that property is a struct though (CGRect is a struct, not an object) and you get a read-only copy of that struct.

You need to do this the long way around - copy the struct into a local variable, change it, then copy it back into the object.

Code:
CGRect myFrame = aSubview.frame;
myFrame.origin.y -= 5;
aSubview.frame = myFrame;
Your way would work OK if these were all objects, but they are not. In short, the rules for objects and structs are different.
__________________

Free Games!
smasher is offline   Reply With Quote
Old 02-20-2011, 03:09 PM   #3 (permalink)
Registered Member
 
Join Date: Feb 2011
Posts: 13
ebarmes is on a distinguished road
Default

Thanks a ton, I tried for hours to figure out what I was doing wrong. So that's fixed but now I've run into another problem.

I have multiple subviews (i.e. aSubview, bSubview, cSubview) and instead of hardcoding each separately to move like

CGRect tempRect = aSubview.frame;
tempRect.origin.y -= 5;
aSubview.frame = tempRect;

I'd like to save some time and lines of code by creating an array like

NSArray* subviewArray = [[NSArray alloc] initWithObjects:aSubview, bSubview, cSubview, nil]}

but when I try to move the three in my game loop like

int i = 0;

while (i < 3){
CGRect tempRect = [subviewArray objectAtIndex:i].frame;
tempRect.origin.y -= 5;
[subviewArray objectAtIndex:i].frame = tempRect;
i++;
}

I get an error "request for member 'frame' in something not a structure or union". if I try

while (i < 3){
CGRect tempRect = [[subviewArray objectAtIndex:i] frame];
tempRect.origin.y -= 5;
[[subviewArray objectAtIndex:i] frame] = tempRect;
i++;
}

I get no error for line 2, but I get "Lvalue required as left operand of assignment" for line 4. Now I think this is like you said before, .frame returns a read only CGRect which is a struct but can you direct me on how I can use an array and cycle through using a loop to move each subview.
ebarmes is offline   Reply With Quote
Old 02-20-2011, 05:45 PM   #4 (permalink)
Registered Member
iPhone Dev SDK Supporter
 
smasher's Avatar
 
Join Date: Jul 2008
Location: San Mateo, CA (San Fran)
Posts: 3,858
smasher will become famous soon enough
Default

You're very close - let the compiler know what you're getting from the array and it'll help you out:

Code:
while (i < 3){
    UIView *myView = [subviewArray objectAtIndex:i];
    CGRect tempRect = myView.frame;
    tempRect.origin.y -= 5;
    myView.frame = tempRect;
    i++;
}
__________________

Free Games!
smasher is offline   Reply With Quote
Old 02-21-2011, 01:11 PM   #5 (permalink)
Registered Member
 
Join Date: Feb 2011
Posts: 13
ebarmes is on a distinguished road
Default

Quote:
Originally Posted by smasher View Post
You're very close - let the compiler know what you're getting from the array and it'll help you out:

Code:
while (i < 3){
    UIView *myView = [subviewArray objectAtIndex:i];
    CGRect tempRect = myView.frame;
    tempRect.origin.y -= 5;
    myView.frame = tempRect;
    i++;
}
ok, but this code creates new instances mirroring the objects in the array. Is it not possible to add a view from an array to the stage, as its called in actionscript, not sure what its called in ios but I just mean the highest level view, then continue to manipulate it by [subviewArray objectAtIndex:], or does adding the subview remove the option of accessing its properties through the array. My thinking could be completely flawed but I would much appreciate a short description of why this will or won't work.
ebarmes is offline   Reply With Quote
Old 02-21-2011, 01:48 PM   #6 (permalink)
Registered Member
iPhone Dev SDK Supporter
 
smasher's Avatar
 
Join Date: Jul 2008
Location: San Mateo, CA (San Fran)
Posts: 3,858
smasher will become famous soon enough
Default

My code doesn't create new instances at all. You're looking at this line:

Code:
UIView *myView = [subviewArray objectAtIndex:i];
That does *not* create a new UIview. It creates a new pointer, and points it to an existing object in the array.

Your problem stems from a confusion between pointers and objects, and that's partly our fault. We say "call a method on myView" or "myView is a UIView" when we really mean "call a method on the object pointed to by myView" or "myView is a pointer which points to a UIView." It's convenient shorthand, but misleading to anyone new to pointers.
__________________

Free Games!
smasher is offline   Reply With Quote
Old 02-21-2011, 08:36 PM   #7 (permalink)
Registered Member
 
Join Date: Feb 2011
Posts: 13
ebarmes is on a distinguished road
Default

woah, that just blew my mind. I think that is going to help a lot. I didn't really understand why ios used so many pointers.

so to make sure im thinking correctly now

(thisSubview*) aSubview = [[thisSubview alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];

creates a pointer called aSubview to an instance of the thisSubview class which i just allocated memory for and initialized with a frame.

now

(NSArray*) myArray = [[NSArray alloc] initWithObjects: aSubview, nil];

creates a pointer called myArray to an NSArray instance which includes the pointer to the thisSubview instance.

so

(thisSubview*) newASubview = [myArray objectAtIndex:0];

simply creates a new pointer to the same instance of thisSubview that aSubview originally pointed to. So now calling

[aSubview customMethod];
or
[newASubview customMethod];

will do the same thing or affect the same instance of thisSubview?

and while im at it, i think i finally understand how a memory leak can happen.
if i create a new instance of thisSubview

(thisSubview*) bSubview = [[thisSubview alloc] initWithFrame:CGRectMake(1, 1, 1, 1)];

then tell aSubview to point to the same thing

aSubview = bSubview;

will this create a memory leak because now there is no pointer, and therefore, no way to access the original thisSubview instance, assuming that I had not created the newASubview pointing to it

by the way thanks for all your help so far, youve really cleared up some of my misconceptions about ios, cocoa, c++, c and probably more
ebarmes is offline   Reply With Quote
Old 02-21-2011, 10:17 PM   #8 (permalink)
Registered Member
iPhone Dev SDK Supporter
 
smasher's Avatar
 
Join Date: Jul 2008
Location: San Mateo, CA (San Fran)
Posts: 3,858
smasher will become famous soon enough
Default

You're right, right down the line, until the last one:

Code:
ThisSubview* bSubview = [[ThisSubview alloc] initWithFrame:CGRectMake(1, 1, 1, 1)];
ThisSubview* aSubview = bSubview;
You now have two pointers to one objects, which is fine. It might be a leak if no one calls [aSubview release] or [bSubview release] though.

This is definitely a leak:
Code:
ThisSubview* bSubview = [[ThisSubview alloc] initWithFrame:CGRectMake(1, 1, 1, 1)];
bSubview = nil;
Now no one has a pointer to your new view, so no one can release it. It is definitely a leak. Even if you do [bSubview release] later in this code it doesn't help, because you're just calling the method on nil, which has no effect.

As Obi-wan said, you've just take the first step into a larger world!
__________________

Free Games!
smasher is offline   Reply With Quote
Old 02-21-2011, 10:27 PM   #9 (permalink)
Registered Member
 
Join Date: Feb 2011
Posts: 13
ebarmes is on a distinguished road
Default

i meant

ThisSubview* bSubview = [[ThisSubview alloc] initWithFrame:CGRectMake(1, 1, 1, 1)];
aSubview = bSubview;
but aSubview was already pointing like

ThisSubview* aSubview = [[ThisSubview alloc] initWithFrame:CGRectMake(0,0,0,0)];

so i'd lose the pointer to "[[ThisSubview alloc] initWithFrame:CGRectMake(0,0,0,0)];"

also I'm new to the forum, and ios in general as you can tell, how do you add those code boxes?
ebarmes is offline   Reply With Quote
Old 02-21-2011, 10:45 PM   #10 (permalink)
Registered Member
iPhone Dev SDK Supporter
 
smasher's Avatar
 
Join Date: Jul 2008
Location: San Mateo, CA (San Fran)
Posts: 3,858
smasher will become famous soon enough
Default

Righto, you're leaking the original view that aSubview pointed to.

To make code boxes you use code tags - start with [code]
and end with [ /code] but without the space before the /
__________________

Free Games!
smasher is offline   Reply With Quote
Reply

Bookmarks

Tags
animating, game loop, touch input, touchesbegan, uiview

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 425
8 members and 417 guests
chemistry, ChrisYates, hussain1982, Retouchable, skrew88, SLIC, walex, xzoonxoom
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,679
Threads: 94,128
Posts: 402,921
Top Poster: BrianSlick (7,990)
Welcome to our newest member, xzoonxoom
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 08:11 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0