I am developing a project in which I have created a UIImageView dynamically using an NSMutableArray
The code for this is:
for (int i = 0; i < index ; i++) {
image_name= [NSString stringWithFormat:#"%#%dpng.png",[string_values objectAtIndex:0],i+1];
UIImageView *tempImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:image_name]];
tempImageView.userInteractionEnabled = YES;
CGSize size2=tempImageView.image.size;
int width2=size2.width/2;
int height2 =size2.height/2;
tempImageView.frame = CGRectMake(xvalue,yvalue,width2,height2);
[myArray addObject:tempImageView];
}
After that I add the subview to show it on the screen with this code:
for(int i=0;i<[myArray count];i++) {
[self.view addSubview:[myArray objectAtIndex:i]];
}
All the above code runs well as according to the needs. Now for the touchesBegan method, I am doing this code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
printf("the touch is fired");
for(int i=0;i<[myArray count];i++) {
[self.view addSubview:[myArray objectAtIndex:i]];
touchStart = [[touches anyObject] locationInView:[myArray objectAtIndex:i]];
}
}
The app crashes when the touchesBegan method is called, right after it prints the first line of the touchesBegan method.
I am having difficulties here and have also gone through many question/answers but can't find a working solution. Any help will be appreciated. Thanks for Good Replies
To make your imageviews draggable,
1) Remove all - (void)touches methods
2) Add these two lines just after creating UIImageView *tempImageView (in loop)
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handleDrag:)];
[tempImageView addGestureRecognizer:panRecognizer];
3) then, add this method somewhere in your view controller.m file
-(void) handleDrag:(UIPanGestureRecognizer *) panGesture{
CGPoint transition = [panGesture translationInView:self.view];
panGesture.view.center = CGPointMake(panGesture.view.center.x + transition.x, panGesture.view.center.y +transition.y);
[panGesture setTranslation:CGPointMake(0,0) inView:self.view];}
Related
Here's my GameViewController.m file:
- (void)viewDidLoad {
[super viewLoad];
.
.
.
_board = [[TwinstonesBoardModel alloc] init];
[_board setToInitialStateMain];
TwinstonesStoneView* twinstonesBoard = [[TwinstonesStoneView alloc]
initWithMainFrame:CGRectMake(12, 160, 301.5, 302.5)
andBoard:_board];
[self.view addSubview:twinstonesBoard];
TwinstonesStonesView *stoneOne = [[TwinstonesStoneView alloc] init];
TwinstonesStonesView *one = (TwinstonesStoneView*)stoneOne.stoneUnoView;
TwinstonesStonesView *stoneTwo = [[TwinstonesStoneView alloc] init];
TwinstonesStonesView *two = (TwinstonesStoneView*)stoneTwo.stoneDueView;
UISwipeGestureRecognizer* swipeLeft = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:#selector(swipeLeft:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft.numberOfTouchesRequired = 1;
[one addGestureRecognizer:swipeLeft];
[two addGestureRecognizer:swipeLeft];
Here's the relevant code in my TwinstonesStoneView.m file:
#implementation TwinstonesStoneView
{
NSMutableArray* _array;
NSMutableArray* _emptyArray;
CGRect _frame;
NSUInteger _column;
NSUInteger _row;
TwinstonesBoardModel* _board;
int _i;
}
- (id)initWithMainFrame:(CGRect)frame andBoard:
(TwinstonesBoardModel*)board
{
if (Self = [super initWithFrame:frame])
{
float rowHeight = 49.0;
float columnWidth = 49.0;
float barrierHorizontalRowHeight = 12.5;
float barrierVerticalColumnWidth = 12.5;
for (int row = 0; row < 5; row++)
{
for (int col = 0; col < 5; col++)
{
TwinstonesStonesView* square = [[TwinstonesStoneView alloc]
initWithEmptyFrame:CGRectFrame(//spacial equations, not important)
column:col
row:row
board:board];
BoardCellState state = [board cellStateAtColumn:col andRow:row];
if (state == BoardCellStateStoneOne) {
// _stoneUnoView is a public property
// 'stoneOneCreation' creates a UIImageView of the stone
_stoneUnoView = [UIImageView stoneOneCreation];
[self addSubview:square];
[square addSubview:_stoneUnoView];
[_array insertObject:_stoneUnoView atIndex:0];
} else if (state == BoardCellStateStoneTwo) {
// same idea as above
_stoneDueView = [UIImageView stoneTwoCreation];
[self addSubview:square];
[square addSubview:_stoneDueView];
[_array insertObject:_stoneDueView atIndex:1];
} else {
// based on the 'init' method I write below, I assumed this
// would return an empty square cell
[self addSubview:square];
[_emptyArray insertObject:square atIndex:_i];
_i++;
}
}
}
self.backgroundColor = [UIColor clearColor];
}
return self;
}
- (UIView*)stoneUnoView {
return _stoneUnoView;
}
- (UIView*)stoneDueView {
return _stoneDueView;
}
- (id)initWithEmptyFrame:(CGRect)frame
column:(NSUInteger)column
row:(NSUInteger)row
board:(TwinstonesBoardModel*)board
{
self = [super initWithFrame:frame];
return self;
}
- (void)swipeLeft:(UIGestureRecognizer*)recognizer
{
NSLog(#"Swipe Left");
UIView* view = recognizer.view;
[self move:CGPointMake(-1, 0) withView:view];
}
- (void)move:(CGPoint)direction withView:view {
// whatever code I decide to put for stone movement
}
#end
I apologize for the (probably) unnecessary length, I've just trying to figure this out for a couple days and have had no luck. Here's the bullet points of what I'm trying to do:
1. setInititalStateMain sets the placements of two stones in a 5x5 grid
2. In GameViewController.m, I'm trying to capture the 'stoneUnoView' and
'stoneDueView' properties (set in the TwinstonesStoneView.m file), give them swipe gestures, and interact with them using the methods provided in TwinstonesStoneView.m.
3. Am I generating too many views? The catch is that everything works in terms of what I'm able to see on my IPhone when I run the program. The stones show up on my screen, but when I try to interact with them, not even the 'NSLog' message shows up in the console.
4. The 'stoneOneCreation' method (and ...two) are UIImageView's, but, as you can see, I store them in a UIView pointer.
5. I also used '[one setUserInteractionEnabled:YES]' (and ...two) but that didn't help either.
6. If I add the gesture recognizer to self.view, everything works (the displays of the stones, gameboard, and other graphics appears, and when I interact with ANY part of the screen, I output the directions to the console......just not stone-specific interaction).
Thank you so very much for putting up with all of this, this will really help if someone knows what's wrong. PS: all file #import's are correct, so that isn't a problem.
I am using XCode 7, Objective-C language, and developing for iOS
Anthony
One thing that catches my eye is I don't think you can add the same gesture recognizer to multiple views. I suspect, at best, only the last view is actually receiving it.
try this but i am not sure try this, just create 2 swipe gestures
in GameViewController.m
- (void)viewDidLoad {
[super viewLoad];
//.... other code
//comment below line
// UISwipeGestureRecognizer* swipeLeft = [[UISwipeGestureRecognizer alloc]
//initWithTarget:self //setting self is the problem is the problem
//action:#selector(swipeLeft:)];
UISwipeGestureRecognizer* swipeLeft = [[UISwipeGestureRecognizer alloc]
initWithTarget:stoneOne //set target will be one
action:#selector(swipeLeft:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft.numberOfTouchesRequired = 1;
[one addGestureRecognizer:swipeLeft];
UISwipeGestureRecognizer* swipeLeft_2 = [[UISwipeGestureRecognizer alloc]
initWithTarget:stoneTwo //this will be two
action:#selector(swipeLeft:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft.numberOfTouchesRequired = 1;
[two addGestureRecognizer:swipeLeft_2]; //set the gesture
}
u are setting the gesture to self which means the actions are sent to GameViewController.m but we want actions to be in TwinstonesStoneView.m so change the target to view to TwinstonesStoneView. And also if it is image views u are adding gestures, then enable user interaction for each image views setUserInteractionEnabled:
just try it
Here's my GameViewController.m file:
- (void)viewDidLoad {
[super viewLoad];
.
.
.
_board = [[TwinstonesBoardModel alloc] init];
[_board setToInitialStateMain];
TwinstonesStoneView* twinstonesBoard = [[TwinstonesStoneView alloc]
initWithMainFrame:CGRectMake(12, 160, 301.5, 302.5)
andBoard:_board];
[self.view addSubview:twinstonesBoard];
TwinstonesStonesView *stoneOne = [[TwinstonesStoneView alloc] init];
TwinstonesStonesView *one = (TwinstonesStoneView*)stoneOne.stoneUnoView;
TwinstonesStonesView *stoneTwo = [[TwinstonesStoneView alloc] init];
TwinstonesStonesView *two = (TwinstonesStoneView*)stoneTwo.stoneDueView;
UISwipeGestureRecognizer* swipeLeft = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:#selector(swipeLeft:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft.numberOfTouchesRequired = 1;
[one addGestureRecognizer:swipeLeft];
[two addGestureRecognizer:swipeLeft];
Here's the relevant code in my TwinstonesStoneView.m file:
#implementation TwinstonesStoneView
{
NSMutableArray* _array;
NSMutableArray* _emptyArray;
CGRect _frame;
NSUInteger _column;
NSUInteger _row;
TwinstonesBoardModel* _board;
int _i;
}
- (id)initWithMainFrame:(CGRect)frame andBoard:
(TwinstonesBoardModel*)board
{
if (Self = [super initWithFrame:frame])
{
float rowHeight = 49.0;
float columnWidth = 49.0;
float barrierHorizontalRowHeight = 12.5;
float barrierVerticalColumnWidth = 12.5;
for (int row = 0; row < 5; row++)
{
for (int col = 0; col < 5; col++)
{
TwinstonesStonesView* square = [[TwinstonesStoneView alloc]
initWithEmptyFrame:CGRectFrame(//spacial equations, not important)
column:col
row:row
board:board];
BoardCellState state = [board cellStateAtColumn:col andRow:row];
if (state == BoardCellStateStoneOne) {
// _stoneUnoView is a public property
// 'stoneOneCreation' creates a UIImageView of the stone
_stoneUnoView = [UIImageView stoneOneCreation];
[self addSubview:square];
[square addSubview:_stoneUnoView];
[_array insertObject:_stoneUnoView atIndex:0];
} else if (state == BoardCellStateStoneTwo) {
// same idea as above
_stoneDueView = [UIImageView stoneTwoCreation];
[self addSubview:square];
[square addSubview:_stoneDueView];
[_array insertObject:_stoneDueView atIndex:1];
} else {
// based on the 'init' method I write below, I assumed this
// would return an empty square cell
[self addSubview:square];
[_emptyArray insertObject:square atIndex:_i];
_i++;
}
}
}
self.backgroundColor = [UIColor clearColor];
}
return self;
}
- (UIView*)stoneUnoView {
return _stoneUnoView;
}
- (UIView*)stoneDueView {
return _stoneDueView;
}
- (id)initWithEmptyFrame:(CGRect)frame
column:(NSUInteger)column
row:(NSUInteger)row
board:(TwinstonesBoardModel*)board
{
self = [super initWithFrame:frame];
return self;
}
- (void)swipeLeft:(UIGestureRecognizer*)recognizer
{
NSLog(#"Swipe Left");
UIView* view = recognizer.view;
[self move:CGPointMake(-1, 0) withView:view];
}
- (void)move:(CGPoint)direction withView:view {
// whatever code I decide to put for stone movement
}
#end
I apologize for the (probably) unnecessary length, I've just trying to figure this out for a couple days and have had no luck. Here's the bullet points of what I'm trying to do:
setInititalStateMain sets the placements of two stones in a 5x5 grid
In GameViewController.m, I'm trying to capture the 'stoneUnoView' and 'stoneDueView' properties (set in the TwinstonesStoneView.m file), give them swipe gestures, and interact with them using the methods provided in TwinstonesStoneView.m.
Am I generating too many views? The catch is that everything works in terms of what I'm able to see on my IPhone when I run the program. The stones show up on my screen, but when I try to interact with them, not even the 'NSLog' message shows up in the console.
The 'stoneOneCreation' method (and ...two) are UIImageView's, but, as you can see, I store them in a UIView pointer.
I also used '[one setUserInteractionEnabled:YES]' (and ...two) but that didn't help either.
If I add the gesture recognizer to self.view, everything works (the displays of the stones, gameboard, and other graphics appears, and when I interact with ANY part of the screen, I output the directions to the console......just not stone-specific interaction).
Thank you so very much for putting up with all of this, this will really help if someone knows what's wrong. PS: all file #import's are correct, so that isn't a problem.
I am using XCode 7, Objective-C language, and developing for iOS
Anthony
You should add different instances of the swipe gesture recogniser to different instances of UIView.
UISwipeGestureRecognizer* swipeLeft1 = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:#selector(swipeLeft:)];
swipeLeft1.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft1.numberOfTouchesRequired = 1;
[one addGestureRecognizer:swipeLeft1];
UISwipeGestureRecognizer* swipeLeft2 = [[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:#selector(swipeLeft:)];
swipeLeft2.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft2.numberOfTouchesRequired = 1;
[two addGestureRecognizer:swipeLeft2];
I assume it is because the gestire recogniser has readonly view property.
Hi may be user interaction is disabled for that views , gestures working only for the views which have the userInteractionEnable = YES.
Code:
Header file:
#interface game : UIViewController
{
UIImageView *anh[8][8];
}
-(void)SwipeToMove:(id)sender;
#end
Implementation file:
- (void)viewDidLoad
{
[super viewDidLoad];
UISwipeGestureRecognizer *move = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(SwipeToMove:)];
[move setDirection:(UISwipeGestureRecognizerDirectionUp)];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
anh[i][j]=[[UIImageView alloc] initWithFrame:CGRectMake(0+40*i,200 + 40*j,40,40)];
anh[i][j].userInteractionEnabled = YES;
[self.view addSubview:anh[i][j]];
anh[i][j].image = [UIImage imageNamed:#"Earth.png"];
[anh[i][j] addGestureRecognizer:move];
}
}
}
-(void)SwipeToMove:(id)sender{
NSLog(#"ok");
}
The UIImageView works as expected, but UISwipeGestureRecognizer is not working. Then, I tried this:
- (void)viewDidLoad
{
[super viewDidLoad];
UIImageView *image1 = [[UIImageView alloc]initWithFrame:CGRectMake(100,50,40,40)];
label1.image = [UIImage imageNamed:#"Ceres.png"];
[self.view addSubview:image1];
image1.userInteractionEnabled = YES;
image1.image = [UIImage imageNamed:#"Earth.png"];
UISwipeGestureRecognizer *move = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(SwipeToMove:)];
[move setDirection:(UISwipeGestureRecognizerDirectionUp)];
[image1 addGestureRecognizer:move];
-(void)SwipeToMove:(id)sender{
NSLog(#"OK");
}
It's working, but I need an array of UIImageViews to make my app. Please help me.
Your code is only creating one gesture recognizer, but you try to add it many image views. You need to create the gesture recognizer inside the loop so you create a new one for each image view.
(void)viewDidLoad
{
[super viewDidLoad];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
UISwipeGestureRecognizer *move = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(SwipeToMove:)];
[move setDirection:(UISwipeGestureRecognizerDirectionUp)];
anh[i][j]=[[UIImageView alloc] initWithFrame:CGRectMake(0+40*i,200 + 40*j,40,40)];
anh[i][j].userInteractionEnabled = YES;
[self.view addSubview:anh[i][j]];
anh[i][j].image = [UIImage imageNamed:#"Earth.png"];
[anh[i][j] addGestureRecognizer:move];
}
}
}
You are adding the same gesture recognizer all the time to the different images, so it will take just the last one for my understanding, because you have just created one. Create an aux recognizer like an aux var inside the loop and give a tag to every UIImageView so you can access to the tag and distinguish every swipe in every image, when it has happened in your app. It should work. But basically :
for (....){
// create aux gesture recognizer and assign it to the UIImageView
}
Hope it helps.
I am trying to add a tap gesture from a subclassed UIImageView and then control the tap from the View Controller. I am not getting any compiling errors but "addSubview" is not displaying any image. How can make the UIImageView to be displayed?
If I try to control the tap and pan gestures from the subclassed UIImageVIew I have no problems but I would like to control these functions from the View Controller
Relevant code looks like this.
UIImageView subclass
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
//self.userInteractionEnabled = YES;
previewController = [[PreviewController alloc]init];
[previewController self];
[self addSubview:character];
// Tap Initialization code
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:(PreviewController *)self.previewController action:#selector(addCharacter:)];
[self addGestureRecognizer:tap];
self.userInteractionEnabled = YES;
}
return self;
}
View Controller
- (void)addCharacter:(UITapGestureRecognizer *)t
{
NSLog(#"add character");
imageNSArray = [NSMutableArray array];
uiImg = [UIImage imageNamed:#"homer.png"];
CGPoint loc = [t locationInView:self.view];
character = [[UIImageView alloc] initWithImage:uiImg];
character.center = loc;
[imageNSArray addObject:character];
//Locate the imageNSArray on frameImageView area only.
[self.view addSubview:character];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panCharacter:)];
[self.character addGestureRecognizer:pan];
character.userInteractionEnabled = YES;
}
put a view behind your subclassed imageView. Apply the gestureRecognition to the new View.
You can control your tap gesture from new view. Let me know if i am not clear, or if more info needed.
I think what you want is.. .you want to show a image when user taps on screen.
Do following steps:
1. drag & drop a tap gesture recognizer on default view of your view controller.
2. connect (ctrl +) gestureRecognizer with ViewController.m
Take a look at this code. (Just modified your code)
- (IBAction)onTap:(UITapGestureRecognizer *)sender {
NSLog(#"add character");
UIImage * uiImg = [UIImage imageNamed:#"sel.png"];
CGPoint loc = [sender locationInView:self.view];
UIImageView * character = [[UIImageView alloc] initWithImage:uiImg];
character.center = loc;
[self.view addSubview:character];
}
Let me know if this is not what you want…
Edit
better go for this code… No need to do above steps.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onTap:)];
[self.view addGestureRecognizer:tap];
self.view.userInteractionEnabled = YES;
}
- (void)onTap:(UITapGestureRecognizer *)sender
{
NSLog(#"add character");
UIImage * uiImg = [UIImage imageNamed:#"sel.png"];
CGPoint loc = [sender locationInView:self.view];
UIImageView * character = [[UIImageView alloc] initWithImage:uiImg];
character.center = loc;
[self.view addSubview:character];
}
I have a NSMutableArray of UILabels.
I need to be able to select a particular UILabel in this NSMutableArray upon a user touch, and move the center of this touch UILabel to where the user drags their finger to.
I am able to move a particular UILabel in my bunchOfLabels NSMutableArray by doing:
UIGestureRecognizer *gestureRecognizer;
touchPosition = [gestureRecognizer locationInView:mainView];
NSLog(#"x: %f", touchPosition.x);
UILabel *temp;
temp = [bunchOfLabels objectAtIndex:0];
temp.center = touchPosition;
this will always move the first label, even if the user touches 2nd, 3rd, or whatever label.
but I need to be able to say, move objectAtIndex:4 UILabel anywhere the user touches and drags on a objectAtIndex:4 UILabel to.
I'm a beginner, could somebody please help me out with this? Thanks!
Added info:
I'm currently using UIPanGestureRecognizer, like this:
-(void)setupLabels {
bunchOfLabels = [[NSMutableArray alloc] initWithCapacity:[characters count]];
for (int i=0; i < [characters count]; i++) {
int xPosition = arc4random() % 518;
int yPosition = arc4random() % 934;
UILabel *tempCharacterLabel = [[UILabel alloc] initWithFrame:CGRectMake(xPosition, yPosition, 60, 60)];
tempCharacterLabel.text = [characters objectAtIndex:i]; // characters is another NSMutableArray contains of NSStrings
[tempCharacterLabel setUserInteractionEnabled:YES];
[bunchOfLabels addObject:tempCharacterLabel];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panElement:)];
[panGesture setMaximumNumberOfTouches:2];
[[bunchOfLabels objectAtIndex:i] addGestureRecognizer:panGesture];
}
}
-(void)panElement:(UIPanGestureRecognizer *)gestureRecognizer
{
UILabel *temp;
temp = [bunchOfLabels objectAtIndex:1];
temp.center = touchPosition;
}
Everything is OK so far, but I've stuck at being able to move a particular UILabel in bunchOfLabels (in the code above, objectAtIndex:1).
Hurray!!! Got it!
I make panElement as below and it works now!
-(void)panElement:(UIPanGestureRecognizer *)gesture
{
UILabel *tempLabel = (UILabel *)gesture.view;
CGPoint translation = [gesture translationInView:tempLabel];
tempLabel.center = CGPointMake(tempLabel.center.x + translation.x, tempLabel.center.y + translation.y);
[gesture setTranslation:CGPointZero inView:tempLabel];
}
Thanks to those attempting to answer my question!