hittin UIImageViews with another UIImageView - ios

I have 10 UIImageViews on the screen. They are all in an array called posArray. I also have another UIImageView that is dragged by user and can hit those other 10. What is the easies way of displaying a simple NSlog message if the one object hits any of the other 10?
Right now i'm using touchesBegin, touchesMoved to move my one object and this array below to test if the one objects hits any of the other ten.
I'm just thinking that there is an easier, less memory spending way, way of doing this for some reason.
for (int i = 0; i < [posArray count]; i++) {
UIImageView *tempPos;
tempPos = [posArray objectAtIndex:i];
if (CGRectIntersectsRect(red1.frame, tempPos.frame)) {
red1.center = CGPointMake(tempPos.center.x, tempPos.center.y);
NSLog(#"position piece touched");
}
}

You can also use fast enumeration to get some more speed. Also you can add a break statement after you found one match (if you just need one match):
for (UIImageView * tempPos in posArray){
if (CGRectIntersectsRect(red1.frame, tempPos.frame)) {
red1.center = CGPointMake(tempPos.center.x, tempPos.center.y);
NSLog(#"position piece touched");
break;
}
}

Related

How can I take the current integer value out of my array loop when I press my button on Xcode?

I need to take the current value of mtype and pass it forward to Mselect so that the image pushed forward is the same as the one rotating in the animation.
here is the code sample
- (void)viewDidLoad
{
//Array to hold Images
NSMutableArray *imageArray = [[NSMutableArray alloc] initWithCapacity:Mush_Count];
for (mtype = 1; mtype < Mush_Count; mtype++)
{
[imageArray addObject:[UIImage imageNamed:[NSString stringWithFormat:#"Mush%i.png", mtype]]];
//make button
SelectBt.imageView.animationImages = [NSArray arrayWithArray:imageArray];
SelectBt.imageView.animationDuration = 5;
[SelectBt.imageView startAnimating];
Mselect = mtype;
}
}
-(IBAction)Selection:(id)sender{
[self Placement];
}
-(void)Placement{
if (Place1Occ == NO) {
[self Place1];
}
}
-(void)Place1{
if (Place1Occ == NO) {
Place1.image =[UIImage imageNamed:[NSString stringWithFormat:#"Mush%i.png", Mselect]];
Place1Occ = YES;
}
}
The animation loops just fine and the selection of the images works but it's not selecting the image the is currently on the screen it selects the last image on the Array.
Any suggestions?
for (mtype = 1; mtype < Mush_Count; mtype++)
{
[imageArray addObject:[UIImage imageNamed:[NSString stringWithFormat:#"Mush%i.png", mtype]]];
}
That loop is enough to build the array of images - you don't need to set the imageView's animation images until this loop completes and the array is populated.
As it stands, you reset the animation images each loop and set Mselect to type each iteration: this is why you always get the last image index stored in Mselect
This code should be after the for loop:
SelectBt.imageView.animationImages = [NSArray arrayWithArray:imageArray];
SelectBt.imageView.animationDuration = 5;
[SelectBt.imageView startAnimating];
As far as I know, you can't get the current frame of the animation directly - you have to create a timer when you start the animation and have this count the number of frames (by increasing your Mselect value. Then use that to load the current image
Is SelectBT a subclass of UIButton? if so is it the (id)sender coming from your IBAction?
If so then you can just grab the image directly from the SelectBT instance by calling sender.imageView.image
As an aside, objective-C convention is to capitalize ClassNames, but start instances with lowerCase like this ClassName *instanceOfClassName and you're likely to take flack for it around here if you don't adhere to that convention
Update
Could you bump your imageArray into a class variable or a property? It already contains all the fully loaded UIImages, which you can get back out by calling [imageArray objectAtIndex:i]
Then you just have to keep track of which numeric index is facing your user, or which index they tapped and pull the corresponding image.
Feel free to post your whole class if you'd like us to explain more.

Keeping track of objects on the screen

Even though I’m writing in Objective C, most of my code is still written in a procedural style. However, now I want to do something where that approach will not work. So I need some advice on how to deal with an indeterminate number of objects on the screen at the same time. I’m sure that this problem has been solved, I just haven’t been able to find out how.
I have a bunch of games where I put two or four pictures on the screen and then the user interacts with the picture. When they are done with a page they swipe to the next one and I use a transition to slide the pictures off the screen. I can control the movement of the pictures because when they were created I name them self.picture_1 and self.picture_2. The movement method knows about them even though that method didn’t create them.
Now suppose I want to have an indeterminate number of pictures on the screen. I can’t call them self.picture_1. through self.picture_n because ObjectiveC won’t let you dynamically create variable names. But I still need to move them in a method where they weren’t created.
I can make it work with two techniques, neither of which seem ideal. First, I look at all the objects on the screen and then do something with the ones that I want to target. Note: pictures are in buttons.
for ( id subview in self.parentView.subviews ) {
if ( [subview isKindOfClass:[UIButton class]] ) {
UIButton *pictureButton = subview;
for (NSUInteger i=0; i<self.totalItems; i++) {
NSUInteger row = (i % 2) + 1;
NSUInteger column = (i/2) + 1;
NSString *pictureTitle = [NSString stringWithFormat:#"pictureR%iC%i", row, column];
if ( [pictureButton.titleLabel.text isEqualToString:pictureTitle] ) [pictureButton removeFromSuperview];
}
}
}
This works for removing them from the view, but gets cumbersome when I try to make the pictures slide off the screen.
The second way is to make an array that holds the picture objects when they are created. I’ve been playing with something like this.
self.gridImages = [NSMutableArray arrayWithCapacity:4];
for (NSUInteger i = 0; i < itemsOnScreen; i++) {
Word *word = [wordListArray objectAtIndex:i];
self.gridImages[i] = word.image;
}
And then to do things with the pictures I loop through the array.
for (NSUInteger i = 0; i < itemsOnScreen; i++) {
Picture *picture = self.gridImages[i];
// do something with picture
}
Neither of these methods seems ‘right’ so I’m wondering if there is a preferred method for manipulating an indeterminate number of objects on the screen?
#Hot Licks, that works, so I put you answer into an answer.
I have it working for checkBoxes. They are created by the main view controller and it passes in a tag. I'm using tags starting at 1000 for checkboxes, 2000 for pictures, etc. Just before I put the checkBox on the screen, I assign it the tag.
[self.checkBox setTag:checkBoxTag];
You could also use: self.checkbox.tag = checkBoxTag;
When it is time to remove the checkBoxes, I loop through all of the tags starting at 1000 up to the total number of items on the screen. I have warnings turned up to 11 so I need to cast the counter to an NSInteger.
- (void)removeCheckboxes {
for (NSUInteger i = 0; i < self.totalItems; i++) {
NSInteger tagNumber = 1000 + (NSInteger)i;
[ [self.parentView viewWithTag:tagNumber] removeFromSuperview];
}
}

iOS: Moving a uibutton by its tag outside of where it was generated

Is it possible? I have an array of buttons created in an void and I want to move one when a neighbouring one is called in the buttonTapped void. I have no trouble moving the button thats pressed because it is the sender, but I also need to move the one next to it and can't seem to get it to move. Each button in the array has a tag value so they're unique.
Thanks
Reasonable intuitive assumption: you generated the buttons so that they are ordered in the array...
- (void)moveButton:(UIButton *)sender // whatever
{
NSUInteger idx = [buttonArray indexOfObject:sender] + 1;
UIButton *nextButton = idx < buttonArray.count ? [buttonArray objectAtIndex:idx] : nil;
// do something with `nextButton`
}

Managed array of UIView using some method

Hello I am noob in Xcode and I want to ask
I have array of UIView's with one image
NSInteger i;
for (i=0; i<CARD_AMOUNT; i++) {
[cardArray addObject:[UIImage imageNamed:#"Back.png"]];
}
and I want to draw it and then to do different things on each (move...etc)
or I must create 10 variables of UIImageView?
Could use a bit more explanation of the app you're trying to build, but essentially if you're wanting to display many different cards on one view (let's say, a game of solitaire) - you'll want to create many UIImageViews. Well, from an pure design perspective, you'd probably want a different class called CardView which knew how to render itself
So, if you wanted many different views all with one image, something like this:
for(int a=0; a<CARD_AMOUNT; a++) {
UIImageView *view = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Back.png"]];
[cardArray addObject:view];
// and maybe you'd want to set the frame locations, or add them to your current view as subviews, or ..
}
To address the comments, your custom CardView might have something like this (there's ways to optimize, but the general concept isn't too bad):
- (void)setRank: (int)rank andSuit:(int)suit {
self.image = [UIImage imageNamed:[NSString stringWithFormat:#"card-%d-%d.png",rank,suit];
self.rank = rank; self.suit = suit;
}
or, better yet (since a card's rank won't change) - some initWithRank: andSuit: method.. dunno.
There's probably 10 other ways to design this.

Demand loading a UIScrollView

I would like to implement an app using a UIScrollView with paging, similar to the apple weather app.
But I am a little concerned about performance. The example implementation I have been using loads all of the views then the application launches. After a certain point, once this prove slow?
I wonder how Apple's camera roll is dealing with this, where a user may have 100+ photos that can be scrolled through. Should I try to figure out a way to build the view only when it is needed? Or maybe there is a way to replicate the dequeue reusable cell technique from a UITableView, only for horizontal view loading, since each view will have the same layout.
By far the most efficient solution (and this is used in many photo-browsing apps such as Facebook, and probably the native Photos app too) is going to be to load the content on-demand, just as UITableView does. Apple's StreetScroller sample project should get you on the right track.
A very efficient solution, is to make sure to reuse any views whenever possible. If you are going to be simply displaying images, you could use a subclass of UIScrollView, and layout these reusable views within layoutSubviews. Here you could detect what views are visible and not visible and create the subviews as needed.
An example dequeuing function may look like:
- (UIImageView *)dequeueReusableTileWithFrame:(CGRect) frame andImage:(UIImage *) image
{
UIImageView *tile = [reusableTiles anyObject];
if (tile) {
[reusableTiles removeObject:tile];
tile.frame = frame;
}
else {
tile = [[UIImageView alloc] initWithFrame:frame];
}
tile.image = image;
return tile;
}
Where reusableTiles is just an iVar of NSMutableSet type. You could then use this to load fetch any currently offscreen image views and quickly and easily bring them back into view.
Your layoutSubviews may look something like:
- (void)layoutSubviews {
[super layoutSubviews];
CGRect visibleBounds = [self bounds];
CGPoint contentArea = [self contentOffset];
//recycle all tiles that are not visible
for (GSVLineTileView *tile in [self subviews]) {
if (! CGRectIntersectsRect([tile frame], visibleBounds)) {
[reusableTiles addObject:tile];
[tile removeFromSuperview];
}
}
int col = firstVisibleColumn = floorf(CGRectGetMinX(visibleBounds)/tileSize.width);
lastVisibleColumn = floorf(CGRectGetMaxX(visibleBounds)/tileSize.width) ;
int row = firstVisibleRow = floorf(CGRectGetMinY(visibleBounds)/tileSize.height);
lastVisibleRow = floorf(CGRectGetMaxY(visibleBounds)/tileSize.height);
while(row <= lastVisibleRow)
{
col = firstVisibleColumn;
while (col <= lastVisibleColumn)
{
if(row < firstDisplayedRow || row > lastDisplayedRow || col < firstDisplayedColumn || col >lastDisplayedColumn)
{
UImageView* tile = [self dequeueReusableTileWithFrame:CGRectMake(tileSize.width*col, tileSize.height*row, tileSize.width, tileSize.height) andImage:YourImage];
[self addSubview:tile];
}
++col;
}
++row;
}
firstDisplayedColumn = firstVisibleColumn;
lastDisplayedColumn = lastVisibleColumn;
firstDisplayedRow = firstVisibleRow;
lastDisplayedRow = lastVisibleRow;
}
I used something similar to this to tile in areas of a line when I was working with an exceptionally large area of a scroll view and it seemed to work quite well. Sorry for any typos that I may have created when updating this for an image view instead of my custom tileView class.

Resources