【问题标题】:NSArray received memory warningNSArray 收到内存警告
【发布时间】:2014-01-02 22:54:15
【问题描述】:

我有一个图像数组,当按下按钮时,它们会变为随机图像,并附有一个 IBAction。在模拟器上运行时它运行良好,但在设备上它似乎在内存警告后崩溃。按下按钮时它也会滞后。我希望它运行平稳,而不是崩溃。我相信这与我的数组没有发布每个图像有关。这是我的按钮代码中的数组。

-(IBAction)buttonPressed:(id)sender;
{

     int ptr = arc4random() % 132;

    NSArray* images = [[NSArray alloc] initWithObjects:@"17",@"29",@"55",@"400",@"Alcohol",@"Arianny",@"Anderson",@"Approach",@"Arab",@"Asian",@"Attitude",@"Attraction",@"Beckinsale",@"Blueberry",@"Brain",@"Break",@"Breakups",@"Burns",@"Buttocks",@"Charity",@"Check",@"Chicago",@"Chocolate",@"Coco",@"Coffee",@"College",@"Commit",@"Common",@"Confident",@"Cook",@"Count",@"Country",@"Couples",@"Courtship",@"Criminal",@"Cruz",@"Date",@"Date14",@"Deed",@"Degree",@"Dropped",@"Dushku",@"Dworaczyk",@"Eating",@"Emotion",@"Exercise",@"Fwb",@"Fantasies",@"Fitness",@"Flings",@"Flirt",@"Foot",@"Forget",@"Friendship",@"Frowning",@"Hum",@"Impression",@"Hair",@"Happiness",@"Hazel",@"Headache",@"Instant",@"Interest",@"Internet",@"Jacobs",@"January",@"Jimena",@"Jolie",@"Kalia",@"Kardashian",@"Kiss",@"Kissing",@"Krupa",@"Larissa",@"Latino",@"Laughter",@"Lip",@"London",@"Love",@"Love2",@"Love3",@"Love4",@"Math",@"Maximus",@"Melany",@"Memory",@"Men",@"Milian",@"Miller",@"Millions",@"Mind",@"Monica",@"Muscle",@"Partner",@"Naps",@"Negativity",@"Novels",@"Oral",@"Ossa",@"Pain",@"Positions",@"Productive",@"Proximity",@"Read",@"Reputation",@"Second",@"Sensitive",@"Serious",@"Shaking",@"Sleep2",@"Smile",@"Smoke",@"Smoke2",@"Smokers",@"Sneeze",@"Socks",@"Sold",@"Spot",@"Stimuli",@"Stone",@"Survey",@"Swell",@"Tattoo",@"Teacher",@"Teeth",@"Vickers",@"Violence",@"Wallet",@"Weight",@"Windmills.png",@"White",@"Women",@"Yawn",nil];


    [imageView setImage:[UIImage imageNamed:[images objectAtIndex:ptr]]];
    ptr++;
    NSLog(@"button pressed");

}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
        [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.images=nil;

}

- (void)dealloc {

    [images release];
    [adView release];

    [super dealloc];
}

【问题讨论】:

  • 你真的是手动输入的吗?!
  • 您的目标是哪些 iOS 版本?从 iOS 6 开始,viewDidUnload 永远不会被调用,因为视图永远不会被卸载。它们释放了大部分内部存储(尽管与公共属性无关)但继续存在,而不是视图控制器完全转储视图。

标签: ios memory memory-leaks nsarray


【解决方案1】:

我看到你的代码没有在 ARC 上运行,所以当你创建图像数组时,它不会从内存中删除,直到你调用 release.在你不再需要你的数组之后写 release:

int ptr = arc4random() % 132;
NSArray* images = [[NSArray alloc] initWithObjects:@"17",@"29"];
[imageView setImage:[UIImage imageNamed:[images objectAtIndex:ptr]]];
ptr++;
[images release];

【讨论】:

  • 是的,没错,我认为他有名为 images 的属性,从未使用过,所以他只需创建一次,只在不需要时释放它。
【解决方案2】:

首先,如果可以,请使用 ARC。

您有 2 件事泄漏内存:图像和图像名称数组。由于图像名称是恒定的,因此您只需要创建一次此数组。

为图像和图像名称数组创建 ivars: UIImage *_image; NSArray *_imageNames; // 在你的 viewDidLoad: 中初始化它

然后,在您的按钮按下处理程序中:

-(IBAction)buttonPressed:(id)sender;
{
     int ptr = arc4random() % 132;

    [_image release];
    _image = UIImage imageNamed:_images[ptr]];
    [imageView setImage:_image];
    ptr++;
    NSLog(@"button pressed");
}

最后,释放 _imageNames:

- (void)dealloc
{
    [_imageNames release];
    // release everything else.
}

同样,您真的应该考虑改用 ARC。你会很高兴你这样做了。

【讨论】:

  • 谢谢。所以我是否像之前在按钮按下处理程序中设置它一样全局设置我的 NSARRay,列出所有字符串对象?
  • 是的。这个想法是只做一次,而不是每次用户按下按钮。
  • 所以我会在 _imageNames 下的 viewdidload 中初始化我的字符串对象,或者我会使用 _image.. _imageNames = [[NSArray alloc] initWithObjects:@"17.png",@"29.png",无]
  • 是的,您可以在viewDidLoad: 中初始化数组。另一种常见的做法是将这个数组声明为一个属性,然后在getter方法中对其进行初始化。
  • 如果我这样做,我仍然不明白 UIImage*_image 是什么,或者我不需要它
【解决方案3】:

你实际上有两个问题,都围绕这一行:

NSArray* images = [[NSArray alloc] initWithObjects: ...strings omitted... ,nil];

首先是行首的NSArray*声明了一个新的局部变量images。这与您尝试在-viewDidUnload 中擦除并在-dealloc 中释放的属性self.images 是分开的。从行中删除 NSArray* 将解决此问题,将数组存储到您似乎打算的 self.images 属性中。

这给了你这样的一行:

images = [[NSArray alloc] initWithObjects: ...strings omitted... ,nil];

第二个问题是每次执行此方法时都会重新创建images 数组。这意味着,即使您解决了第一个问题,您仍然会在每次通过该方法时丢弃旧数组而不释放它,因此您仍然会泄漏这些数组。有很多方法可以解决这个问题,但最简单的方法可能是简单地测试你是否已经有一个数组,如果没有就创建它:

if(!images) {
    images = [[NSArray alloc] initWithObjects: ...strings omitted... ,nil];
}

(由于此类的所有实例都有相同的图像名称列表,因此您可以将数组存储在静态变量中,以便在它们之间共享 - 可能通过调用 dispatch_once 进行初始化 - 但这不是除非您在屏幕上同时有许多此视图控制器的实例,否则可能会有所作为。)

【讨论】:

    猜你喜欢
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-28
    • 1970-01-01
    • 2012-09-28
    相关资源
    最近更新 更多