UITapGestureReconizer error - xcode

I am getting errors with my UITapGestureReconizer like "UITapGestureReconizer undeclared". Because UITapGestureReconizer is inside a concrete class should it not be declared? and how do I fix it... below is where it first shows up in the code.
- (void)loadView {
[super loadView];
// set the tag for the image view
[imageView setTag:ZOOM_VIEW_TAG];
// add gesture recognizers to the image view
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[imageView addGestureRecognizer:doubleTap];
[doubleTap release];
UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTwoFingerTap:)];
[imageView addGestureRecognizer:twoFingerTap];
[twoFingerTap release];
[doubleTap setNumberOfTapsRequired:2];
[twoFingerTap setNumberOfTouchesRequired:2];
// calculate minimum scale to perfectly fit image width, and begin at that scale
float minimumScale = [imageScrollView frame].size.width / [imageView frame].size.width;
[imageScrollView setMinimumZoomScale:minimumScale];
[imageScrollView setZoomScale:minimumScale];
}

UITapGestureRecognizer is a part of UIKit, so it should be declared as long as you’re importing <UIKit/UIKit.h> somewhere. One problem I see in your code, though, is this:
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[imageView addGestureRecognizer:doubleTap];
[doubleTap release];
…
[doubleTap setNumberOfTapsRequired:2];
At the point where you call [doubleTap setNumberOfTapsRequired:2], you don’t have a valid reference to doubleTap. It’s most likely retained by imageView, but that’s an implementation detail that you can’t rely on. Move the call to -setNumberOfTapsRequired: before the call to -release to ensure that this doesn’t break in a future version of iOS.

Related

Activity Indicator will not go away

I am using the following code to show an Activity Indicator while some data is loading. The problem is that when I try to hide it again. The Activity Indicator stays put. The screen lightens a bit but that is it.
To show it:
self.overlayView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.overlayView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3];
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicator.center = self.overlayView.center;
[self.overlayView addSubview:self.activityIndicator];
[self.activityIndicator startAnimating];
[self.tableView addSubview:self.overlayView];
To hide it:
[self.activityIndicator stopAnimating];
[self.overlayView removeFromSuperview];
Try to add your overlayView to the superview of your tableView :
[self.view.superview addSubview:self.overlayView];
I figured it out with a combination of stackoverflow questions. Here is my code to show the UIActivityIndicatorView
-(void)loadView {
[super loadView];
self.overlayView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.overlayView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3];
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicator.center = self.overlayView.center;
[self.overlayView addSubview:self.activityIndicator];
[self.tableView addSubview:self.overlayView];
[self.activityIndicator startAnimating];
}
Here is the code to hide it. It looks like putting the code in the loadView event made all the difference.
[overlayView removeFromSuperview];

xcode: segmented control appears on sim, not on device

I have an iPad app with several segmented controls, including one view with two controls.
On that view, everything shows in the sim, both normal and retina. However, in the device, only one shows.
Below is the code that does not show on the device.. I have checked and all the images that make up the control are copied in the bundle resources. I've tried removing, cleaning, etc. No joy. I must be missing something (hopefully simple)..
UISegmentedControl *controls = [[UISegmentedControl alloc] initWithItems:
[NSArray arrayWithObjects:
[UIImage imageNamed:#"1.png"],
[UIImage imageNamed:#"2.png"],
[UIImage imageNamed:#"3.png"],
[UIImage imageNamed:#"4.png"],
[UIImage imageNamed:#"5.png"],
[UIImage imageNamed:#"6.png"],
[UIImage imageNamed:#"7.png"],
nil]];
CGRect frame = CGRectMake(35, 70, 700, 35);
controls.frame = frame;
}
[controls addTarget:self action:#selector(drawSegmentAction:) forControlEvents:UIControlEventValueChanged];
controls.segmentedControlStyle = UISegmentedControlStyleBar;
controls.momentary = YES;
controls.tintColor = [UIColor grayColor];
[self.view addSubview:controls];
}
For reference, this code in the same view does work:
For reference, this control code does work:
-(void) buildColorBar {
//NSLog(#"%s", __FUNCTION__);
UISegmentedControl *colorControl = [[UISegmentedControl alloc] initWithItems:
[NSArray arrayWithObjects: [UIImage imageNamed:#"White.png"],
[UIImage imageNamed:#"Red.png"],
[UIImage imageNamed:#"Yellow.png"],
[UIImage imageNamed:#"Green.png"],
[UIImage imageNamed:#"Blue.png"],
[UIImage imageNamed:#"Purple.png"],
[UIImage imageNamed:#"Black.png"],
nil]];
NSLog(#"Portrait");
CGRect frame = CGRectMake(35, 950, 700, 35);
colorControl.frame = frame;
// When the user chooses a color, the method changeBrushColor: is called.
[colorControl addTarget:self action:#selector(changeBrushColor:) forControlEvents:UIControlEventValueChanged];
colorControl.segmentedControlStyle = UISegmentedControlStyleBar;
// Make sure the color of the color complements the black background
colorControl.tintColor = [UIColor grayColor];
// Add the control to the window
[self.view addSubview:colorControl];
}
Is there a rule against using two segmented controls in one view?
I found that one image in the segmented control - while it looked like it was in the bundle - it wasn't. PITA, but at least, it works..

UIPickerController - want to show specific selection upon loading

I have a custom UIPickerView that is embedded into an UIActionsheet that comes up half the screen when called. Works great. The problem is that I want to have the barrelPicker be showing the 'most probable' results as the selection when it first comes up (after all the data has been loaded into it).
Prior to having the custom picker embedded in the action sheet, I had it in a UIViewController and was just calling "showProbableResults" (a custom method of mine) in the viewDidLoad method of the ViewController, because I knew at that point, the UIPickerView would be loaded up and ready to go. Is there an equivalent place for me to call this method now or do I need to rethink my whole design? Essentially, what I need is a place to call this after the UIPickerView has been loaded.
- (void)startWithDelegate:(UIViewController <ImageProcessingDelegate> *)sender
{
self.delegate = sender;
self.showFirstBottle = YES;
[self start];
}
- (void) start {
self.actionSheet = [[UIActionSheet alloc] initWithTitle:#"Choose Something"
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[self.actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 40, 0, 0);
NSLog(#"1.) About to alloc the picker");
self.vintagePicker = [[UIPickerView alloc] initWithFrame:pickerFrame];
self.vintagePicker.showsSelectionIndicator = YES;
self.vintagePicker.dataSource = self;
self.vintagePicker.delegate = self;
[self.actionSheet addSubview:self.vintagePicker];
[self.vintagePicker release];
UISegmentedControl *nextButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Next"]];
nextButton.momentary = YES;
nextButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
nextButton.segmentedControlStyle = UISegmentedControlStyleBar;
nextButton.tintColor = [UIColor blackColor];
[nextButton addTarget:self action:#selector(show:) forControlEvents:UIControlEventValueChanged];
[self.actionSheet addSubview:nextButton];
[nextButton release];
UISegmentedControl *backButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Back"]];
backButton.momentary = YES;
backButton.frame = CGRectMake(10, 7.0f, 50.0f, 30.0f);
backButton.segmentedControlStyle = UISegmentedControlStyleBar;
backButton.tintColor = [UIColor blackColor];
[backButton addTarget:self action:#selector(cancel:) forControlEvents:UIControlEventValueChanged];
[self.actionSheet addSubview:backButton];
[backButton release];
[self.actionSheet showInView:_delegate.parentViewController.tabBarController.view]; // show from our table view (pops up in the middle of the table)
[self.actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
One option is to create a reusable picker view, as shown here, and then call the #optional
-(void)setInitialPickerValueToRow:(int)i inComponent:(int)j animated:(BOOL)k{
[pickerView selectRow:i inComponent:j animated:k];
}
from any view controller or NSObject (such as your UIActionSheetDelegate).
Your other option is to set a standard pre-chosen selection, as follows:
self.vintagePicker = [[UIPickerView alloc] initWithFrame:pickerFrame];
self.vintagePicker.showsSelectionIndicator = YES;
self.vintagePicker.dataSource = self;
self.vintagePicker.delegate = self;
[self.actionSheet addSubview:self.vintagePicker];
[self.vintagePicker selectRow:0 inComponent:0 animated:NO];
You could also have different variables that you set, and have selectRow:inComponent:animated: access those, instead of being preset.
[self.vintagePicker selectRow:myRow inComponent:0 animated:NO];
Hope this helps!

Releasing UIImage after use

I want to learn the right way to alloc an uiimage and release it for memory management.
When i use the following code it crashes when deallocating,
if i dont use [imager release];
program doesnt crash but it shows a leak for imager. Any ideas for solution?
UIImage *imager = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:s#"nameofimage" ofType:#"jpg"]];
UIImageView *imageView = [[UIImageView alloc] initWithImage:imager];
[imageView release];
[imager release];
The right way of doing memory management is as you have done.
UIImage *imager = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"nameofimage" ofType:#"jpg"]];
UIImageView *imageView = [[UIImageView alloc] initWithImage:imager];
[imager release];
[imageView release];
May be it work if you first release the uiimage than uiimageview
I am not finding any mistake in this code. If the application crashes then check if you are using the same object reference anywhere else after it gets released.

How can I animate a content switch in an NSImageView?

I want to switch the image shown in an NSImageView, but I want to animate that change. I've tried various methods to do this. Hopefully one of you could suggest one that might actually work. I'm working with Cocoa for Mac.
As far as I know, NSImageView doesn't support animating image changes. However, you can place a second NSImageView on top of the first one and animate hiding the old one and showing the new one. For example:
NSImageView *newImageView = [[NSImageView alloc] initWithFrame: [imageView frame]];
[newImageView setImageFrameStyle: [imageView imageFrameStyle]];
// anything else you need to copy properties from the old image view
// ...or unarchive it from a nib
[newImageView setImage: [NSImage imageNamed: #"NSAdvanced"]];
[[imageView superview] addSubview: newImageView
positioned: NSWindowAbove relativeTo: imageView];
[newImageView release];
NSDictionary *fadeIn = [NSDictionary dictionaryWithObjectsAndKeys:
newImageView, NSViewAnimationTargetKey,
NSViewAnimationFadeInEffect, NSViewAnimationEffectKey,
nil];
NSDictionary *fadeOut = [NSDictionary dictionaryWithObjectsAndKeys:
imageView, NSViewAnimationTargetKey,
NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey,
nil];
NSViewAnimation *animation = [[NSViewAnimation alloc] initWithViewAnimations:
[NSArray arrayWithObjects: fadeOut, fadeIn, nil]];
[animation setAnimationBlockingMode: NSAnimationBlocking];
[animation setDuration: 2.0];
[animation setAnimationCurve: NSAnimationEaseInOut];
[animation startAnimation];
[imageView removeFromSuperview];
imageView = newImageView;
[animation release];
If your view is big and you can require 10.5+, then you could do the same thing with Core Animation, which will be hardware accelerated and use a lot less CPU.
After creating newImageView, do something like:
[newImageView setAlphaValue: 0];
[newImageView setWantsLayer: YES];
// ...
[self performSelector: #selector(animateNewImageView:) withObject: newImageView afterDelay: 0];
- (void)animateNewImageView:(NSImageView *)newImageView;
{
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration: 2];
[[newImageView animator] setAlphaValue: 1];
[[imageView animator] setAlphaValue: 0];
[NSAnimationContext endGrouping];
}
You'll need to modify the above to be abortable, but I'm not going to write all your code for you :-)
You could implement your own custom view that uses a Core Animation CALayer to store the image. When you set the contents property of the layer, the image will automatically smoothly animate from the old image to the new one.

Resources