Objective-C/iPhone内存管理静态变量

Mar*_*ark 12 iphone variables static memory-management objective-c

我有一个静态方法,它创建一个类的实例并将其放在静态变量中.我想知道在这种情况下,内存管理的正确方法是什么.

你不能把它放在dealloc方法中,因为虽然它可以访问静态变量,但任何创建的实例方法都会释放getInstance.

我想可能有一个创建静态破坏方法的选项,它将手动释放内存,并且可以由appWillTerminate用户调用,但这看起来有点奇怪.

那么,问题是: 释放静态变量的正确方法是什么?


// MyClass.m
#import "MyClass.h"

static MyClass *myClass; // How to properly do memory management

@implementation MyClass

+ (MyClass *)sharedMyClass {
    if (myClass == nil) myClass = [[MyClass alloc] init];
    return myClass;
}
@end
Run Code Online (Sandbox Code Playgroud)

Rol*_*ien 8

您可以不释放它们,这很好,因为应用程序无论如何都要关闭.iPhone上的Cocoa已经这样做了,它并没有完全删除所有内容,只是让应用程序被吹走了.

或者您可以从appWillTerminate或其他一些关闭功能中删除它.

  • 请注意,如果您有一个单例,那么最好做的是使用某种清理方法,当应用程序委托获得内存不足警告时,可以调用该方法.你甚至可以在那个时候转储整个静态对象,如果创建不是太昂贵就让它重新创建. (3认同)

jes*_*rry 7

您需要查看iPhone开发中心的"创建单例",了解如何正确实现该模式.你不会释放你的单身,只是在应用程序退出时让它死掉.

此外,如果您是多线程的,您可能希望将该alloc包装在@synchronize(self){}中

这是全文:

某些类的Foundation和Application Kit创建单例对象.在"严格"实现中,单例是当前进程中类的唯一允许实例.但是您也可以使用更灵活的单例实现,其中工厂方法始终返回相同的实例,但您可以分配和初始化其他实例.NSFileManager类适合后一种模式,而UIApplication适合前者.当您要求UIApplication的实例时,它会向您传递对唯一实例的引用,如果它尚不存在则分配并初始化它.

单例对象充当一种控制中心,指导或协调该类的服务.当概念上只有一个实例时(例如,NSWorkspace),您的类应该生成单例实例而不是多个实例.当可以想象某天可能存在多个实例时,可以使用单例实例而不是工厂方法或函数.

要在当前进程中创建单例作为类的唯一允许实例,您需要具有类似于清单2-15的实现.此代码执行以下操作:

声明单个对象的静态实例并将其初始化为nil.在类的类工厂方法(命名为"sharedInstance"或"sharedManager")中,生成类的实例,但仅当静态实例为nil时.如果有人试图直接分配和初始化类的实例而不是使用类工厂方法,则覆盖allocWithZone:方法以确保未分配另一个实例.相反,只需返回共享对象.实现基本协议方法copyWithZone:,release,retain,retainCount和autorelease来做相应的事情以确保单例状态.(这些方法的最后四个适用于内存管理代码,而不是垃圾收集代码.)清单2-15严格实现单例静态MyGizmoClass

 *sharedGizmoManager = nil;  
 + (MyGizmoClass*)sharedManager {
     if (sharedGizmoManager == nil) {
         sharedGizmoManager = [[super allocWithZone:NULL] init];
     }
     return sharedGizmoManager; }  
 + (id)allocWithZone:(NSZone *)zone {
     return [[self sharedManager] retain]; }

 - (id)copyWithZone:(NSZone *)zone {
     return self; }

 - (id)retain {
     return self; }

 - (NSUInteger)retainCount {
     return NSUIntegerMax;  //denotes an object that cannot be released }

 - (void)release {
     //do nothing }

 - (id)autorelease {
     return self; }
Run Code Online (Sandbox Code Playgroud)

如果您需要单例实例(由类工厂方法创建和控制),但也能够通过分配和初始化根据需要创建其他实例,请不要覆盖allocWithZone:以及其后的其他方法,如清单2-15所示.


更新:现在有一种更简单的方法来创建单身人士

+ (MyClass*)sharedInstance
{
  static MyClass* _sharedInstance = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    _sharedInstance = [[MyClass alloc] init];
  });

  return _sharedInstance;
}
Run Code Online (Sandbox Code Playgroud)

使用这种新样式,您无需担心@syncronize或重写内存管理方法.