2

軍隊が建物を攻撃できる状況があります。各部隊は、そのターゲットへのポインターを保持します。

@property (nonatomic, weak) Building *target;

更新ループでは、部隊は定期的にターゲットにダメージを与えます。

if (_target)  
{
    if (/*enough time has passed since last attack, attack again*/)
    {
        [_target attack];
        if (_target.health <= 0)
        {
            [_target removeFromParentAndCleanup:YES];   //Cocos2d
            _target = nil;
        }
    }
}
else /* Find new target */ 

問題は:

  • troop1倒れた一撃を与え、次にbuilding1進むbuilding2
  • troop2攻撃してbuilding1いましたが、次の攻撃まで待って、building1現在nil.

問題は、troop2ポインターが nil に設定されていないことであり、代わりにポインターの値が nil であることを確認する必要があることに気付きました。

使用してみif (*_target)ましたが、メッセージが表示されました

ステートメントにはスカラー型の式が必要です

Objective-Cでこの種の比較を実現する方法があれば? 値がいつ変更されたかを判断するための他のオプションは何ですか? KVO? いくつかの広範なデリゲート パターン?

4

4 に答える 4

4

それが指しているオブジェクトが割り当て解除されたときに nil に設定されるのは、ポインター自体です。if (objectPointer == nil)Objective-C/Cocoa でオブジェクトが nil かどうかを確認する方法は常にです。ポインターが nil でない場合、問題のオブジェクトが実際には割り当て解除されていないことを意味します。オブジェクトへのポインターを逆参照すると、構造体が取得されるため、if 式でスカラー値が必要であるというコンパイラ エラーが発生します。

したがって、あなたの場合、if(self.target != nil)期待した結果が得られない場合は、(他のオブジェクトから) ターゲットへの残りの強い参照を探す必要があります。

より広義には、trojanfoe の回答で示唆されているように、実際のプログラム ロジックに対して ARC のゼロ化の弱い参照動作に依存しています。(彼の最初の声明に反して)ARC のゼロ化の弱い動作は信頼性が高く、決定論的であるため、理論的にはこれで問題ありません。しかし、それは、ターゲットが競技場 (またはその他のもの) に存在しなくなったときに、常にターゲットの割り当てが解除されるようにする必要があることを意味します。これは少し壊れやすいです。弱い参照をゼロにすることは、現在の方法でロジックを実装する方法としてではなく、保持サイクル (本質的にはメモリ リークの一種) を回避する方法として意図されています。必要に応じてターゲットを明示的に登録および登録解除するトロイの木馬のソリューションの要点は、おそらくより堅牢なソリューションです。

于 2013-02-20T16:08:02.420 に答える
1

[_target removeFromParentAndCleanup:YES];ターゲットは弱い参照であるため、ターゲットへのすべての強い参照を削除すると仮定すると、コードは「そのまま」機能するはずです。

最後の強い参照が削除されると、それを指すすべての弱いプロパティが自動的に に設定されnilます。それらが自動的に に設定されない場合nilでも、どこかにターゲットへの強い参照が残っています。

その参照を見つけて削除すると、これでうまくいきます。

于 2013-02-20T16:09:17.853 に答える
1

ポインターがnil. これは移植性がなく、オブジェクトが解放されてからポインターが になるまでの間に保証できますnilか?

代わりに、一意の ID に対してマップされたオブジェクトの中央ディクショナリを使用し、オブジェクト ポインター自体ではなく、この一意の ID のみを格納します。この例ではNSNumber、増加する整数を使用してキーに を使用していますが、使用できるより良いキーがおそらくあります。またObject、このディクショナリに格納するオブジェクトの基本クラスです。

// Probably ivars in a singleton class
unsigned _uniqueId = 1;
NSMutableDictionary *_objects;

- (NSNumber *)addObject:(Object *)object
{
    NSNumber *key = [NSNumber numberWithUnsignedInt:_uniqueId++];
    [_objects setObject:object forKey:key];
    return key;
}

- (void)removeObjectForKey:(NSNumber *)key
{
    [_objects removeObjectForKey:key];
}

- (Object *)getObjectForKey:(NSNumber *)key
{
    return [_objects objectForKey:key];
}

そして、ターゲットに、建物のキーを保存するだけです:

@property (strong) NSNumber *buildingKey;

提供されたメソッドを介して建物を取得します。

Building *building = (Building *)[objectDictionary objectForKey:buildingKey];
if (building != nil)
{
    // building exists
}
else
{
    // building does not exist; throw away the key
    buildingKey = nil;
}
于 2013-02-20T15:55:05.080 に答える