I will constantly call this method multiple times:
-(void)entityMaker {
UIImageView *entity;
NSUInteger image = [self getRandomNumberBetween:0 to:1];
NSUInteger xPosition = [self getRandomNumberBetween:20.0 to:self.width - 20.0];
entity = [[UIImageView alloc] initWithFrame:CGRectMake(xPosition, 20, 20, 20)];
[entity setImage:[self.imageArray objectAtIndex:image]];
[self.view addSubview:entity];
[self performSelector:#selector(animate:) withObject:entity afterDelay:2.0];
}
-(void)animate:(UIImageView *)image {
[image release];
//release has been deprecated
}
But, I don't want millions of image to stay on the screen.
How can I get rid of them (after any set number of seconds) so that they no longer take up memory and or no longer being displayed?
If you have no strong reference to the image view (which you don't in the code you posted), it will be deallocated after you remove it from its superview.
-(void)animate:(UIImageView *)image {
[image removeFromSuperview];
}
You could also use a property UIImageView and just update the image eveytime instead of creating a new UIImageView every-time and removing it.
Related
Just a general question about the best practices for functions which return values. Say for example I have the following function (pseudo code):
- (UIImageView *)createImageViewAndAddWithImageName:(NSString *)sName
{
UIImageView *iv = nil;
if (sName)
{
UIImage *image = [UIImage imageNamed:sName];
if (image)
{
iv = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[iv setImage:image];
[iv setContentMode:UIViewContentModeScaleAspectFit];
[self.view addSubview:iv];
}
}
return iv;
}
Now in some instances I want to perform further modifications like below:
UIImageView *iv = [self createImageViewAndAddWithImageName:#"Blah"];
[iv setAlpha:0.5f];
Where-as other times I want to just add an image:
[self createImageViewAndAddWithImageName:#"Blah"];
In the second instance, I presume that the memory will just be autoreleased? In the second instance, if this was running in a loop would it make sense to use an auto release block like below:
for (int i = 0; i < 100; i++)
{
#autoreleasepool {
[self createImageViewAndAddWithImageName:#"Blah"];
}
}
Just to free up the memory sooner? And is there any memory impact in having an autorelease pool in the main function like below too?
- (UIImageView *)createImageViewAndAddWithImageName:(NSString *)sName
{
UIImageView *iv = nil;
#autoreleasepool {
if (sName)
{
UIImage *image = [UIImage imageNamed:sName];
if (image)
{
iv = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[iv setImage:image];
[iv setContentMode:UIViewContentModeScaleAspectFit];
[self.view addSubview:iv];
}
}
}
return iv;
}
I just want to make sure that not using a returned value doesn't have a negative impact on my application, and that over-using autorelease pools doesn't either.
Thanks for any advice.
Every time the run loop calls out, it creates an autorelease pool. So all you have to do is to not allocate too much memory while doing anything caused by the run loop. For example if a user presses a button, your code handling this shouldn't allocate 100 MB of memory, even if autoreleased. Otherwise, autoreleased is reasonably cheap.
I am working on a view based app, I have set the background image as follows.
.h file:
UIImageView *BackgroundImage;
.m file:
viewdidLoad method:
BackgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"BG.png"]];
[[self view] addSubview:BackgroundImage];
[BackgroundImage.superview sendSubviewToBack:BackgroundImage];
and on the rotate method:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
BackgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"BG2.png"]];
[[self view] addSubview:BackgroundImage];
[BackgroundImage.superview sendSubviewToBack:BackgroundImage];
[super viewDidLoad];
}
Using this code I am able to set the background, but on rotation the first loaded image is not removed and the second one is loading just behind the first one, so just half of the image is visible, because of the first image is in front of second one.
Is there is a better way to do this?
OR
How can I just remove the first image and then set the second one?
Please help me to resolve this.
Change your didRotate... method to:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[BackgroundImage removeFromSuperview];
BackgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"BG2.png"]];
[[self view] addSubview:BackgroundImage];
}
Notice the [BackgroundImage removeFromSuperview]; line. What we are doing here is whenever the device rotates, you remove the old image view and add another one.
Also please notice that variable names should start with lower case, so BackgroundImage should be backgroundImage. This is to tell them apart from classes' names.
If you change your code like this should to work
BackgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"BG.png"]];
[self.view addSubview:BackgroundImage];
[self.view sendSubviewToBack:BackgroundImage];
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[BackgroundImage removeFromSuperview];
BackgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"BG2.png"]];
[self.view addSubview:BackgroundImage];
[self.view sendSubviewToBack:BackgroundImage];
[super viewDidLoad];
}
This is because you are initializing the UIImageview again. Better to use same UIImageView that is backgroundImage with different image.
[Background Image set image:[UIImage imageNamed:#"BG2.png"]];
Just set the new image when rotating:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
BackgroundImage.image = [UIImage imageNamed:#"BG2.png"];
}
Your code kept adding new image views when rotating.
How [do stuff] properly in iOS?
Start your ivar names using an underscore and a lowercase letter: _backgroundImage instead of BackgroundImage.
Insert a subview in the right spot: [self.view insertSubview:_backgroundImage atIndex:0];
I have an array of UIImages that I show in UIViews like this
UIImage *image=[self.currentAlphabet objectAtIndex:i ];
UIImageView *imageView=[[UIImageView alloc]initWithFrame:CGRectMake(xPos, yPos, imageWidth, imageHeight)];
imageView.image=image;
[self.view addSubview:imageView];
now later I want to remove these images from the view. I thought it should work like this
UIImage *image=[self.currentAlphabet objectAtIndex:i ];
UIImageView *imageView=[[UIImageView alloc]initWithImage:image];
[imageView removeFromSuperview];
but it doesn't work like that... do I need to save the UIImageViews in the array or is there any solution that needs less changes in the code written already?
You are creating a brand new view object (which isn't in the hierarchy) and then removing it from the view hierarchy. It doesn't work for this reason.
You have to remove the view object that you've previously added to view hierarchy (in the first snippet).
Basically, you have to keep track of those views: store them also in an NSMutableArray, use the tagproperty of UIView or use an instance variable.
It depends by how many views you have to add to your hierarchy. If you have a few of them, an instance variable is fine. If you have many of them, use an NSMutableArray.
For example, using a secondary NSMutableArray:
UIImage *image = [self.currentAlphabet objectAtIndex:i];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(xPos, yPos, imageWidth, imageHeight)];
imageView.image = image;
[self.view addSubview:imageView];
[imageViewArray addObject:imageView];
later on (I suppose that at this point you know the index of the object to remove):
[imageViewArray removeObjectAtIndex:i]
As long as the only image views in your view are the ones you want removed, a simple method to remove them is the following:
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[UIImageView class]]) {
[view removeFromSuperview];
}
}
What you are doing is creating a new Instance of UIImageView and without even Adding it to your view heirarchy you are removing it.
UIImage *image=[self.currentAlphabet objectAtIndex:i ];
UIImageView *imageView=[[UIImageView alloc]initWithImage:image];// It's a fresh new ImageView
[imageView removeFromSuperview];
What you can do is...
1) If there is only one ImageView in your View.. Then Create a Class Variable in .h File for UIImageView..
UIImageView *yourImageView; // in .h file
yourImageView.image = //Set Image here.
yourImageView.image = nil; // For removing the image.
2) Or If you don't want to create a Class variable for that.. Just give tag to your ImageVIew... And access it with viewWithTag method of UIView.
yourImageView.tag = 2;
and access it like following.
UIImageView *imageViewRef = [self.view viewWithTag:2];
[imageViewRef removeFromSuperView];
Hope this will help you..
I'm new here and could use some help, i'm making an ios app for the ipad and want to be able to animate the transition of pages in a pageview with custom and/or stock transitions.
What is the correct way to animate through various pages (PageView) each having full screen photos in them? Similar to in apples photos app. I'd like to be able to set up a basic slideshow and transition through them.
All Help is appreciated.
Thank You
Edit: Wow those responses were fast, is it also possible to have custom animations?
you can create like this way:-
- (void)viewDidLoad {
[super viewDidLoad];
UIScrollView *scr=[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
scr.tag = 1;
scr.autoresizingMask=UIViewAutoresizingNone;
[self.view addSubview:scr];
[self setupScrollView:scr];
UIPageControl *pgCtr = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 264, 480, 36)];
[pgCtr setTag:12];
pgCtr.numberOfPages=10;
pgCtr.autoresizingMask=UIViewAutoresizingNone;
[self.view addSubview:pgCtr];
}
- (void)setupScrollView:(UIScrollView*)scrMain {
// we have 10 images here.
// we will add all images into a scrollView & set the appropriate size.
for (int i=1; i<=10; i++) {
// create image
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"sti%02i.jpeg",i]];
// create imageView
UIImageView *imgV = [[UIImageView alloc] initWithFrame:CGRectMake((i-1)*scrMain.frame.size.width, 0, scrMain.frame.size.width, scrMain.frame.size.height)];
// set scale to fill
imgV.contentMode=UIViewContentModeScaleToFill;
// set image
[imgV setImage:image];
// apply tag to access in future
imgV.tag=i+1;
// add to scrollView
[scrMain addSubview:imgV];
}
// set the content size to 10 image width
[scrMain setContentSize:CGSizeMake(scrMain.frame.size.width*10, scrMain.frame.size.height)];
// enable timer after each 2 seconds for scrolling.
[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(scrollingTimer) userInfo:nil repeats:YES];
}
- (void)scrollingTimer {
// access the scroll view with the tag
UIScrollView *scrMain = (UIScrollView*) [self.view viewWithTag:1];
// same way, access pagecontroll access
UIPageControl *pgCtr = (UIPageControl*) [self.view viewWithTag:12];
// get the current offset ( which page is being displayed )
CGFloat contentOffset = scrMain.contentOffset.x;
// calculate next page to display
int nextPage = (int)(contentOffset/scrMain.frame.size.width) + 1 ;
// if page is not 10, display it
if( nextPage!=10 ) {
[scrMain scrollRectToVisible:CGRectMake(nextPage*scrMain.frame.size.width, 0, scrMain.frame.size.width, scrMain.frame.size.height) animated:YES];
pgCtr.currentPage=nextPage;
// else start sliding form 1 :)
} else {
[scrMain scrollRectToVisible:CGRectMake(0, 0, scrMain.frame.size.width, scrMain.frame.size.height) animated:YES];
pgCtr.currentPage=0;
}
}
You can use:-
SDWebimage
AFNetworking
NSCache and use of NSCache
For image cache and asynchronous load image
UPDATE:-
Here Bellow is some Library that doing something like photo gallery slide show check this and if you want then use in to you project by reading How to Implement.
MWPhotoBrowser for iOS
EGOPhotoViewer for iOS
CXPhotoBrowser for iOS
FGallery for iOS
Nimbus for iOS
PTImageAlbumViewController for iOS
I make a app which include a image view within scroll view.
I have 3 classes and each class add images into image view.
When i press button1, it call class1 and it fill Class1images(from image001 to image200).
When i press button2, it call class2 and it fill Class2images(from image201 to image400)
The problem is when i call class1, image view show class1images(from image001 to image200).
After calling class1, i call class2.
When i call class2, my image view can't show class2images(from image201 to image400)
But, class1Images (from image001 to image200) are remaining in app.
I think class1 images are still in memory, so that class2 images can't add to memory.
I want to remove class1images when i call class2.
When i call next class, it will remove old images in memory and replace with new images.
But, my app is develop with storyboard and ARC.
So, i can't release memory manually in ARC mode.
Is there any ways to remove old images in memory?
- (void)viewDidLoad{
[super loadView];
self.view.backgroundColor = [UIColor grayColor];
ScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width,self.view.frame.size.height)];
ScrollView.pagingEnabled = YES;
NSInteger numberOfViews = 200;
for (int i = 0; i < numberOfViews; i++) {
CGFloat xOrigin = i * self.view.frame.size.width;
// Create a UIImage to hold Info.png
UIImage *image1 = [UIImage imageNamed:#"Image001.jpg"];
UIImage *image2 = [UIImage imageNamed:#"Image002.jpg"];
:
:
UIImage *image200 = [UIImage imageNamed:#"Image200.jpg"];
NSArray *images = [[NSArray alloc] initWithObjects:image1,image2, . . . ,image200,nil];
ImageView = [[UIImageView alloc] initWithFrame:CGRectMake(xOrigin, 0,self.view.frame.size.width, self.view.frame.size.height)];
[ImageView setImage:[images objectAtIndex:i]];
[ScrollView addSubview:ImageView];}
ScrollView.contentSize = CGSizeMake(self.view.frame.size.width*numberOfViews,self.view.frame.size.height);
[self.view addSubview:ScrollView];}
setting an imageview's animationImages property to a new array will remove the olf array and animate the new one.
to be 110% safe call stopAnimation, set the images, call startAnimation
I think your scrollview is not getting cleaned up. You need to remove previous images from scrollView and after that add images from next class.
try to implement something like this for removing images from scrollview and after this add other images on button click
for(UIView *subView in self.ScrollView.subviews)
{
if([subView isKindOfClass:[UIImageView class]])
[subView removeFromSuperview];
}
Hopefully can help you. Just give it a try.