web-dev-qa-db-ja.com

allocとallocWithZone:の違いは何ですか?

フォーラムディスカッション から、大きな違いはパフォーマンス要因であるように思われます。allocWithZone:特定のメモリ領域からメモリを割り当てるため、スワッピングのコストが削減されます。

実際には、allocWithZone:を使用する機会はほとんどありません。誰でも、allocWithZone:を使用するケースを説明する簡単な例を提供できます。

よろしくお願いいたします。

50
Forrest

あるオブジェクトが別のオブジェクトを作成するとき、それらが両方とも同じメモリ領域から割り当てられていることを確認することをお勧めします。この目的には、ゾーンメソッド(NSObjectプロトコルで宣言されている)を使用できます。レシーバが配置されているゾーンを返します。

これは、あなたのivarと、クラス自体が "作成"するオブジェクトがこのように+allocWithZone:を使用して、それらが作成するインスタンスを同じゾーンに作成できることを示唆しています。

-(id)init {
  if (self = [super init]) {
    someIvar = [[SomeOtherClass allocWithZone:[self zone]] init];
  }

  return self;
}
47
d11wtq

Appleの ドキュメント から:

この方法は歴史的な理由で存在しています。メモリゾーンはObjective-Cでは使用されなくなりました。

30
Rivera

AllocWithZone:を使用する良い例は、NSCopyプロトコルを実装する場合です。これにより、次のようにカスタムオブジェクトをコピー可能(ディープコピー/値でコピー)にすることができます。

(1) ClassName *newObject = [currentObject copy]; //results in newObject being a copy of currentObject not just a reference to it

NSCopyプロトコルは、メソッドの実装を保証します。

(2) -(id)copyWithZone:(NSZone *)zone;

オブジェクトをコピーするとき、上記のように送信する「copy」メッセージ(1)が「copyWithZone」と指定されている場合、メッセージをメソッドに送信します(2)。別名ゾーンを自分で取得するために何もする必要はありません。

このメッセージに「ゾーン」が送信されたので、これを使用して、コピーが元のメモリと同じリージョンのメモリから作成されていることを確認できます。

これは次のように使用できます。

-(id)copyWithZone:(NSZone *)zone
{
   newCopy = [[[self class]allocWithZone:zone]init]; //gets the class of this object then allocates a new object close to this one and initialises it before returning
   return(newCopy);
}

これが、allocWithZoneが実際に使用されていることを知っている唯一の場所です。

5

シングルトンではallocWithZoneを使用しています。フォレストが述べたように、作成された変数は同じメモリ領域から割り当てられます。したがって、他のクラスは同じメモリ領域からそれらを使用またはアクセスできます。アプリを実行するときにメモリ領域を節約します。

2
felixwcf

Foundation Functions Reference では、すべてのZone関数の前に、ゾーンが無視されるという以下の警告が表示されます。

IOSではゾーンは無視され、OS Xでは64ビットランタイムが無視されます。現在の開発ではゾーンを使用しないでください。

NSCreateZone
NSRecycleZone
NSSetZoneName
NSZoneCalloc
NSZoneFree
NSZoneFromPointer
NSZoneMalloc
NSZoneName
NSZoneRealloc
NSDefaultMallocZone
2
pkamb

AppleのドキュメントでallocWithZone:

歴史的な理由で存在します。メモリゾーンはObjective-Cでは使用されなくなりました。このメソッドをオーバーライドしないでください。

そして

IOSではゾーンは無視され、OS Xでは64ビットランタイムが無視されます。現在の開発ではゾーンを使用しないでください。

実際には、Objective-Cクラス(完全なObjective-Cプロジェクト)でオーバーライドしました。ビルドがiPhone 6sで実行されている場合でも、このメソッドは[[Mylass alloc] init]を実行すると呼び出されます。

しかし、ドキュメントに従って、allocメソッドをオーバーライドする方が、allocが確実に同じ仕事を行うことができるので、このメソッドよりも優れていると思います。

0
Thibault