NSMutableDictionary setObject: forKey (ios 6 без ARC) приводит к нулю
Следующий код работал до обновления до iOS 6. Он также работает в симуляторе iPhone 5.1, но терпит неудачу с симулятором и устройством 6.0.
Попытка setObject: forKey в цикле к NSMutableDictionary. Пробовали добавлять в цикле (как показано в следующем коде), а также пытались инициализировать массивами для объектов и ключей, что приводит к тому же сбою. Еще один странный бит информации заключается в том, что иногда он работает, но в большинстве случаев терпит неудачу. Объект добавление-это UILocalNotification, а ключ-это объект, представляющий день недели (больше, чем простая строка). Результат выполнения показан ниже. UILocalNotifications и ключи явно не являются NULL, но добавленная пара в MutableDictionary имеет NULL для некоторых объектов большую часть времени. В основном это последний добавленный день (ключ), объект которого равен null. Я совершенно не понимаю, как это ломается, заранее спасибо за любую помощь!
Метод копирования для дня недели (NSCopying Протокол):
- (id)copyWithZone:(NSZone *)zone
{
WeekDay * copy = [[WeekDay alloc] initWithDay:self.day];
return copy;
}
Фрагмент кода с использованием setObject: forKey:
NSMutableDictionary * newAlarmsDictionary = [[NSMutableDictionary alloc] init];
NSArray * theDayKeys = [[_daysEnabledDict allKeys] sortedArrayUsingSelector:@selector(compare:)];
NSMutableArray * tempNotifyArray = [[NSMutableArray alloc] init];
UILocalNotification * theAlarm = nil;
WeekDay * theWeekDay = nil;
for (int i=0; i < [theDayKeys count]; i++) {
if ([[_daysEnabledDict objectForKey:[theDayKeys objectAtIndex:i]] boolValue] == TRUE) {
theWeekDay = [theDayKeys objectAtIndex:i];
NSDate * now = [NSDate date];
... deleted lines setting up fire date for UILocalNotification, not significant to problem ...
theAlarm = [[UILocalNotification alloc] init];
theAlarm.fireDate = itemDate;
theAlarm.repeatInterval = NSWeekCalendarUnit;
theAlarm.timeZone = [NSTimeZone localTimeZone];
theAlarm.soundName = UILocalNotificationDefaultSoundName;
theAlarm.applicationIconBadgeNumber = 0;
[newAlarmsDictionary setObject:theAlarm forKey:theWeekDay];
[tempNotifyArray addObject:theAlarm];
[theAlarm release];
}
}
}
NSLog(@"--Debug: tempNotifyArray---- %@ -------------", tempNotifyArray);
NSLog(@"--Debug: newAlarmsDictionary ====== %@ =============", newAlarmsDictionary);
Здесь выводятся два оператора NSlog в конце фрагмента кода. Этот конкретный запуск добавляет 4 уведомления, в течение нескольких дней СР через сб. "Сигналы тревоги", помещенные в tempNotifyArray, являются допустимыми, но при добавлении в словарь (в данном случае один) равны нулю.
2012-11-26 11:07:01.087 MedTrack[9728:11303] --Debug: tempNotifyArray---- (
"<UIConcreteLocalNotification: 0x7277940>{fire date = Wednesday, November 28, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Wednesday, November 28, 2012, 11:06:00 AM Eastern Standard Time, user info = {n Temp = Fred;n}}",
"<UIConcreteLocalNotification: 0x8883280>{fire date = Thursday, November 29, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Thursday, November 29, 2012, 11:06:00 AM Eastern Standard Time, user info = {n Temp = Fred;n}}",
"<UIConcreteLocalNotification: 0x75c6590>{fire date = Friday, November 30, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Friday, November 30, 2012, 11:06:00 AM Eastern Standard Time, user info = {n Temp = Fred;n}}",
"<UIConcreteLocalNotification: 0x75c83e0>{fire date = Saturday, December 1, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Saturday, December 1, 2012, 11:06:00 AM Eastern Standard Time, user info = {n Temp = Fred;n}}"
) -------------
2012-11-26 11:07:01.097 MedTrack[9728:11303] --Debug: newAlarmsDictionary ====== {
"[WeekDay] 6 (Sat)" = (null);
"[WeekDay] 3 (Wed)" = "<UIConcreteLocalNotification: 0x7277940>{fire date = Wednesday, November 28, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Wednesday, November 28, 2012, 11:06:00 AM Eastern Standard Time, user info = {n Temp = Fred;n}}";
"[WeekDay] 4 (Thu)" = "<UIConcreteLocalNotification: 0x8883280>{fire date = Thursday, November 29, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Thursday, November 29, 2012, 11:06:00 AM Eastern Standard Time, user info = {n Temp = Fred;n}}";
"[WeekDay] 5 (Fri)" = "<UIConcreteLocalNotification: 0x75c6590>{fire date = Friday, November 30, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Friday, November 30, 2012, 11:06:00 AM Eastern Standard Time, user info = {n Temp = Fred;n}}";
1 ответ:
Проблема здесь заключается в том, что вы реализуете
-copyWithZone:
, но не можете реализовать-isEqual:
. Не зная полной структуры вашего объекта, я не могу ответить, как это должно быть реализовано, но вот хорошая основа:- (BOOL)isEqual:(id)otherObject; { if ([otherObject isKindOfClass:[self class]]) { WeekDay *otherWeekDay= (WeekDay *)otherObject; if (self.day != [otherWeekDay day]) return NO; if (self.name != [otherWeekDay name]) return NO; return YES; } return NO; } - (NSUInteger) hash; { return self.day ^ [self.name hash]; }