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"];
Related
I have an uiImageview which is intended to use in multiple viewControllers.
What I am thinking is an independant UiImageview that can bind and
unbind from viewController to viewController if needed.
Here is my bind/ unbind part of code.
#synthesize uiImgView1;
-(void) sendUIObjToViewController : (UIImageView*)imgView : (UIViewController*)vController{
[vController.view addSubview:imgView];
}
-(UIImageView*)constructUiImgView : (NSString*) imgAddress{
UIImageView *imgView = [[UIImageView alloc] initWithFrame : CGRectMake(50,50,100,100)];
[imgView setImage:[UIImage imageNamed:imgAddress]];
return imgView;
}
-(void) construct : (UIViewController*) vController{
uiImgView1 = [self constructImgView : #"abc.png"];
[self sendUIObjToViewController : uiImgView1 : vController];
}
If I call addSubView method from scope of constructUiImgView,
addSubView works.
-(UIImageView*)constructUiImgView : (NSString*) imgAddress : (viewController*)vController{
UIImageView *imgView = [[UIImageView alloc] initWithFrame : CGRectMake(50,50,100,100)];
[imgView setImage:[UIImage imageNamed:imgAddress]];
[vController.view addSubView imgView];
return imgView;
}
However, that means constructed uiImageView is depandant to one
specific viewController and I don't want to do that.
and If I call sendUiObjToViewController method, uiImageView
should bind to view of viewController but not works.
Am I doing some mistake of referencing variable or something??
My knowledge of Object-c is very limited so I really
need you guys help. Could you tell me what is wrong with my code?
any help will be appreciated.
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"];
}
I'm trying to pass a UIImage value to a UIImageView inside a View that I'm adding as a subView.
Here's what I'm doing in my mainViewController:
- (IBAction)selectStore:(id)sender {
StoreSelectorViewController *SSVC = [[StoreSelectorViewController alloc] initWithNibName:#"StoreSelectorViewController" bundle:nil];
[self.navigationController addChildViewController:SSVC];
[SSVC.backgroundView setImage:[UIImage imageNamed:#"CoolBG.png"]];
[self.view.window addSubview:SSVC.view];
}
I did the following in my StoreSelectorViewController.h file:
#property (nonatomic, retain) IBOutlet UIImageView *backgroundView;
And I also linked it in the XIB file.
Everything loads, except that I never receive the UIImage value. Thanks
Sometimes using this doesn't seem to work:
[SSVC.backgroundView setImage:[UIImage imageNamed:#"CoolBG.png"]];
So instead I use this two line version, in a slightly dif't order, setting the image, before displaying its parent (SSVC):
StoreSelectorViewController *SSVC = [[StoreSelectorViewController alloc] initWithNibName:#"StoreSelectorViewController" bundle:nil];
UIImage *img = [UIImage imageNamed:#"CoolBG.png"];
[SSVC.backgroundView setImage:img];
[self.navigationController addChildViewController:SSVC];
[self.view.window addSubview:SSVC.view];
You really shouldn't be calling addChildViewController regardless, it's not what you want. You're not making use of the UIViewController either, just stealing its view property. It's possible that because of this, the UIViewController is not fully instantiated since it's not presented (viewWill/Did) methods never get called, and so backgroundView is probably nil.
The problem is in this line [self.view.window addSubview:SSVC.view]; So just replace the line to below:-
Also you want to add imageview as a subview of view. So use below code where backgroundView is the imageview:-
[SSVC.view addSubview:SSVC.backgroundView];
[self.view addSubview:SSVC.view];.
Here is my code:
Header:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
UIImageView *imageView;
NSMutableArray *arrayWithImages;
}
- (IBAction)startAnimation:(id)sender;
- (IBAction)cleanMemory:(id)sender;
#end
Implementation:
#import "ViewController.h"
#implementation ViewController
......
- (IBAction)startAnimation:(id)sender {
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 768, 1024)];
arrayWithImages = [[NSMutableArray alloc] initWithObjects:
[UIImage imageNamed:#"pic1"],
[UIImage imageNamed:#"pic2"],
[UIImage imageNamed:#"pic3"],
[UIImage imageNamed:#"pic4"],
[UIImage imageNamed:#"pic5"],
[UIImage imageNamed:#"pic6"],
[UIImage imageNamed:#"pic7"],
[UIImage imageNamed:#"pic8"],nil];
imageView.animationImages = arrayWithImages;
imageView.animationDuration = 3;
imageView.animationRepeatCount = 1;
[self.view addSubview:imageView];
[imageView startAnimating];
}
- (IBAction)cleanMemory:(id)sender {
[arrayWithImages removeAllObjects];
[arrayWithImages release];
arrayWithImages= nil;
[imageView removeFromSuperview];
[imageView release];
imageView = nil;
}
#end
I have ViewController and its view with two buttons. First button with startAnimation action, which creates UIImageView , NSMutableArray and starts animation on it. Second button with cleanMemory action , which clean all what i've created in startAnimation.
When i start Profile with Activity Monitor instrument, my program have 4 mb Real Mem, when i press startAnimation button it's changes to 16 mb Real Mem and after animation i press cleanMemory button, but it has same 16 mb Real Mem... Why? I wont to clean my memory to started value( 4 mb Real Mem). Please, can you explain, where i have problems?
UIImage imageNamed: caches the images and will release the memory on it's own schedule. If you do not want the caching, that is completely control the memory then load the image directly,not with UIImage imageNamed:.
From the Apple docs:
This method looks in the system caches for an image object with the
specified name and returns that object if it exists. If a matching
image object is not already in the cache, this method loads the image
data from the specified file, caches it, and then returns the
resulting object.
You can use
+ (UIImage *)imageWithContentsOfFile:(NSString *)path
to load the image directly.
From the Apple docs:
This method does not cache the image object.
If even after using + (UIImage *)imageWithContentsOfFile:(NSString *)path you still don't get to free memory, tyr calling imageView.animationImages = nil;
I have a problem to change the background image of a UINavigationBar for IOS version < 5. I read already about one good solution, which is based on method swizzling, but the problem of this solution is when I add the image it covers everything include the buttons on a navigation bar.
I found a solution which partially worked for me it is base on a following code:
#interface UINavigationBar (UINavigationBarCategory)
-(void)setBackgroundImage:(UIImage*)image withTag:(NSInteger)bgTag;
-(void)resetBackground:(NSInteger)bgTag;
#end
#implementation UINavigationBar (UINavigationBarCategory)
-(void)setBackgroundImage:(UIImage*)image withTag:(NSInteger)bgTag{
if(image == NULL){ //might be called with NULL argument
return;
}
UIImageView *aTabBarBackground = [[UIImageView alloc]initWithImage:image];
aTabBarBackground.frame = CGRectMake(0,0,self.frame.size.width,self.frame.size.height);
aTabBarBackground.tag = bgTag;
[self addSubview:aTabBarBackground];
//[self sendSubviewToBack:aTabBarBackground];
[aTabBarBackground release];
}
-(void)setRightButton:(UIButton*)button withTag:(NSInteger)bgTag{
if(button == NULL){ //might be called with NULL argument
return;
}
[self addSubview:button];
}
/* input: The tag you chose to identify the view */
-(void)resetBackground:(NSInteger)bgTag {
[self sendSubviewToBack:[self viewWithTag:bgTag]];
}
#end
I used this Category in my ViewWillAppear methods like this:
-(void) viewWillAppear:(BOOL)animated {
UIImage *backgroundImage = [UIImage imageNamed:#"background_confernce_import_logo"];
if ([self.navigationController.navigationBar respondsToSelector:#selector(setBackgroundImage:forBarMetrics:)])
{
[self.navigationController.navigationBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
}
else{
[[self.navigationController navigationBar] setBackgroundImage:backgroundImage withTag:8675309];
}
}
In else clause I call setBackgroundImage. It is ok, but the problem is that if I have a right button on navigation bar of page 1 for example and go to page 2 after come back to page 1 the button is disappear. I should change the background image of navigation bar in every page in my application like this in viewWillAppear method where I put the new image.
Any help will be appreciated. Under IOS 5 there are no such problem, but it should work on both versions.
I hate to say it, but your approach (adding a subview to hold the background) will not work exactly for the reason you mention. Each time the navigation bar is redrawn, the subview will not keep its z-order (and thus it will cover other UI elements). This behavior is described by other sources (see this, e.g.)
If you don't want to use swizzling, you could override drawRect in a category, so that the background is always drawn correctly. (this last option has the drawback that any navigation bar in your app will be drawn with the same background). This is a sample code I use:
#implementation UINavigationBar (CustomBackground)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"back.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
A different approach could be:
subclassing UINavigationBar;
overriding drawRect;
in Interface Builder, set the class of your navigation bar object to your UINavigationBar subclass.
I haven't tried it, but it should work.
As per request, here comes my slightly naughty and not really polished hack. This is really just for making the OP happy. The right answer was given by sergio.
UINavigationBar+CustomDraw.m
NSString *gNavbarBackgroundImageName = #"default_navbar_background.png";
#implementation UINavigationBar (CustomBackground)
- (void)drawRect:(CGRect)rect
{
if (gNavbarBackgroundImageName != nil)
{
UIImage *image = [UIImage imageNamed:gNavbarBackgroundImageName];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
}
#end
UINavigationBar+CustomDraw.h
extern NSString *gNavbarBackgroundImageName;
And here comes the example usage in two view controllers...
FooViewController.m
#import "UINavigationBar+CustomDraw.h"
#implementation FooViewController
- (void)viewWillAppear:(BOOL)animated
{
gNavbarBackgroundImageName = #"foo_navbar_background.png";
[self.navigationController.navigationBar setNeedsDisplay];
}
#end
BarViewController.m
#import "UINavigationBar+CustomDraw.h"
#implementation BarViewController
- (void)viewWillAppear:(BOOL)animated
{
gNavbarBackgroundImageName = #"bar_navbar_background.png";
[self.navigationController.navigationBar setNeedsDisplay];
}
#end
Now let us assume you want to show a non-styled navigation bar, for example when displaying a Facebook login page (as provided by their SDK).
Use this to prevent any custom drawing:
gNavbarBackgroundImageName = nil;
Note Some of Apple's components use the UINavigationBar at places you might not have thought of. For example, the MPMoviePlayerController uses a custom navigation bar for displaying the upper part of its UI - so that would be another case where you want to prevent custom drawing.