UIScrollView goes crazy when zooming? - objective-c

I've tried searching for answers for this, but I have no idea what to search for and I'm at wit's end. I've got a UIScrollView that, when zooming, completely flips out and the image glitches everywhere before disappearing entirely. It even manages to, on occasion, temporarily screw up other components that aren't even part of the UIScrollView in which the zooming is happening. I apologize I can't be more technical. I wouldn't even know which part of my code to look at.
I made a video, because I have no technical terminology to describe what's happening here. Any help would be appreciated.
https://www.youtube.com/watch?v=SvhqHI-3_g8
The red is my current background of the UIScrollView. Don't mind that.
ViewController.h
#interface ViewController : UIViewController <UIActionSheetDelegate, UIImagePickerControllerDelegate, UIScrollViewDelegate>
#property (strong, nonatomic) UIImage *workingImage;
#property (weak, nonatomic) IBOutlet UIImageView *chosenImageView;
#property (weak, nonatomic) IBOutlet UIScrollView *imageScroller;
-(IBAction)cameraButtonPressed;
#end
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.imageScroller.minimumZoomScale = 1.00f;
self.imageScroller.maximumZoomScale = 15.0f;
self.imageScroller.contentSize = self.imageScroller.frame.size;
self.imageScroller.scrollEnabled = YES;
}
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.chosenImageView;
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *chosenImage = [info objectForKey:UIImagePickerControllerOriginalImage];
[self.chosenImageView setImage:chosenImage];
[self.imageScroller setContentSize:chosenImage.size];
[self dismissViewControllerAnimated:YES completion:nil];
}

See if this article helps. It seems the missing ScrollViewDidZoom method might be key to maintaining the zoomed view in place. http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content

Related

Building a Camera Application... UIScrollView will not zoom

I'm building a camera application, and I can't get the zooming on the image to work. I honestly don't know where to go from here, I'm sure it's some dumb mistake that I'm missing though. The app sets the chosenImageView to the workingImage (picture from the camera). When I try to zoom, nothing happens.
ViewController.h
#interface ViewController : UIViewController <UIActionSheetDelegate, UIImagePickerControllerDelegate, UIScrollViewDelegate>
#property (strong, nonatomic) UIImage *workingImage;
#property (weak, nonatomic) IBOutlet UIImageView *chosenImageView;
#property (weak, nonatomic) IBOutlet UIScrollView *imageScroller;
-(IBAction)cameraButtonPressed;
#end
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.imageScroller.minimumZoomScale = 0.01f;
self.imageScroller.maximumZoomScale = 6.0f;
self.imageScroller.contentSize = self.imageScroller.frame.size;
self.imageScroller.scrollEnabled = YES;
self.navigationController.navigationBar.tintColor = [UIColor blackColor];
}
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.chosenImageView;
}
Here was the problem. You have to control+drag from the UIScrollView to the View Controller to set the delegate.

Making a UIButton change a UIImageView image

I'm very new to programming and objective c so please go easy on me.
I would like a UIButton (which I'm using as an IBAction) to change an the image in a UIImageView when pressed. I put the UIImageView into a UIScrollView in the storyboard but I hope I can still programmatically change the image.
I have searched absolutely everywhere for an answer for hours but nothing has worked for me either because it wasn't the right solution or I didn't do it properly.
I have tried this code and some more but they always return a "Thread 1: signal SIGABRT" when I press the button:
imageView.image = [UIImage imageNamed: #"Ruler pic inch.png"];
Here is my code so far:
ViewController.h
#import <UIKit/UIKit.h>
#import <iAd/iAd.h>
#interface ViewController : UIViewController <ADBannerViewDelegate, UIScrollViewDelegate> {
ADBannerView *adView;
BOOL bannerIsVisible;
IBOutlet UIScrollView *scrollView;
IBOutlet UIImageView *imageView;
IBOutlet UIButton *proVersion;
IBOutlet UIButton *howToUse;
}
- (IBAction)switchUnit:(id)sender;
#property (nonatomic, assign) BOOL bannerIsVisible;
#property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
#property (nonatomic, retain) IBOutlet UIImageView *imageView;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize bannerIsVisible;
#synthesize scrollView;
#synthesize imageView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Hide status bar:
[[UIApplication sharedApplication] setStatusBarHidden:YES];
// iAd:
adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
adView.frame = CGRectOffset(adView.frame, 0, -50.0f);
[self.view addSubview:adView];
adView.delegate=self;
self.bannerIsVisible=NO;
// Setting scrollview content size to size of image
scrollView.contentSize = CGSizeMake(320,2246);
}
-(void)bannerViewDidLoadAd:(ADBannerView *)banner
{
if (!self.bannerIsVisible) {
[UIView beginAnimations:#"animateAdBannerOn" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0, 50.0f);
[UIView commitAnimations];
self.bannerIsVisible = YES;
}
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
if (self.bannerIsVisible) {
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0, -50.0f);
[UIView commitAnimations];
self.bannerIsVisible = NO;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)switchUnit:(id)sender {
// CODE THAT MAKES IMAGE CHANGE GOES HERE (I thought...)
}
#end
Help would be greatly appreciated. I'm fed up with it. I've probably done a silly mistake somewhere but I can't work it out. Thanks in advance.
General pointers:
Try to use #property for all your instance variables (it'll server you well in future)
Don't use #synthesize (the compiler does a better job of it for you)
If you have a property bob, access it by using self.bob
Turn on ARC (looks like you don't have it on currently)
Best not to have any spaces in image names
To be clear on properties, when you have a property you don't need to create instance variables in between {} of the #interface. These should be removed in order to prevent multiple definitions. The auto-synthesising done by the compiler will define the instance variables for you but you should always use the property to access the value (as in item 3 above).
That said, your - (IBAction)switchUnit:(id)sender looks fine, if a little empty. The code should be something like:
self.imageView.image = [UIImage imageNamed:#"Ruler_pic_inch.png"];
For it to work, the image Ruler_pic_inch.png would need to be in your bundle (which means it's in Xcode project and set to copy during the build.
Again, that said, your problem would seem to relate to you being confused somewhere. SIGABRT type issues would usually be picked up by the compiler and notified to you as a warning saying something like "some object may not respond to some selector". If you see any of those, look at them and work out why you're trying to ask the object a question it doesn't understand.
If you don't see any compiler warnings, then you've told the compiler that an object is going to be of one type and then actually set it to something else. In this case I'd look at your IBOutlets in Storyboard and check that they are actually set to the correct destination view (disconnect and reconnect them all to be sure).

UIScrollView + UIImage and zoom: not fluid

I have view controller, and inside that I have a UIScrollView, for managing the zoom, and a UIImage.
Now I'm handling the zoom effect with UIScrollViewDelegate delegate and method viewForZoomingInScrollView:... but the result is very poor, definitely not fluid!
This is my code:
#import "ImageViewController.h"
#interface ImageViewController () <UIScrollViewDelegate, UIActionSheetDelegate>
#property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#end
#implementation ImageViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView.delegate = self;
self.scrollView.maximumZoomScale = 3.0;
// some code
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.imageView;
}
// last update
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
if ([self.scrollView zoomScale] < 1.0) {
[self.scrollView setZoomScale:1.0];
}
}
// some other methods...
#end
This is the storyboard view:
I'm not using a Pinch Gesture Recognizer.
All images are quite small like 640x480.
Thanks
P.S. this is a continue of UICollectionView and images.
Checkout out this tutorial I wrote. The first part is exactly what you need to implement.
This has been addressed in other posts:
Zooming image views with autolayout:
Centering logic for autolayout or springs and struts

Unable to implement simple view scrolling in iOS

I'm having a hard time implementing a simple scroll on my detail view.
The app is straightforward with a Master and Detail views.
When the user taps an item on Master, the Detail view is pushed with larger photo, blog text and etc.
I would like the entire Detail view to scroll, so if the picture is tall, or the text is long, they can scroll vertically to see/read more. I do not want the user to scroll these items individually. It should feel like webpage scrolling.
Currently my Detail view loads OK but I can't make it scroll.
My DetailViewController.h
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController {
IBOutlet UILabel *postTextLabel; // wired to Text Label
IBOutlet UILabel *postAuthorNameLabel; // wired to Author Label
}
#property (strong, nonatomic) id detailItem;
#end
My DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
- (void)configureView;
#end
#implementation DetailViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self configureView];
}
- (void)configureView
{
if (self.detailItem) {
NSDictionary *post = self.detailItem;
NSString *postText = [post objectForKey:#"post_text"];
NSString *postAuthorName = [post objectForKey:#"post_author_name"];
postTextLabel.text = postText;
postAuthorNameLabel.text = postAuthorName;
}
}
#end
Structure on IB:
Any ideas on what's missing to make this work?
I would do the following:
1)(optional)turn your View into a scrollview by dragging it into the view in the scruture list on the side.
2)link the scrollView into your viewcontroller .h and make an Outlet connection something like this
#property (strong, nonatomic) IBOutlet UIScrollView *scroller;
(make sure you add #synthesize in the .m if you add this manually)
and make sure it is connected in IB!
3)set the contentsize of the scrollview in viewDidLoad method
scroller.contentSize = CGSizeMake(320,550);
NOTE: IBOutlet UILabel *postTextLabel; should actually probably be a UITextView so you can access ContentSize
Which would allow for the following.
CGRect frame = postTextLabel.frame;
frame.size = postTextLabel.contentSize;
postTextLabel.frame = frame;
scroller.contentSize = CGSizeMake(320, frame.size.height+200);//200 or how ever much space is above the textView
and again that only works if you use a UITextView
for ipad replace 320 with 768 or 1024, or whichever depending on orientation
The best way to connect it in IB is like this holding down control and dragging to the .h file
and make sure it is set to automatic like in the picture, and pointing to> the .h of your view.
Adding it like this also automatically adds the #synthesize for you.
Make sure UserInteractionsEnabled are checked here for our scrollview

How do I access or manipulate variables of one class from another in Xcode

I am a novice to IOS programming hence struggling a bit with the below problem. I will do my best to describe the problem and any help is greatly appreciated.
I have the following created:
AboutViewController (.h, .m and .xib ) which has two subviews called - mainView, infoView. mainView and infoView interfaces are created in the XIB file.
TestView ( View to deal with initiating, toggling between mainView and infoView )
TestView.h is as follows:
#interface TestView : UIView {
IBOutlet UIView *mainView;
IBOutlet UIView *infoView;
UILabel *lbltitle;
UIImageView *imgIcon;
IBOutlet UITextView *txtInfo1;
IBOutlet UITextView *txtInfo2;
IBOutlet UITextView *txtInfo3;
}
#property (nonatomic, retain) IBOutlet UILabel *lbltitle;
#property (nonatomic, retain) IBOutlet UIImageView *imgIcon;
TestView.m is as follows:
#import "TestView.h"
#import <QuartzCore/QuartzCore.h>
#implementation TestView
#synthesize lbltitle, imgIcon;
-(void)awakeFromNib
{
[self addSubview:mainView];
}
In portrait mode the views are working great but when it comes to landscape mode, the views are all kinda screwed up. I tried to use the XIB but I guess you can only do so much so I decided to do this programmatically.
In the AboutViewController.m, I am trying to override willAnimateRotationToInterfaceOrientation method and place the objects based on the orientation. When I put breakpoints, I can see that code is being called except it is not translating into the UI i.e., no change in the UI. What am I doing wrong ? Should I be approaching this in a different way. Any suggestions or guidance is greatly appreciated.
- (void)willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
TestView *t = [[TestView alloc]init];
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
[t.imgIcon setFrame:CGRectMake(10,74,165,190)];
[t.lbltitle setFrame:CGRectMake(20, 10, 387, 21)];
}
else
{
[t.imgIcon setFrame:CGRectMake(10,74,165,190)];
[t.lbltitle setFrame:CGRectMake(189, 10, 387, 21)];
}
}
Well the particular problem is you manipulate a view that you just created using
TestView *t = [[TestView alloc]init];
You don't display the view anywhere, so it sits in memory. You can apply all changes you want, but to be able to see them, you must first display the view:
Find the appropriate parent and do:
[parentview addSubview:t];
In more general terms you shouldn't be creating new views in the rotation handling code.