Add UIImageView to UIView from subclass - ios

I created a custom class called Slot and it is a subclass of UIView. In the slot class, the following function is called:
- (NSString*)assignItem:(Item*)item {
NSString *message;
if (item.slotSize + currentCapacity > slotSize) {
message = #"Sorry this item will not fit.";
} else {
//uiimageview stuff
UIImage *image = [[UIImage alloc] initWithContentsOfFile:item.imageName];
UIImageView *iv = [[UIImageView alloc] initWithImage:image];
[self addSubview:iv];
[items addObject:item];
currentCapacity = currentCapacity + item.slotSize;
message = #"Success";
}
NSLog(#"%#",message);
return message;
}
What happens is an Item (another custom class, subclass of NSObject) is passed to the Slot a UIImageView is created from the item from a string to an image in the bundle and it is added to the subview. However, the image isn't showing. The Success message is showing so I know its getting in there. Is there another way to add a subview from the subclass or am I just doing it all wrong?

UIImage *image = [[UIImage alloc] initWithContentsOfFile:item.imageName];
This is not the correct way to instantiate an image that you have in the bundle. You can either use imageNamed: like this,
UIImage *image = [UIImage imageNamed:item.imageName];
Or, you can get the image with initWithContentsOfFile like this,
NSString *imagePath = [[NSBundle mainBundle] pathForResource:item.imageName ofType:#"JPG"]; // replace JPG with whatever is appropriate for your image.
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
imageNamed: will cache the images, the other way doesn't.

Related

How to load gif image and control that in ios?

In my application i want load the gif images in my view and also controls stop and continue animating.
Kindly follow the below tutorial that may help you.
http://anand3777.blogspot.in/2014/07/gif-image-loading.html
Step 1:
Download library from below url and add it on your project.
https://drive.google.com/folderview?id=0B5JC34Lt79ctamtOVTV6SHhzOVU&usp=sharing
Step 2:
Import the file on your "viewController.h" like below.
//gifImage//
#import "SCGIFImageView.h"
//gifImage//
Step 3:
Create object like given below on your "viewController.h".
//gifImage//
IBOutlet SCGIFImageView* _gifImageView;
IBOutlet UIButton* _button;
//gifImage//
Step 4:
Create ibaction on your "viewController".
//gifImage//
- (IBAction)controlAnimate:(id)sender;
//gifImage//
Step 5:
Add the following code were you want to use gif image
//gifImage//
//load url gif image
NSURL *imageURL = [NSURL URLWithString:#"http://google.co.in/anim.gif"];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
/*
//load local gif image
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"1.gif" ofType:nil];
NSData* imageData = [NSData dataWithContentsOfFile:filePath];
*/
_gifImageView = [[SCGIFImageView alloc] initWithFrame:CGRectMake(225, 70, 75, 75)] ;
[_gifImageView setData:imageData];
[self.view addSubview:_gifImageView];
//gifImage//
Step 6:
Add the following code for stop/start animating
//gifImage//
- (IBAction)controlAnimate:(id)sender{
_gifImageView.animating = !_gifImageView.animating;
if (_gifImageView.animating) {
[_button setTitle:#"Pause" forState:UIControlStateNormal];
} else {
[_button setTitle:#"Continue" forState:UIControlStateNormal];
}
}
//gifImage//
[1]: https://drive.google.com/folderview?id=0B5JC34Lt79ctamtOVTV6SHhzOVU&usp=sharing
Use Latest GIF Class from https://github.com/Flipboard/FLAnimatedImage
It is easy to use and memory friendly.
In your code, #import "FLAnimatedImage.h", create an image from an animated GIF, and setup the image view to display it:
FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif"]]];
FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init];
imageView.animatedImage = image;
imageView.frame = CGRectMake(0.0, 0.0, 100.0, 100.0); //As your Wish you can set frame
[self.view addSubview:imageView];
or If you are using Bundle gif file then
NSURL *url = [[NSBundle mainBundle] URLForResource:#"loading_01" withExtension:#"gif"];
FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:[NSData dataWithContentsOfURL:url]];
FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init];
imageView.animatedImage = image;
imageView.frame = CGRectMake(0.0, 0.0, 100.0, 100.0); //As your Wish you can set frame
[self.view addSubview:imageView];

Displaying UIImageViews in different UIView with different size

I am displaying UIImageViews programmatically. It works fine with the first UIView but when I try to display it on the smaller view, it does not resize.
Can you help me. Thanks in advance
By the way, I have a custom class of my UIView called courtView. I use this class for the two UIView
UIImageView *newImage;
NSSet *ballPosition = [self.startPosition valueForKey:#"ballPosition"];
for (BallPosition *courtPosition in ballPosition) {
PlayerPosition *player = [courtPosition valueForKey:#"playerPosition"];
if ([player.team isEqual: #(1)]) {
newImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Btn_blue.png"]];
}
else if ([player.team isEqual: #(2)]){
newImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Btn_red.png"]];
}
else if ([player.team isEqual: #(0)]){
newImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Ball.png"]];
}
newImage.frame = CGRectFromString([courtPosition valueForKey:#"courtPosition"]);
[self.courtView addSubview:newImage];
}
try this code
UIImage *myImage = [UIImage imageNamed :#"myImage.extension"];
//if ur images are static, if your images are from an array then loop it out write the below inside the loop, make sure myImageView is a class,static component.
CGFloat height = myImage.size.height;
CGFloat width = myImage.size.width;
myImageView.frame = CGRectMake (myImageView.frame.origin.x,myImageView.frame.origin.y,height,width);
myImageView.image = myImage;
Hope this helps

Programmatically placing an image in an UIImageView on a UIViewController

I have an image (a .png file) that I want to place in an ImageView in a ViewController. I use the following code but the simulator gives me a blank white view without the image. The .png file is in the same directory as the ViewController files. Here is the code:
#implementation ViewController
{
NSArray *_pArray;
UIImage *_image;
UIImageView *_imageView;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_image = [[UIImage alloc] initWithContentsOfFile:#"TM-1P2.png"];
_imageView = [[UIImageView alloc]initWithFrame:self.view.bounds];
[_imageView setImage:_image];
[_imageView setContentMode:UIViewContentModeScaleAspectFit];
[self.view addSubview:_imageView];
}
If you examine at _image (either NSLog or in the debugger), it probably is nil. With initWithContentsOfFile you should specify the entire path, for example:
NSString *path = [[NSBundle mainBundle] pathForResource:#"TM-1P2" ofType:#"png"];
_image = [[UIImage alloc] initWithContentsOfFile:path];
Alternatively, you can use the following, which automatically looks for the image in the bundle:
_image = [UIImage imageNamed:#"TM-1P2.png"];
This latter syntax, imageNamed, caches the image (i.e. will keep it in memory even if you dismiss the view controller). That's great if you have to use the same image again and again throughout the app (because it won't have to reload it every time), but if you only use it once, you might not want to use imageNamed. As the imageNamed documentation says:
If you have an image file that will only be displayed once and wish to ensure that it does not get added to the system’s cache, you should instead create your image using imageWithContentsOfFile:. This will keep your single-use image out of the system image cache, potentially improving the memory use characteristics of your app.
Note, both of these assume that you've successfully added this image to your bundle.
If, on the other hand, the image is in your Documents folder, you could load it like so:
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *path = [documentsPath stringByAppendingPathComponent:#"TM-1P2.png"];
_image = [[UIImage alloc] initWithContentsOfFile:path];
Finally, note that the iOS devices are case sensitive (generally the simulator is not), so make sure you have your capitalization correct.
Unrelated to your question, those variables in between the braces probably should not be defined in the #implementation, but rather you should put them in a #interface. For example, you could put them in your .h file, or better, you can put them in a private class extension in your .m file, right before the #implementation:
#interface ViewController ()
{
NSArray *_pArray;
UIImage *_image;
UIImageView *_imageView;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"TM-1P2" ofType:#"png"];
_image = [[UIImage alloc] initWithContentsOfFile:path];
_imageView = [[UIImageView alloc]initWithFrame:self.view.bounds];
[_imageView setImage:_image];
[_imageView setContentMode:UIViewContentModeScaleAspectFit];
[self.view addSubview:_imageView];
}
// ...
#end
Have you stepped through in the debugger?
I would be interested to see if _image is non-nil - and the most likely reason for it being nil is that you have not added it to your project.
If you have your image named as "TM-1P2.png" in your bundle, you can simply do the following:
_image = [UIImage imageNamed:#"TM-1P2.png"];
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.layer.frame.size.width, self.view.layer.frame.size.height)];
imgView.image = [UIImage imageNamed:#"emptyCart.jpeg"];
imgView.backgroundColor = [UIColor whiteColor];
imgView.contentMode = UIViewContentModeCenter;
[self.view addSubview: imgView];
}

Images not release in memory

I have table with Images cell. Images download from internet and save in local disk. Count = 200. Tableview show this images. When scroll content to bottom, comes message memory warning... Used memory 250 - 300 mb O_O!!! Links to images that do not keep.
NSString *cellID = #"cellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
...
NSString* imagePath = [arrayContent objectAtIndex:indexPath.row];
UIImage* image = [[UIImage alloc] initWithContentsOfFile:imagePath];
[cell.imageView setImage:image];
Why hide images not release?
Replace this line
UIImage* image = [[UIImage alloc] initWithContentsOfFile:imagePath];
with this and check once
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
Well I used a custom MSAsyncImageCell class that replaces its image when reused by iOS. It loads the image from a URL asynchronously, displaying a "loading" image gracefully and release memory when reused for another image. If you want I can post the code here but the code is a bit long.
Here is the part of code that actually loads the image. I have images off web/caches so it is NSData.
- (BOOL)_loadImageWithData:(NSData *)imageData
{
UIImage *image = [UIImage imageWithData:imageData];
// Just in case loading failed.
if (image)
{
// Extra check - don't mix up.
if ([[self.currentURL absoluteString] isEqualToString:[self.imageURL absoluteString]])
self.asyncImageView.image = image;
return YES;
}
return NO;
}

Load UIImage from file using grand central dispatch

I'm trying to load images in the background using gcd. My first attempt didn't work:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
// create UI Image, add to subview
});
});
commenting out the background queue code and leaving just the main queue dispatch block didn't work:
dispatch_async(dispatch_get_main_queue(), ^{
// create UI Image, add to subview
});
Is there some trick to doing ui stuff inside a gcd block?
In response to mattjgalloway's comment, I'm simply trying to load a big image in a background thread. Here's the full code that I tried originally:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
UIImage* img = [[UIImage alloc] initWithContentsOfFile: path];
dispatch_async(dispatch_get_main_queue(), ^{
imageView = [[[UIImageView alloc] initWithImage: img] autorelease];
imageView.contentMode = UIViewContentModeScaleAspectFill;
CGRect photoFrame = self.frame;
imageView.frame = photoFrame;
[self addSubview:imageView];
});
});
I simplified it so that I was running everything inside the main queue, but even then it didn't work. I figure if I can't get the whole thing to work in the main queue, no way the background queue stuff will work.
================ UPDATE ==============
I tried the above technique (gcd and all) in a brand new project and it does indeed work as expected. Just not in my current project. So I'll have to do some slow, painful process of elimination work to figure out what's going wrong. I'm using this background loading to display images in a uiscrollview. Turns out bits of the images do sometimes show up, but not always. I'll get to the bottom of this....
================ UPDATE ==============
Looks like the issue is related to the UIScrollView all of this is inside. I think stuff isn't getting drawn/refreshed when it should
I ran your code. It works with one exception. Also did you mean self.view rather than self?
Case 1:
path is declared at a property.
imageView is declared at an ivar
- (IBAction)buttonImagePressed:(id)sender
{
self.path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"picture1.jpg"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
UIImage* img = [[UIImage alloc] initWithContentsOfFile: self.path];
dispatch_async(dispatch_get_main_queue(), ^{
imageView = [[[UIImageView alloc] initWithImage: img] autorelease];
imageView.contentMode = UIViewContentModeScaleAspectFill;
CGRect photoFrame = self.view.frame;
imageView.frame = photoFrame;
[self.view addSubview:imageView];
});
});
}
Case 2:
path and imageView are both ivars. - no property is used.
- (IBAction)buttonImagePressed:(id)sender
{
// will crash if path is defined here
// path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"picture1.jpg"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
//if path is defined here then it will work
path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"picture1.jpg"];
UIImage* img = [[UIImage alloc] initWithContentsOfFile:path];
dispatch_async(dispatch_get_main_queue(), ^{
imageView = [[[UIImageView alloc] initWithImage: img] autorelease];
imageView.contentMode = UIViewContentModeScaleAspectFill;
CGRect photoFrame = self.view.frame;
imageView.frame = photoFrame;
[self.view addSubview:imageView];
});
});
}
On case 2, where it crashed, the message in the console said to file a bug at apple.com ...
Try to call setNeedDisplay right after [self addSubview:imageView], by the way most of UIKit isn't thread safe, I don't know about UIImage methods specifically (maybe is ok on iOS4 and higher), but I wouldn't do that. If you want to load images from background better use ImageIO that is thread safe, or Core Graphics functions.
An alternative could be load an NSData object with your image data on a background thread an later call [UIImage alloc]inithWithData: data] on the main thread.
Displaying my image as a background image, rather than a UIImageView added as a subview works. No clue why
#interface PhotoView(){
UIImageView* imageView;
}
#end
#implementation PhotoView
-(id)initWithFrame:(CGRect)frame andPathToPhoto:(NSString*)path andSequenceView:(SequencerView*) sequencerView{
if(self = [super initWithFrame:frame]){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
UIImage* img = [[UIImage alloc] initWithContentsOfFile: path];
dispatch_async(dispatch_get_main_queue(), ^{
self.backgroundColor = [UIColor colorWithPatternImage:img];
});
[img release];
});
}
return self;
}
#end

Resources