0

この簡単なコードを作成しました:

PO(self.last10000Places);
PO(PlaceMark);
NSMutableArray *placemarks= [NSMutableArray arrayWithArray:PlaceMark];
PO(placemarks);//Breakpoint1
[placemarks removeObjectsInArray:self.last10000Places];
PO(placemarks);//Breakpoint2
[self.last10000Places addObjectsFromArray:placemarks];

ここで PO は単に私のマクロです

#define CLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define PO(x) CLog(@#x ": %@", x)
#define PD(x) CLog(@#x ": %f", x)

現在、nsmutablearray に isEqual を実装する必要があることを認識しています。

だから私はこのコードを入れます:

@interface CLLocation  (equal)
- (BOOL)isEqual:(CLLocation*)other;
@end

@implementation CLLocation  (equal)

- (BOOL)isEqual:(CLLocation*)other {


    if ([self distanceFromLocation:other] ==0)
    {
        return true;
    }
    return false;
}
@end
@interface CLPlacemark (equal)
- (BOOL)isEqual:(CLPlacemark*)other;
@end

@implementation CLPlacemark (equal)

- (BOOL)isEqual:(CLPlacemark*)other {
    PO(self);
    PO(other);
    if (![self.name isEqual:other.name])
    {
        return false;
    }
    if (![self.location isEqual:other.location ])
    {
        return false; //NEVER called
    }
    return true;//breakpoint3 but strange result
}


@end

次に、コードをステップ実行します。今、これは奇妙なことです。

breakpoint1 で私が見た:

2012-09-22 21:40:53.959 GetAllDistricts[18381:c07] <0x74a7480 SDViewController.m:(82)> placemarks: (
    "Ross Sea, Ross Sea @ <-77.43947520,-168.68218520> +/- 100.00m, region (identifier <-75.73637772,-0.00216940> radius 2140218.36) <-75.73637772,-0.00216940> radius 2140218.36m"

at breakpoint3 I saw:
2012-09-22 21:41:22.964 GetAllDistricts[18381:c07] <0xd77fab0 SDViewController.m:(37)> self: Alexander Island, Antarctica @ <-71.05224390,-70.87965290> +/- 100.00m, region (identifier <-70.73927686,-71.91489801> radius 258243.49) <-70.73927686,-71.91489801> radius 258243.49m
2012-09-22 21:41:22.964 GetAllDistricts[18381:c07] <0xd77fab0 SDViewController.m:(38)> other: South Atlantic Ocean, South Atlantic Ocean, Antarctica @ <-42.60533670,-21.93128480> +/- 100.00m, region (identifier <-41.51023865,-31.60774370> radius 4958095.65) <-41.51023865,-31.60774370> radius 4958095.65m
2012-09-22 21:41:22.965 GetAllDistricts[18381:c07] <0xd787390 SDViewController.m:(37)> self: South Atlantic Ocean, South Atlantic Ocean, Antarctica @ <-42.60533670,-21.93128480> +/- 100.00m, region (identifier <-41.51023865,-31.60774370> radius 4958095.65) <-41.51023865,-31.60774370> radius 4958095.65m
2012-09-22 21:41:22.965 GetAllDistricts[18381:c07] <0xd787390 SDViewController.m:(38)> other: South Atlantic Ocean, South Atlantic Ocean, Antarctica @ <-42.60533670,-21.93128480> +/- 100.00m, region (identifier <-41.51023865,-31.60774370> radius 4958095.65) <-41.51023865,-31.60774370> radius 4958095.65m

目印にロス海が含まれていることは明らかです。では、南大西洋とは一体何をremoveObjectsinArray呼ぶのでしょうか?isEqual

また、ロス海はブレークポイント 2 によって目印から削除されません。

isEqual を実装しました hash を実装しません

これが問題ですか?

4

2 に答える 2

2

私は問題が何であるかを理解しました。-(NSUInteger) ハッシュを実装すると、問題が解決します。

ドキュメントには、isEqual をオーバーライドするときにハッシュをオーバーライドする必要があると書かれています

removeObjects は最適化のためにハッシュを使用し、ハッシュが等しくないことを把握し、isEqual がチェックせずに false を返すと結論付けているようです。

したがって、次のコードを追加するだけです。

@interface CLLocation  (equal)
- (BOOL)isEqual:(CLLocation*)other;
@end

@implementation CLLocation  (equal)

- (BOOL)isEqual:(CLLocation*)other {


    if ([self distanceFromLocation:other] ==0)
    {
        return true;
    }
    return false;
}

- (NSUInteger) hash
{
    NSUInteger theHash = (NSUInteger) (self.coordinate.latitude *360 + self.coordinate.longitude);
    CLog(@"thehash %d",theHash);
    return theHash;
}
@end
@interface CLPlacemark (equal)
- (BOOL)isEqual:(CLPlacemark*)other;
@end

@implementation CLPlacemark (equal)

- (BOOL)isEqual:(CLPlacemark*)other {
    PO(self);
    PO(other);
    if (![self.name isEqual:other.name])
    {
        return false;
    }
    if (![self.location isEqual:other.location ])
    {
        return false;
    }
    return true;
}

-(NSUInteger) hash
{
    return self.name.hash;
}
于 2012-09-22T18:28:55.517 に答える
1

あなたの質問は、いくつかの片付けと、おそらく現在の動作の要約された説明と、それが予想からどのように逸脱しているかを使用することができます.

しかし、(質問のタイトルに基づいて)arrayWithArray:メソッドが実際に別のコレクションを作成および維持するという事実について混乱しているのだろうかと思います。オブジェクトはコピーされませんが、このシナリオでは:

NSArray *objects = [NSArray arrayWithObjects:@"A", @"B", @"C", nil];
NSMutableArray *mute = [NSMutableArray arrayWithArray:objects];
NSArray *removals = [NSArray arrayWithObjects:@"A", @"C", nil];
[mute removeObjectsInArray:removals];

最終結果は次のようになります。

objects = { @"A", @"B", @"C" }
mute = { @"B" }

この例は何かを明確にするのに役立ちますか?

于 2012-09-22T16:00:32.247 に答える