Monotouch ipad memory / animation problem
All, I'm working on what I thought was a fairly simple app. I'm using multiple view controllers with a view - under which there are buttons and a single image view. the buttonpress event triggers the other viewcontroller's view to display. That works perfectly. However, I'm also wanting to animate the transition to simulate a page turn. I use the code below to do that. It works well, however, every time I use this method the memory used increases. The memory used appears to be disconnected from the actual size of the image array. Also, I changed from png to jpeg ( much smaller images ) and it doesn't make a bit of difference. I thought about using .mov but the load time is very noticeable.
Please help. I've tried a ton of different way to force garbage collection. I've dug through the limited texts, and searched this website to no avail.
Here's a sample of the code.
public partial class AppDelegate : UIApplicationDelegate {
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
UIApplication.SharedApplication.SetStatusBarHidden( true, true);
// If you have defined a view, add it here:
// window.AddSubview (navigationController.View);
//window.AddSubview(mainController.View);
window.MakeKeyAndVisible ();
coverOpenbtn.TouchUpInside += HandleCoverOpenbtnTouchUpInside;
backBtn1.TouchUpInside += HandleBackBtn1TouchUpInside;
return true;
}
void HandleBackBtn1TouchUpInside (object sender, EventArgs e)
{
this.navView.RemoveFromSuperview();
List<UIImage> myImages = new List<UIImage>();
myImages.Add(UIImage.FromFile("c_1_00011.jpg"));
myImages.Add(UIImage.FromFile("c_1_00010.jpg"));
myImages.Add(UIImage.FromFile("c_1_00009.jpg"));
myImages.Add(UIImage.FromFile("c_1_00008.jpg"));
myImages.Add(UIImage.FromFile("c_1_00007.jpg"));
myImages.Add(UIImage.FromFile("c_1_00006.jpg"));
myImages.Add(UIImage.FromFile("c_1_00005.jpg"));
myImages.Add(UIImage.FromFile("c_1_00004.jpg"));
myImages.Add(UIImage.FromFile("c_1_00003.jpg"));
myImages.Add(UIImage.FromFile("c_1_00002.jpg"));
myImages.Add(UIImage.FromFile("c_1_00001.jpg"));
myImages.Add(UIImage.FromFile("c_1_00000.jpg"));
//myImages.Add(UIImage.FromFile("c_1_00012.jpg"));
var myAnimatedView = new UIImageView(window.Bounds);
myAnimatedView.AnimationImages = myImages.ToArray();
myAnimatedView.AnimationDuration = 1; // Seconds
myAnimatedView.AnimationRepeatCount = 1;
myAnimatedView.StartAnimating();
window.AddSubview(myAnimatedView);
}
void HandleCoverOpenbtnTouchUpInside (object sender, EventArgs e)
{
this.coverView.AddSubview(navView);
开发者_JAVA百科 List<UIImage> myImages = new List<UIImage>();
myImages.Add(UIImage.FromFile("c_1_00000.jpg"));
myImages.Add(UIImage.FromFile("c_1_00001.jpg"));
myImages.Add(UIImage.FromFile("c_1_00002.jpg"));
myImages.Add(UIImage.FromFile("c_1_00003.jpg"));
myImages.Add(UIImage.FromFile("c_1_00004.jpg"));
myImages.Add(UIImage.FromFile("c_1_00005.jpg"));
myImages.Add(UIImage.FromFile("c_1_00006.jpg"));
myImages.Add(UIImage.FromFile("c_1_00007.jpg"));
myImages.Add(UIImage.FromFile("c_1_00008.jpg"));
myImages.Add(UIImage.FromFile("c_1_00009.jpg"));
myImages.Add(UIImage.FromFile("c_1_00010.jpg"));
myImages.Add(UIImage.FromFile("c_1_00011.jpg"));
//myImages.Add(UIImage.FromFile("c_1_00012.jpg"));
var myAnimatedView = new UIImageView(window.Bounds);
myAnimatedView.AnimationImages = myImages.ToArray();
myAnimatedView.AnimationDuration = 1; // Seconds
myAnimatedView.AnimationRepeatCount = 1;
opened++;
}
myAnimatedView.StartAnimating();
window.AddSubview(myAnimatedView);
}
Here's a few hints (just by reading the code):
There no difference between JPEG and PNG once the images are loaded in memory. The format only matters when the image is stored, not displayed. Once loaded (and decompressed) they will take a bit over (Width * Height * BitCount) of memory.
Consider caching your images and load them only they are not available. The GC will decide when to collect them (so many copies could exists at the same time). Right now you're loading each image twice when you could do it once (and use separate array for ordering them).
Even if you cache them also be ready to clear them on demand, e.g. if iOS warns you memory is low. Override ReceiveMemoryWarning to clear your list (or better arrays).
Don't call ToArray if you can avoid it (like your sample code). If you know how many images you have them simply create the array with the right size (and cache both array too ;-). It will cut down (a bit) the allocations;
Even consider caching the 'myAnimatedView' UIImageView (if the above did not help enough)
Be helpful to others, try them one-by-one and tell us what help you the most :-)
The images are to "animate" a page turn...is this to navigate through the app?
E.g. you start at the "home" page, press a button then it animates a page turn to the next screen in your app?
I think you would be better off looking at using CoreGraphics to try and achieve this effect, it'll both be a lot more efficient memory wise, and it will probably look a lot better as well. There are a few projects in Objective-C to get you started, such as Tom Brow's excellent Leaves project.
Okay, here is the best solution I found, doesn't crash the hardware, and is generally useful for other tasks.
This is the code that goes in the handler for the button press, each NavImage is a UIImage I built under the same view in interface builder. I just turned the alpha to 0 initially, and light them up one by one...
NSTimer.CreateScheduledTimer(.1,delegate { navImage1.Alpha = 1; NSTimer.CreateScheduledTimer(.1,delegate { navImage2.Alpha = 1;
NSTimer.CreateScheduledTimer(.05,delegate { navImage3.Alpha = 1;
NSTimer.CreateScheduledTimer(.05,delegate { navImage4.Alpha = 1;
NSTimer.CreateScheduledTimer(.05,delegate { navImage5.Alpha = 1;
NSTimer.CreateScheduledTimer(.05,delegate { navImage6.Alpha = 1;
NSTimer.CreateScheduledTimer(.05,delegate { navImage7.Alpha = 1;
NSTimer.CreateScheduledTimer(.05,delegate { navImage8.Alpha = 1;
NSTimer.CreateScheduledTimer(.05,delegate { navImage9.Alpha = 1;
NSTimer.CreateScheduledTimer(.05,delegate { navImage.Alpha = 1; });});});});});});});});});});
精彩评论