После поиска в Интернете без какой-либо информации, я решил опубликовать здесь свою проблему, надеясь, что кто-то может объяснить, что не так с следующим фрагментом кода. Я просто не смог реализовать шаблон проектирования Singleton в Objective-C. Я нашел некоторый код, который реализует шаблон в Интернете, и немного изменил его, чтобы добавить словарь, который инициируется из файла plist (где каждая запись в списке свойств сама является словарем):
@interface UnitManager : NSObject {
NSString *someProperty;
NSDictionary *factors;
}
@property (nonatomic, retain) NSString *someProperty;
@property (nonatomic, retain) NSDictionary *factors;
+ (id) sharedUnitManager;
@end
// implementation file
#import "Unit.h"
#define MARGIN 20
static UnitManager *unitManager = nil;
@implementation UnitManager
@synthesize someProperty;
@synthesize factors;
#pragma mark Singleton Methods
+ (id)sharedUnitManager {
@synchronized(self) {
if(unitManager == nil)
unitManager = [[super allocWithZone:NULL] init];
}
return unitManager;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedUnitManager] retain];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)retain {
return self;
}
- (unsigned)retainCount {
return UINT_MAX; //denotes an object that cannot be released
}
- (void)release {
// never release
}
- (id)autorelease {
return self;
}
- (id)init {
if (self = [super init]) {
someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
// get path to file that stores category order
NSString *path = [[NSBundle mainBundle] pathForResource:@"factors" ofType:@"plist"];
factors = [NSDictionary dictionaryWithContentsOfFile:path];
}
return self;
}
- (void)dealloc {
// Should never be called, but just here for clarity really.
[someProperty release];
NSLog(@"should NEVER GET HERE!");
[factors release];
[super dealloc];
}
@end
Затем, немного кода позже, я пытаюсь получить доступ к словарю в одноэлементном объекте, и первый раз, когда он вызывается, работает нормально, но во второй раз, когда он обращается к освобожденной памяти!
- (void) someFunction {
...
NSString *str = [[[[UnitManager sharedUnitManager] factors] objectForKey:category] objectForKey:name];
...
...
}
Я получаю сообщение:
2011-09-12 17: 39: 44.567 Тест [7837: b603] - [CFDictionary objectForKey:]: сообщение отправлено освобожденному экземпляру 0x4d565e0 *
И след памяти:
(gdb) info malloc-history 0x5c73300
Alloc: адрес блока: 0x05c73300 длина: 48
Стек - pthread: 0xac2bd2c0 количество кадров: 44
0. 0x92573993 in malloc_zone_malloc
1. 0xebe87d in _CFRuntimeCreateInstance
2. 0xebe47a in CFBasicHashCreate
3. 0xf81e44 in __CFDictionaryCreateTransfer
4. 0xeed3ff in __CFBinaryPlistCreateObject2
5. 0xee2009 in __CFTryParseBinaryPlist
6. 0xee1a48 in _CFPropertyListCreateWithData
7. 0xee19ba in CFPropertyListCreateWithData
8. 0xee194f in CFPropertyListCreateFromXMLData
9. 0x791e34 in _NSParseObjectFromASCIIPropertyListOrSerialization
10. 0x7913d5 in +[NSDictionary(NSDictionary) newWithContentsOf:immutable:]
11. 0xf067bf in -[__NSPlaceholderDictionary initWithContentsOfFile:]
12. 0x791308 in +[NSDictionary(NSDictionary) dictionaryWithContentsOfFile:]
13. 0xcb38 in -[UnitManager init] at Unit.m:54
14. 0xc833 in +[UnitManager sharedUnitManager] at Unit.m:25
15. 0xe03a in -[Unit factor] at Unit.m:226
16. 0x39c9 in -[MainViewController updateTextFields] at MainViewController.m:113
17. 0x4037 in -[MainViewController refresh] at MainViewController.m:229
18. 0x79c669 in _nsnote_callback
19. 0xf879f9 in __CFXNotificationPost_old
20. 0xf0693a in _CFXNotificationPostNotification
21. 0x79220e in -[NSNotificationCenter postNotificationName:object:userInfo:]
22. 0x79e551 in -[NSNotificationCenter postNotificationName:object:]
23. 0x62f7 in -[MainViewController changeUnit:] at MainViewController.m:447
24. 0x2a4fd in -[UIApplication sendAction:to:from:forEvent:]
25. 0xba799 in -[UIControl sendAction:to:forEvent:]
26. 0xbcc2b in -[UIControl(Internal) _sendActionsForEvents:withEvent:]
27. 0xba750 in -[UIControl sendActionsForControlEvents:]
28. 0xfa59b in -[UISegmentedControl setSelectedSegmentIndex:]
29. 0xff39d in -[UISegmentedControl touchesBegan:withEvent:]
30. 0x4ed41 in -[UIWindow _sendTouchesForEvent:]
31. 0x2fc37 in -[UIApplication sendEvent:]
32. 0x34f2e in _UIApplicationHandleEvent
33. 0x11e8992 in PurpleEventCallback
34. 0xf90944 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
35. 0xef0cf7 in __CFRunLoopDoSource1
36. 0xeedf83 in __CFRunLoopRun
37. 0xeed840 in CFRunLoopRunSpecific
38. 0xeed761 in CFRunLoopRunInMode
39. 0x11e71c4 in GSEventRunModal
40. 0x11e7289 in GSEventRun
41. 0x38c93 in UIApplicationMain
42. 0x2639 in main at main.m:14
43. 0x25b5 in start
Может кто-нибудь объяснить, что здесь происходит? Я действительно не понимаю, почему во второй раз я не могу получить доступ к словарю. Я не вижу ничего, что освобождает словарь во второй раз, когда он используется.
Спасибо всем,
аа