iOS UIImageView doesn't show anything on iPad - ios

I have a scrollViewController, in viewDidLoad, I add an UIImageView to it:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.scrollView addSubview:self.imageView];
}
Then I set my image:
- (void)setImage:(UIImage *)image
{
self.scrollView.zoomScale = 1.0;
self.imageView.image = image;
self.imageView.frame = CGRectMake(0,0,image.size.width,image.size.height);
self.scrollView.contentSize = self.image ? self.image.size : CGSizeZero;
}
On iPhone, this works fine, but on iPad (SplitViewController Detail), it doesn't show anything.
I think the problem is, that on iPhone ViewDidLoad is called when there is already an image set, on iPad when the app launches, the detail is always on screen.
I tried to put the addSubview to setImage, this works, but when the user clicks another item, the two imageViewControllers overlay each other.
Could anyone help me? Thanks! :-)

The basics:
viewDidLoad is only called once the controller is loaded into memory. So in your SplitViewController the viewDidLoad method is invoked immediately after launching the app.
My suggestion:
Add a UIImageView from InterfaceBuilder and connect it to your controller using a IBOutlet. This is the easiest way to reach the goal. I assume you're using a storyboard?!
right click drag the outlet to your header:
enter a name for your property and click connect
This way you can access your UIImageView in your implementation and you're good to go. No need to add it programmatically.
For further informations have a look at this tutorial: http://klanguedoc.hubpages.com/hub/IOS-5-A-Beginners-Guide-to-Storyboard-Connection

Before adding second imageViewController, you should remove first imageViewController
Try this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//_imageView variable is created by outlet, or you can do it by programmatically
_imageView.image = [UIImage imageNamed:#"1"];
}
- (void) setNewImage
{
[_imageView removeFromSuperview];
_imageView.image = [UIImage imageNamed:#"2"];
}

Related

UIImagePickerController takePicture Dismisses Controller

I have a custom UIImagePickerController that works nicely, only I am facing one issue that I feel should be fairly simple - I just have yet to figure out the solution.
Upon touching my custom added "photo" button, I have it targeted to the build in takePicture method of the UIIPC. Here is my code
#interface CustomCameraController ()
#end
#implementation CustomCameraController {
CGFloat width, height;
}
- (instancetype)init {
if (self = [super init]) {
width = self.view.frame.size.width, height = self.view.frame.size.height;
self.allowsEditing = YES;
self.sourceType = UIImagePickerControllerSourceTypeCamera;
self.showsCameraControls = NO;
self.toolbarHidden = YES;
[self buildCameraOverlay];
}
return self;
}
- (void)buildCameraOverlay {
UIView *customOverlay = [UIView alloc] ...
// ... Custom overlay setup done here
_takePhoto = [[CustomButton alloc] initWithFrame:CGRectMake(0, 0, heightBottomBar*.5, heightBottomBar*.5)];
_takePhoto.center = CGPointMake(bottomBar.frame.size.width/2, bottomBar.frame.size.height/2);
[_takePhoto setImage:[UIImage imageNamed:#"camera button icon"] forState:UIControlStateNormal];
[_takePhoto addTarget:self action:#selector(takePicture) forControlEvents:UIControlEventTouchUpInside];
[bottomBar addSubview:_takePhoto];
// ...
self.cameraOverlayView = customOverlay;
}
This is done in my custom controller CustomCameraController init call.
The problem is, upon taking the picture via takePicture, the camera shutter goes off, everything works just fine, but the controller dismisses itself. I'm trying to figure out how to stop it from closing immediately after taking the picture, so I can A)present the taken picture, and B) give the user the option to choose the image or cancel and retake another one (returning to the camera)
If anyone knows why this happens or something that I am missing / doing incorrectly please let me know. I'm sure it's a simple answer - just can't seem to figure it out. Thanks!
The most common reason for such a weird behaviour is usually lack of delegate methods (for UIImagePickerController in this case) or their wrong implementation.

UIImageView set image programmatically bug

I have a UIImageView in a storyboard, connected to the header of the subclassed UIViewController like this:
#property (retain, nonatomic) IBOutlet UIImageView *displayPhoto;
In the .m of the UIViewController subclass, I try to set the image of the displayPhoto.
#synthesize displayPhoto;
-(void)awakeFromNib {
UIImage *image = [UIImage imageNamed:#"dp.jpg"];
[displayPhoto setImage:image];
displayPhoto.layer.cornerRadius = displayPhoto.image.size.width/2;
[self.view addSubview:displayPhoto];
}
but it does absolutely nothing. If I add one more line, adding another view of the image like so: [self.view addSubview:[[UIImageView alloc] initWithImage:image]];, making my methodf
#synthesize displayPhoto;
-(void)awakeFromNib {
UIImage *image = [UIImage imageNamed:#"dp.jpg"];
[self.view addSubview:[[UIImageView alloc] initWithImage:image]];
[displayPhoto setImage:image];
displayPhoto.layer.cornerRadius = displayPhoto.image.size.width/2;
[self.view addSubview:displayPhoto];
}
It suddenly starts working and adds to instances of the image to the view. One in the top left corner (from the line I added) and a second in the storyboard image location.
What's changing? How is adding that one line making my code work and is there any work around so I can make the image just show up as normal?
If you added the UIImage in your storyboard and connected the outlet correctly, there is no need to create a new image programmatically. Try this.
- (void) viewDidLoad {
[super viewDidLoad];
self.displayPhoto.image = [UIImage imageNamed:#"dp.jpg"];
}
Check the connection of imageview to storyboard will solve your problem.
Use this:
self.imgObj.image=[UIImage imageNamed:#"Your string"];

Why setNeedsDisplay required when initWithNibName used

I have custom UIViewController class called MSPageViewController with and associated nib file. I have an IBOutlet which is a UIImageView called pageImage.
Now, I want to use this view controller in another UIViewController which will display a series of my custom MSPageViewController in a UIPageViewController. So, I use the following code:
// alloc and init my custom view controller
MSPageViewController *page1 = [[MSPageViewController alloc] initWithNibName:#"MSPageViewController" bundle:nil];
// I must call this or, the image that I set below will always be null
// why? I guess it's because the view hasn't been drawn yet because it hasn't been displayed, so I need to force the redraw - but this is my question. Is this is the right approach?
[page1.view setNeedsDisplay];
// set the image
page1.pageImage.image = [UIImage imageNamed:#"tutorialPage1.png"];
// make my array of view controllers, it expects an array because could be double-sided
NSArray *viewController = [NSArray page1];
// pass the array that contains my custom view controller
[self.pageController setViewControllers:viewController direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
So am I doing this right? I have to force the redraw so that my outlets exist when I try to assign to them?
It's not the setNeedsDisplay part that you "need", it's the self.view part. By accessing the view property you are forcing the view controller to actually load the NIB. I guess that as a side effect of this, the pageImage property is populated as well (and was nil before you called self.view).
So, just calling self.view; instead of [self.view setNeedsDisplay]; should be enough.
As others have noted, pageImage (a UIImageView?) is likely not loaded from the nib yet when you're accessing it.
If you have a custom getter for pageImage, you could do the following:
- (UIImageView*) pageImage
{
[self view];
return _pageImage; // assuming the property backing ivar is synthesized as _pageImage.
}
But my personal preference would be to not expose the imageview itself and just expose a property for image. Then you can set the image to the viewcontroller regardless of it's loaded state, and internally set it to the imageView once the view loads:
- (void) setImage: (UIImage*) image
{
_image = image;
if ( self.isViewLoaded )
{
self.pageImage.image = image;
}
}
- (void) viewDidLoad
{
[super viewDidLoad];
self.pageImage.image = self.image;
}
If you moved some code to the viewDidLoad method you would be guaranteed that the view had been drawn.

Conflict between Interface builder and .m#.h : who win?

I've been wondering for a few time now how does Xcode interpret the use of both IB and programmaticaly coded objects.
ex : I initWithStyleGrouped a table in .m but I set plain as the style in the attributes of the tableviewcontroller I am working on. so? I noticed that the code gets over the IB.
It first appears when I had to custom a detail table by insering a header and a UITextField in the first cell which is very easy with IB. But when I run the app, nothing but the template of a plain table.
gnuh??
Thank you for your help.
Cheers,
Louis
EDIT
here is the instantiate of the TableViewController :
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
They should never cross. If you instantiate a table with [[UITableView alloc] initWithStyle:UITableViewStyleGrouped], it creates a new table without going though a NIB. If you instantiate a table from a NIB, it creates an instance using -initWithCoder:.
Added after Update
OK, you are subclassing UITableView. In addition to overriding -initWithStyle:, you will want to override -initWithCoder: or -awakeFromNib.
The basic flow of loading an custom UIView from a NIB.
-initWithCoder: is used to instantiate the object
All NIB connections are make (IBOutlets and IBAction are connected).
-awakeFromNib is send to the object
This means if you set a value in -initWithCoder:, the NIB setting will win; if you set a value in -awakeFromNib, the your code will win.
Be sure to read the Subclassing Notes and Methods to Override sections of UIView.
It all depends on how you initialize the object. If you load the UITableView from your controller's init method and call initWithStyle, that's what your UITableView will be. If you want to use IB's, you'll need to initialize your controller with initWithNibName and have an IBOutlet connection to your view, which has the plain setting.
Well, I am not sure but I think I found a beginning of solution. here are my thoughts.
I consider a IB oriented design.
the compiler will ask for IB to instantiate the view.
But if we created a UITableViewController subclass, then we have all the method refering to the instantiation (correct word?) of this view.
So, in order to avoid this conflict, We can erase the code in the .M which refers to the initialization of the table : initWithStyle and the pragma mark about Table source. we just let the View life cycle needed by any view and the delegate.
I found some exemple using this. here is the .m of a detail view table which is designed with static cells on IB :
#import "PictureListDetail.h"
#implementation PictureListDetail
#synthesize managedObjectContext;
#synthesize currentPicture;
#synthesize titleField, descriptionField, imageField;
#synthesize imagePicker;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// If we are editing an existing picture, then put the details from Core Data into the text fields for displaying
if (currentPicture)
{
[titleField setText:[currentPicture title]];
[descriptionField setText:[currentPicture desc]];
if ([currentPicture smallPicture])
[imageField setImage:[UIImage imageWithData:[currentPicture smallPicture]]];
}
}
#pragma mark - Button actions
- (IBAction)editSaveButtonPressed:(id)sender
{
// If we are adding a new picture (because we didnt pass one from the table) then create an entry
if (!currentPicture)
self.currentPicture = (Pictures *)[NSEntityDescription insertNewObjectForEntityForName:#"Pictures" inManagedObjectContext:self.managedObjectContext];
// For both new and existing pictures, fill in the details from the form
[self.currentPicture setTitle:[titleField text]];
[self.currentPicture setDesc:[descriptionField text]];
if (imageField.image)
{
// Resize and save a smaller version for the table
float resize = 74.0;
float actualWidth = imageField.image.size.width;
float actualHeight = imageField.image.size.height;
float divBy, newWidth, newHeight;
if (actualWidth > actualHeight) {
divBy = (actualWidth / resize);
newWidth = resize;
newHeight = (actualHeight / divBy);
} else {
divBy = (actualHeight / resize);
newWidth = (actualWidth / divBy);
newHeight = resize;
}
CGRect rect = CGRectMake(0.0, 0.0, newWidth, newHeight);
UIGraphicsBeginImageContext(rect.size);
[imageField.image drawInRect:rect];
UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Save the small image version
NSData *smallImageData = UIImageJPEGRepresentation(smallImage, 1.0);
[self.currentPicture setSmallPicture:smallImageData];
}
// Commit item to core data
NSError *error;
if (![self.managedObjectContext save:&error])
NSLog(#"Failed to add new picture with error: %#", [error domain]);
// Automatically pop to previous view now we're done adding
[self.navigationController popViewControllerAnimated:YES];
}
// Pick an image from album
- (IBAction)imageFromAlbum:(id)sender
{
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentViewController:imagePicker animated:YES completion:nil];
}
// Take an image with camera
- (IBAction)imageFromCamera:(id)sender
{
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
[self presentViewController:imagePicker animated:YES completion:nil];
}
// Resign the keyboard after Done is pressed when editing text fields
- (IBAction)resignKeyboard:(id)sender
{
[sender resignFirstResponder];
}
#end
available here : enter link description here
What do you think ??
Even though I now alone on this post, I wanted to post the answer !
I finally figured out why my textfield didn't appear which show who's has the hand on the compiler.
I actually subclassed the detail with a class wich implement methods to fill the table source with the coreData.Then, the supposed static cells were actually filled with these methods.
Which shows, to my humble opinion, that the .m overpass the IB.

Trouble with TableView

So I have an view, in which I have a UIScrollView. I wanted to add the first subview to it a grouped table view from another controller. So I did this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.delegate = self;
TodayViewControllerIPhone *todayController = [[TodayViewControllerIPhone alloc] initWithStyle:UITableViewStyleGrouped];
self.firstTitle = todayController.title;
NSLog(#"%#", todayController.title);
todayController.view.frame = CGRectMake(0.0, 0.0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView addSubview:todayController.view];
self.navBar.topItem.title = self.firstTitle;
// Do any additional setup after loading the view from its nib.
}
But I get nothing from the created class... Even it's title is null... Can anyone tell me what I'm doing wrong? Thanks in advance.
You are not supposed to present two view controllers onscreen simultaneously. It's not guaranteed to work. Only the special container types (like UISplitViewController) can do this. In iOS5 you are supposed to be able to write your own containers, but I couldn't find the documentation on that.

Resources