NSSet содержит некорректный результат объекта - PullRequest
0 голосов
/ 19 мая 2019

Я пишу игру, похожую на конфету. У меня есть тип "Swap", чтобы обозначить обмен 2 куки.

@interface Cookie : NSObject {

}
@property (strong) Coord2D *coord;
@end
@implementation Cookie {
}
@interface Swap : NSObject {
}

@property (strong) Cookie *cookieA;
@property (strong) Cookie *cookieB;
@end

@implementation Swap
- (BOOL)isEqual:(id)object {
  Swap *other = object;
  return ([_cookieA.coord isEqual:other.cookieA.coord] && [_cookieB.coord isEqual:other.cookieB.coord])
  || ([_cookieA.coord isEqual:other.cookieB.coord] && [_cookieB.coord isEqual:other.cookieA.coord]);
}

- (NSUInteger)hash {
  // (A, B) and (B, A) must be interchangable (hash to the same value)
  return (_cookieA.coord.row + _cookieB.coord.row) ^ (_cookieA.coord.col + _cookieB.coord.col);
}
- (NSString *)description
{
  return [NSString stringWithFormat:@"[%@, %@]", _cookieA.coord, _cookieB.coord];
}

@end

А cookie.coord просто определяется как тип Coord2D с row и col

@interface Coord2D : NSObject {
}
@property int row;
@property int col;
@end

@implement Coord2D
- (BOOL)isEqual:(id)object {
  Coord2D *other = object;
  return _row == other.row && _col == other.col;
}

- (NSUInteger)hash {
  return _row ^ _col;
}
- (NSString *)description
{
  return [NSString stringWithFormat:@"(%i, %i)", _row, _col];
}

@end

Теперь мне нужно проверить, содержит ли NSSet allPossibleSwaps только что созданный объект swap.

(lldb) po allPossibleSwaps
{(
    [(2, 4), (2, 5)],
    [(1, 1), (2, 1)],
    [(1, 0), (2, 0)],
    [(2, 4), (2, 3)],
    [(1, 2), (2, 2)],
    [(0, 4), (1, 4)],
    [(1, 4), (2, 4)],
    [(1, 4), (1, 5)],
    [(2, 3), (2, 4)]
)}

(lldb) po swap
[(1, 4), (2, 4)]

(lldb) p [allPossibleSwaps containsObject:swap]
(bool) $64 = false

Ожидается, что результатом будет ДА, но на самом деле это НЕТ.

Вот пара подсказок:

содержит объект: (allObject [6] неверно!) Также странно, что они печатаются как true/false вместо YES/NO

(lldb) p [allPossibleSwaps containsObject: allPossibleSwaps.allObjects[0]]
(bool) $41 = true
(lldb) p [allPossibleSwaps containsObject: allPossibleSwaps.allObjects[1]]
(bool) $40 = true
(lldb) p [allPossibleSwaps containsObject: allPossibleSwaps.allObjects[2]]
(bool) $42 = true
(lldb) p [allPossibleSwaps containsObject: allPossibleSwaps.allObjects[3]]
(bool) $39 = true
(lldb) p [allPossibleSwaps containsObject: allPossibleSwaps.allObjects[4]]
(bool) $43 = true
(lldb) p [allPossibleSwaps containsObject: allPossibleSwaps.allObjects[5]]
(bool) $44 = true
(lldb) p [allPossibleSwaps containsObject: allPossibleSwaps.allObjects[6]]
(bool) $45 = false
(lldb) p [allPossibleSwaps containsObject: allPossibleSwaps.allObjects[7]]
(bool) $46 = true
(lldb) p [allPossibleSwaps containsObject: allPossibleSwaps.allObjects[8]]
(bool) $47 = true

isEqual звонки (кажется правильным)

(lldb) p [(Swap *)(allPossibleSwaps.allObjects[0]) isEqual:swap]
(BOOL) $53 = NO
(lldb) p [(Swap *)(allPossibleSwaps.allObjects[1]) isEqual:swap]
(BOOL) $52 = NO
(lldb) p [(Swap *)(allPossibleSwaps.allObjects[2]) isEqual:swap]
(BOOL) $54 = NO
(lldb) p [(Swap *)(allPossibleSwaps.allObjects[3]) isEqual:swap]
(BOOL) $55 = NO
(lldb) p [(Swap *)(allPossibleSwaps.allObjects[4]) isEqual:swap]
(BOOL) $56 = NO
(lldb) p [(Swap *)(allPossibleSwaps.allObjects[5]) isEqual:swap]
(BOOL) $57 = NO
(lldb) p [(Swap *)(allPossibleSwaps.allObjects[6]) isEqual:swap]
(BOOL) $50 = YES
(lldb) p [(Swap *)(allPossibleSwaps.allObjects[7]) isEqual:swap]
(BOOL) $51 = NO
(lldb) p [(Swap *)(allPossibleSwaps.allObjects[8]) isEqual:swap]
(BOOL) $58 = NO

хэш-вызовы: (кажется правильным)

(lldb) p ((Swap *)allPossibleSwaps.allObjects[0]).hash
(NSUInteger) $30 = 13
(lldb) p ((Swap *)allPossibleSwaps.allObjects[1]).hash
(NSUInteger) $31 = 1
(lldb) p ((Swap *)allPossibleSwaps.allObjects[2]).hash
(NSUInteger) $32 = 3
(lldb) p ((Swap *)allPossibleSwaps.allObjects[3]).hash
(NSUInteger) $33 = 3
(lldb) p ((Swap *)allPossibleSwaps.allObjects[4]).hash
(NSUInteger) $34 = 7
(lldb) p ((Swap *)allPossibleSwaps.allObjects[5]).hash
(NSUInteger) $35 = 9
(lldb) p ((Swap *)allPossibleSwaps.allObjects[6]).hash
(NSUInteger) $36 = 11
(lldb) p ((Swap *)allPossibleSwaps.allObjects[7]).hash
(NSUInteger) $37 = 11
(lldb) p ((Swap *)allPossibleSwaps.allObjects[8]).hash
(NSUInteger) $65 = 3
(lldb) p swap.hash
(NSUInteger) $66 = 11

1 Ответ

3 голосов
/ 19 мая 2019

Ваша логика хеширования и isEquals выглядит правильно.И, судя по выводу вашей консоли, оба значения хеш-функции и isEquals ведут себя как положено.Таким образом, вполне вероятно, что во время повторного хеширования элементы помещаются в неправильное положение.

Повторное хэширование происходит при вставке или удалении элемента из набора.Вот хорошая статья, если вы не знакомы с тем, как работает хеширование: https://en.wikipedia.org/wiki/Extendible_hashing

Возможно ли, что ваша логика обмена cookie испортила элемент Swap, уже находящийся в наборе?Вы изменяете координаты после вставки?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...