i searched for a few hours but i can´t find what i´m actually searching for..
i want to free up my memory when im switching from a gameScene to my menuScene.
as i read, it is possible if i add a viewController for each Scene and perfom Segues instead of transitions. but i want to keep it simple and use just one viewController. in addition to the first solution, it is possible to use UIImage´s instead of SKtexture. UIImage`s frees up their memory automatically by transition so i tried, and tried and i ended up here: (obviously not working)
//Load Animations
barrierUfoAtlas = [SKTextureAtlas atlasNamed:#"BarrierUfoAnimation"];
[barrierUfoAtlas preloadWithCompletionHandler:^{
NSArray *barrierUfoAtlasNames = [barrierUfoAtlas textureNames];
NSArray *sortetBarrierUfoAtlasNames = [barrierUfoAtlasNames sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSMutableArray *barrierUfoTextures = [NSMutableArray array];
for (NSString *filename in sortetBarrierUfoAtlasNames) {
NSData *imageData = [NSKeyedArchiver archivedDataWithRootObject:[barrierUfoAtlas textureNamed:filename]];
UIImage *image = [UIImage imageWithData:imageData];
SKTexture *texture = [SKTexture textureWithImage:image];
[barrierUfoTextures addObject:texture];
}
self.barrierUfoAnimation = [SKAction animateWithTextures:barrierUfoTextures timePerFrame:0.0389];}];
can somebody help?
Related
Im pretty new to coding but I'm starting to get the hang of the basics.
how to make an image stay in its new position after an animation?
Example:
I'm giving an animating object a random position, however, the animation causes the object not to animate at the random position, but instead animate at the position it was given in the view controller. This also happens when I animate a completly different object.
Code I used:
int Random1x;
int Random1y;
IBOutlet UIButton *Start;
IBOutlet UIImageview *Object2;
-(void)ObjectMoving;
-(void)Object2Animate;
-(IBAction)Start:(id)sender{
[self ObjectMoving];
[self Object2Animate];
}
-(void)Object2Animate {
Object2.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"2.png"],
[UIImage imageNamed: #"3.png"],
[UIImage imageNamed: #"4.png"],
[UIImage imageNamed: #"1.png"], nil];
Object2.animationDuration = .5
[Object2 setanimationRepeatCount: 0]
[Object2 startAnimating];
}
-(void)ObjectMoving {
Random1y = arc4random() % 466;
Random1y = Random1y + 60;
Random1x = arc4random() % 288;
Object2.center = CGPointMake(Random1x, Random1y);
}
I'd greatly appreciate help, thank you!
If you go to your story board file and click on the View Controller and then file inspector you will see a box for Auto Layout
Post back if that worked.
If you do need to use auto layout then you would have to figure out a different way of moving the image.
I am currently working on a UICollectionView with a lot of images. However, it sometimes crashes in this view with memory warning. I am using AFNetworking and UIImageView+AFNetworking category to set image through setImageWithURL: method. One issue can be caching. I am not sure if AFNetworking deals with image caching. Anyway, is there a way to optimize this code in terms of memory management? Or if I am to implement didReceiveMemoryWarning method in this view controller, what can be put in this method? I attach the code for cellForItemAtIndexPath for this collection view.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"RecipeCell" forIndexPath:indexPath];
// setting the image view for the cell using AFNetworking. Does this do caching automatically?
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:6];
if (PRODUCTION) {
[recipeImageView setImageWithURL:[[self.recipes objectAtIndex:indexPath.row] objectForKey:#"recipe_image"] placeholderImage:[UIImage imageNamed:#"default_recipe_picture.png"]];
} else {
[recipeImageView setImageWithURL:[NSString stringWithFormat:#"http://localhost:5000/%#", [[self.recipes objectAtIndex:indexPath.row] objectForKey:#"recipe_image"]] placeholderImage:[UIImage imageNamed:#"default_recipe_picture.png"]];
}
// configure the back of the cell. fill all the info.
UITextView *recipeNameView = (UITextView *)[cell viewWithTag:8];
recipeNameView.text = [NSString stringWithFormat:#"%#", [[self.recipes objectAtIndex:indexPath.row] objectForKey:#"recipe_name"]];
UILabel *recipeNameLabel = (UILabel *)[cell viewWithTag:2];
recipeNameLabel.text = [NSString stringWithFormat:#"%#", [[self.recipes objectAtIndex:indexPath.row] objectForKey:#"recipe_name"]];
NSDictionary *user = [[self.recipes objectAtIndex:indexPath.row] objectForKey:#"user"];
UIButton *chefNameButton = (UIButton *)[cell viewWithTag:3];
[chefNameButton setTitle:[NSString stringWithFormat:#"%# %#", [user objectForKey:#"first_name"], [user objectForKey:#"last_name"]] forState:UIControlStateNormal];
NSMutableArray *missingIngredientsStringArray = [[NSMutableArray alloc] init];
NSArray *missingIngredients = [[self.recipes objectAtIndex:indexPath.row] objectForKey:#"missing_ingredients"];
for (NSDictionary *missingIngredient in missingIngredients) {
[missingIngredientsStringArray addObject:[missingIngredient objectForKey:#"name"]];
}
NSString *missingIngredientsString = [missingIngredientsStringArray componentsJoinedByString:#","];
UITextView *missingIngredientsView = (UITextView *)[cell viewWithTag:4];
missingIngredientsView.text = [NSString stringWithFormat:#"%u Missing Ingredients: %#", missingIngredients.count, missingIngredientsString];
// configure the front of the cell. chef name button and missing ingredients and likes on front view
UIButton *frontNameButton = (UIButton *)[cell viewWithTag:11];
[frontNameButton setTitle:[NSString stringWithFormat:#"%# %#", [user objectForKey:#"first_name"], [user objectForKey:#"last_name"]] forState:UIControlStateNormal];
[frontNameButton sizeToFit];
frontNameButton.frame = CGRectMake(160 - [frontNameButton.titleLabel.text sizeWithFont:[UIFont boldSystemFontOfSize:13]].width - 7, frontNameButton.frame.origin.y, frontNameButton.frame.size.width, frontNameButton.frame.size.height);
UILabel *likesLabel = (UILabel *)[cell viewWithTag:9];
likesLabel.text = [NSString stringWithFormat:#"%# likes", [[self.recipes objectAtIndex:indexPath.row] objectForKey:#"likes"]];
UIButton *missingIngredientsButton = (UIButton *)[cell viewWithTag:12];
[missingIngredientsButton setBackgroundImage:[UIImage imageNamed:#"badge_green.png"] forState:UIControlStateSelected];
if (missingIngredients.count == 0) {
missingIngredientsButton.selected = YES;
[missingIngredientsButton setTitle:#"" forState:UIControlStateNormal];
} else {
missingIngredientsButton.selected = NO;
[missingIngredientsButton setTitle:[NSString stringWithFormat:#"%u", missingIngredients.count] forState:UIControlStateNormal];
}
// make back view invisible.
UIView *backView = [cell viewWithTag:1];
UIView *frontView = [cell viewWithTag:5];
frontView.alpha = 1.0;
backView.alpha = 0;
// adding flip gesture recognizers
UIView *flipView1 = [cell viewWithTag:12];
UIView *flipView2 = [cell viewWithTag:1];
UITapGestureRecognizer *flipGestureRecognizer1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(flipCell:)];
UITapGestureRecognizer *flipGestureRecognizer2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(flipCell:)];
[flipView1 addGestureRecognizer:flipGestureRecognizer1];
[flipView2 addGestureRecognizer:flipGestureRecognizer2];
return cell;
}
[Edit] I attach a screenshot of my Instruments run.
You can see that memory allocation increases as I just push segue and press back button repeatedly. Things that just keep increasing are CFData, CALayer, CABackingStore, UITableView. I doubt these are things that are created after segue, and they are not being released... Please help!
You're probably going to want some sort of image caching strategy to avoid re-downloading images. And UIImageView+AFNetworking category does cache images for you. But you may also have the responses being cached in the in-memory URL cache, which in this case is somewhat redundant.
So you might consider reducing or turning off the in-memory URL cache. I had the issue you're describing and the following reduced my memory issues quite a bit:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
AFNetworking automatically stores images in an NSCache collection, which automatically removes some or all of the images from memory on a low memory warning. AFNetworking is probably not your issue.
In fact, I don't think displaying images is your issue unless you're downloading lots of very large images and displaying them simultaneously. (If this is the case, you should try optimizing your images for display on the device so they don't need to be resized.)
One issue I see is that you are adding a gesture recognizer to the cell every time it comes into the view, but cells are reused, so when a cell comes in again you are adding unnecessary gesture recognizers to it. You could resolve this by subclassing UITableViewCell and assigning the gesture recognizers as properties. You could also resolve this by checking flipView1 and flipView2 to see if they have gesture recognizers attached before adding them. (I'm not sure if this is enough to cause a memory warning though.)
I'd recommend going to Build -> Profile and selecting the Allocations instrument. On the left, select Objective C only, and hide system calls. Then, scroll through your collection view and look at the instrument to see what's taking up all the memory.
UPDATE
Here's a screenshot of the Allocations tool:
I've been struggling with this for quite a few days now; my app has a diagram with uitextfields to represent labelling of the picture. I would like to check the user input against a dictionary (for the answer) and if it is correct, increase the score by 1.
I had it working by 'hard coding' each of the textfield.text queries each with their own if statement, but I would like a better and more reusable way if possible?
I've tried this so far:
- (IBAction)checkAnswers:(UITextField *)textField
{
// array for each textfield
allTextfields = [[NSArray alloc] initWithObjects:eyepiece, objectiveLenses, focussingKnobs, stage, mirror, nil];
// array for each UIImageView
allTicks = [[NSArray alloc] initWithObjects:eyepieceTick, objectiveTick, focussingTick, stageTick, mirrorTick, nil];
UIImage *image = [UIImage imageNamed:#"Tick.png"];
for (textField in allTextfields) {
if ([textField.text isEqualToString:[[microscopeBrain.microscopeDictionary valueForKey:theTextfieldTag] valueForKey:#"Answer"]]) {
[[allTicks objectAtIndex:textField.tag] setImage:image];
x++;
textField.enabled = NO;
NSLog(#"%#", microscopeBrain.microscopeDictionary);
// NSLog(#"%#", [[microscopeBrain.microscopeDictionary valueForKey:theTextfieldTag] valueForKey:#"Answer"]);
}
finalMicroscopeScore = [[NSString alloc] initWithFormat:#"%i", x];
microscopeScoreLabel.text = [[NSString alloc] initWithFormat:#"%i", x];
}
}
The problem is that even if the answers are in the wrong textfield, as long as one is correct, they will all show up as right, which is kind of embarrassing!
Any help would be very much appreciated.
Try changing the valueForKey:theTextFieldTag to valueForKey:textField.tag and see if that helps. You don't show how you get the value for theTextFieldTag, so I'm not sure if that's the problem.
I have a Addressbook in my App which gets filled from a website by json. If I add a new Person on my website the person get added to the app addressbook on the next launch. If I update a persons name on my website it works perfectly.. but if I add a new image to a existing person it still shows the old default image from Apple after the reload. If I compile it the picture appears. Is there a cache for addressbook pictures?
I tried the following:
BOOL imgBool = ABPersonHasImageData(aContact); -> false
and
ABPersonRemoveImageData(aContact, &anError); -> false because no picture in AB
I add a Persons picture like this:
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[[[self.profsInSection objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] bildUrl]]]];
NSData *picData = UIImageJPEGRepresentation(image, 0.9f);
[...]
ABPersonSetImageData(aContact, (CFDataRef)picData, nil);
There are no Errors, it just saves the last picture and ignores new pictures... :( Any ideas?
Haven't you forget to call saving function, after applying your changes in the address book?
ABAddressBookSave(addrBook, nil);
UPDATE: so, as long as you're using ABUnknownPersonViewController, I've tried the following code by myself and it's working both on the simulator & device
ABRecordRef newPerson = ABPersonCreate();
ABRecordSetValue(newPerson, kABPersonLastNameProperty, #"Smith", nil);
UIImage *personImage = [UIImage imageNamed:#"image.jpg"];
NSData *dataRef = UIImageJPEGRepresentation(personImage, 0.9f);
CFErrorRef error = nil;
bool result = ABPersonSetImageData(newPerson, (CFDataRef)dataRef, &error);
ABUnknownPersonViewController *controller = [ABUnknownPersonViewController new];
//controller.addressBook = addressBook;
controller.allowsAddingToAddressBook = YES;
controller.displayedPerson = newPerson;
[self.navigationController pushViewController:controller animated:YES];
[controller release];
The issue I've met when was testing this code, was my mistype in image name, so the UIImage instance was nil and NSData was empty. And ABPersonSetImageData gave no error on this. So, double check your UIImage instance is not nil.
Following is the code snippet that I have:
// Make Auto release pool
NSAutoreleasePool * autoReleasePool = [[NSAutoreleasePool alloc] init];
try
{
if (mCapture)
{
// Get the image reference
NSImage* image = NULL;
image = [mCapture getCurrentFrameImage];
// Get the TIFF data
NSData *pDataTifData = [[NSData alloc] initWithData:[image TIFFRepresentation]];
NSBitmapImageRep *pBitmapImageRep = [[NSBitmapImageRep alloc] initWithData:pDataTifData];
// Convert to BMP data
NSData *pDataBMPData;
pDataBMPData = [pBitmapImageRep representationUsingType: NSPNGFileType
properties: nil];
// Save to specified path
ASL::String strPath = ASL::MakeString(capInfo->thefile.name);
NSString* pPath = (NSString*)ASL::MakeCFString(strPath);
[pDataBMPData writeToFile:pPath
atomically: YES];
::CFRelease(pPath);
pDataBMPData = nil;
[pBitmapImageRep release];
pBitmapImageRep = nil;
[pDataTifData release];
pDataTifData = nil;
image = nil;
}
}
catch(...)
{
}
[autoReleasePool drain];
Note that image = [mCapture getCurrentFrameImage]; is returning an autoreleased NSImage. I am releasing objects and also have NSAutoreleasePool in place. But still it is leaking about 3-4 MB of memory everytime this code snippet is executed. I am not sure where the mistake is.
You could simplify this code a lot by making captureCurrentFrameImage return an NSBitmapImageRep instead of an NSImage, since you never actually use an NSImage for anything here. You can wrap the image rep in an image when necessary, and for this code, simply use the image rep by itself to produce the PNG data. Among other things, this saves you a trip through the TIFF representation.
If it still leaks after you make those changes, run your app under Instruments's Leaks template; the two instruments in that template, Leaks and ObjectAlloc, will help you hunt down whatever leaks you have.