ईटीए: एप प्रोफाइलिंग द्वारा प्राप्त कुछ और जानकारी के लिए नीचे देखें।एक्सकोडिव-सी एआरसी का उपयोग करते समय ऑब्जेक्ट्स को जारी करने से ऑब्जेक्ट्स को कैसे जारी किया जा सकता है?
मेरे पास एक आईफोन ऐप है जिसे मैंने अभी एआरसी का उपयोग करने के लिए परिवर्तित कर दिया है, और अब मुझे ज़ोंबी ऑब्जेक्ट्स की वजह से कई त्रुटियां मिल रही हैं। स्विच करने से पहले, मैं उन्हें मैन्युअल रूप से बनाए रख रहा था, और सबकुछ ठीक था। मैं यह नहीं समझ सकता कि एआरसी उन्हें क्यों नहीं रख रहा है। वस्तुओं को मजबूत गुणों के रूप में घोषित किया जाता है, और डॉट नोटेशन का उपयोग करके संदर्भित किया जाता है। यह कई जगहों पर हो रहा है, इसलिए मुझे लगता है कि मुझे कहीं भी एआरसी/मेमोरी प्रबंधन की मौलिक गलतफहमी होनी चाहिए।
यहां एक उदाहरण है जो विशेष रूप से निराशाजनक है। मेरे पास 3 ऑब्जेक्ट्स का एनएसएमयूटेबलएरे है। उन वस्तुओं में से प्रत्येक में एक संपत्ति है जो एक एनएसएमयूटेबलएरे भी है, जो इस मामले में हमेशा एक ही वस्तु होती है। अंत में, उस ऑब्जेक्ट में वह संपत्ति है जो रिलीज़ हो जाती है। यह निराशाजनक कारण यह है कि यह केवल मूल सरणी से तीसरी वस्तु के साथ होता है। पहली 2 वस्तुएं हमेशा पूरी तरह से ठीक होती हैं। यह सिर्फ मुझे समझ में नहीं आता है कि एक वस्तु की संपत्ति कैसे जारी की जाएगी जब समान वस्तुओं की एक ही संपत्ति बनाई और उसी तरह उपयोग की जाती है।
सरणी एक UITableViewController पर एक संपत्ति के रूप में संग्रहीत किया जाता है:
@interface SchoolClass : NSObject <NSCopying, NSCoding>
@property (nonatomic, strong) NSMutableArray *schedules;
@end
@implementation SchoolClass
@synthesize schedules;
वस्तुओं कि schedules
में जमा हो जाती:
@interface GenSchedController : UITableViewController <SectionHeaderViewDelegate>
@property (nonatomic, strong) NSArray *classes;
@end
@implementation GenSchedController
@synthesize classes;
वस्तुओं कि classes
सरणी में जमा हो जाती है के रूप में परिभाषित कर रहे हैं सरणी को परिभाषित किया गया है:
@interface Schedule : NSObject <NSCopying, NSCoding>
@property (nonatomic, strong) NSMutableArray *daysOfWeek;
@implementation Schedule
@synthesize daysOfWeek;
daysOfWeek
जो जारी किया जा रहा है। इसमें बस कई एनएसएसटींग शामिल हैं।
मैं देख सकता हूं कि viewDidLoad
के दौरान सभी ऑब्जेक्ट ठीक हैं, कोई ज़ोंबी नहीं। हालांकि, जब मैं तालिका कक्षों में से किसी एक को टैप करता हूं, और tableView:didSelectRowAtIndexPath:
की पहली पंक्ति पर ब्रेकपॉइंट सेट करता हूं, तो इसे पहले ही रिलीज़ कर दिया गया है। , फिर यह केवल पिछले SchoolClass के अंतिम अनुसूची पर होता है
for (SchoolClass *currentClass in self.classes) {
for (Schedule *currentSched in currentClass.schedules) {
for (NSString *day in currentSched.daysOfWeek)
लेकिन,: विशिष्ट लाइन है कि त्रुटि फेंकता @synthesize daysOfWeek;
कि नीचे पाश "के लिए" 3 के बाद कहा जाता है।
क्या कोई मुझे एआरसी के साथ सही ढंग से काम करने के लिए सही दिशा में इंगित कर सकता है?
अनुरोध के रूप में, यहां और जानकारी है। सबसे पहले, स्टैक ट्रेस जब अपवाद फेंक दिया जाता है:
#0 0x01356657 in ___forwarding___()
#1 0x01356522 in __forwarding_prep_0___()
#2 0x00002613 in __arclite_objc_retainAutoreleaseReturnValue (obj=0x4e28b80) at /SourceCache/arclite_host/arclite-4/source/arclite.m:231
#3 0x0000d2fc in -[Schedule daysOfWeek] (self=0x4e28680, _cmd=0x220d6) at /Users/Jesse/Documents/Xcode/Class Test/Schedule.m:18
#4 0x0001c161 in -[SchedulesViewController doesScheduleOverlap:schedule2:withBufferMinutes:] (self=0x692b210, _cmd=0x22d58, schedule1=0x4e28680, schedule2=0x4e27f10, buffer=15) at /Users/Jesse/Documents/Xcode/Class Test/Classes/SchedulesViewController.m:27
#5 0x0001c776 in -[SchedulesViewController doesScheduleOverlap:schedule2:] (self=0x692b210, _cmd=0x22d9b, schedule1=0x4e28680, schedule2=0x4e27f10) at /Users/Jesse/Documents/Xcode/Class Test/Classes/SchedulesViewController.m:53
#6 0x0001cf8c in -[SchedulesViewController getAllowedSchedules] (self=0x692b210, _cmd=0x22dca) at /Users/Jesse/Documents/Xcode/Class Test/Classes/SchedulesViewController.m:78
#7 0x0001d764 in -[SchedulesViewController viewDidLoad] (self=0x692b210, _cmd=0x97cfd0) at /Users/Jesse/Documents/Xcode/Class Test/Classes/SchedulesViewController.m:121
#8 0x00620089 in -[UIViewController view]()
#9 0x0061e482 in -[UIViewController contentScrollView]()
#10 0x0062ef25 in -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:]()
#11 0x0062d555 in -[UINavigationController _layoutViewController:]()
#12 0x0062e7aa in -[UINavigationController _startTransition:fromViewController:toViewController:]()
#13 0x0062932a in -[UINavigationController _startDeferredTransitionIfNeeded]()
#14 0x00630562 in -[UINavigationController pushViewController:transition:forceImmediate:]()
#15 0x006291c4 in -[UINavigationController pushViewController:animated:]()
#16 0x000115d5 in -[GenSchedController tableView:didSelectRowAtIndexPath:] (self=0x4c57b00, _cmd=0x9ac1b0, tableView=0x511c800, indexPath=0x4e2cb40) at /Users/Jesse/Documents/Xcode/Class Test/Classes/GenSchedController.m:234
#17 0x005e7b68 in -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:]()
#18 0x005ddb05 in -[UITableView _userSelectRowAtPendingSelectionIndexPath:]()
#19 0x002ef79e in __NSFireDelayedPerform()
#20 0x013c68c3 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__()
#21 0x013c7e74 in __CFRunLoopDoTimer()
#22 0x013242c9 in __CFRunLoopRun()
#23 0x01323840 in CFRunLoopRunSpecific()
#24 0x01323761 in CFRunLoopRunInMode()
#25 0x01aa71c4 in GSEventRunModal()
#26 0x01aa7289 in GSEventRun()
#27 0x0057ec93 in UIApplicationMain()
#28 0x0000278d in main (argc=1, argv=0xbffff5fc) at /Users/Jesse/Documents/Xcode/Class Test/main.m:16
और सटीक अपवाद Class Test[82054:b903] *** -[__NSArrayM respondsToSelector:]: message sent to deallocated instance 0x4e28b80
है और यहाँ डिस्क से लोड हो रहा है, जहां सब कुछ कोड बनाया जाता है:
NSString *documentsDirectory = [FileManager getPrivateDocsDir];
NSError *error;
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:&error];
// Create SchoolClass for each file
NSMutableArray *classesTemp = [NSMutableArray arrayWithCapacity:files.count];
for (NSString *file in files) {
if ([file.pathExtension compare:@"sched" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:file];
NSData *codedData = [[NSData alloc] initWithContentsOfFile:fullPath];
if (codedData == nil) break;
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:codedData];
SchoolClass *class = [unarchiver decodeObjectForKey:@"class"];
[unarchiver finishDecoding];
class.filePath = fullPath;
[classesTemp addObject:class];
}
}
self.classes = classesTemp;
initWithCoder : तरीके वास्तव में सरल हैं।सबसे पहले SchoolClass के लिए:
- (id)initWithCoder:(NSCoder *)decoder {
self.name = [decoder decodeObjectForKey:@"name"];
self.description = [decoder decodeObjectForKey:@"description"];
self.schedules = [decoder decodeObjectForKey:@"schedules"];
return self;
}
और अनुसूची के लिए:
- (id)initWithCoder:(NSCoder *)decoder {
self.classID = [decoder decodeObjectForKey:@"id"];
self.startTime = [decoder decodeObjectForKey:@"startTime"];
self.endTime = [decoder decodeObjectForKey:@"endTime"];
self.daysOfWeek = [decoder decodeObjectForKey:@"daysOfWeek"];
return self;
}
मैं Zombies टेम्पलेट का उपयोग कर अनुप्रयोग पर एक प्रोफाइल चल की कोशिश की, और वस्तु की तुलना में दूसरों के ओवर-द रिलीज करने के लिए एक सरणी ठीक है। मैं देख सकता हूँ लाइन for (NSString *day in currentSched.daysOfWeek)
पर कि, कि यह daysOfWeek गेटर है, जो एक retain autorelease
करता है में चला जाता है। फिर गेटटर से लौटने के बाद, यह एक और retain
करता है (संभवतः लूप संसाधित होने पर स्वामित्व रखने के लिए), और उसके बाद release
। स्वस्थ वस्तु के लिए समस्या ऑब्जेक्ट के लिए यह सब वही है। अंतर यह है कि release
के तुरंत बाद, समस्या ऑब्जेक्ट release
को फिर से कॉल करता है। यह वास्तव में किसी समस्या का तुरंत कारण नहीं बनता है, क्योंकि ऑटोरेलीज पूल अभी तक नहीं निकला है, लेकिन एक बार ऐसा होने पर, गिनती गिनती 0 तक गिर जाती है, और फिर अगली बार जब मैं इसे एक्सेस करने का प्रयास करता हूं, तो यह एक ज़ोंबी है।
मुझे क्या पता नहीं लगा सकता है कि अतिरिक्त release
वहां कॉल किया जा रहा है। लूप के लिए बाहरी की वजह से, currentSched.daysOfWeek
को बुलाए जाने की संख्या अलग-अलग होती है - इसे समस्या ऑब्जेक्ट पर 3 बार और स्वस्थ वस्तु पर 5 कहा जाता है, लेकिन अतिरिक्त release
पहली बार इसे कॉल किया जाता है, इसलिए मैं नहीं हूं सुनिश्चित करें कि इससे कैसे प्रभावित होगा।
क्या यह अतिरिक्त जानकारी किसी को भी समझने में मदद करती है कि क्या हो रहा है?
रुको, आपके पास फॉर-लूप के अंदर '@ सिंथेसाइज' है? और आप यह कैसे निर्धारित कर रहे हैं कि यदि कोई ज़ोंबी दिखाई नहीं दे रहा है तो इसे जारी किया गया है? – Chuck
क्या आप कोड पोस्ट कर सकते हैं जहां आप वे ऑब्जेक्ट बनाते हैं? –
@Chuck मैं '@ systhesize' डीबगर में करने के लिए कूद गया है, जब वह पाश के लिए में एक्सेसर' currentSched.daysOfWeek' बुला रहा है लगता है। –