2016-03-21 10 views
6

पर नाम बदलने और पुनः लिखने के बाद ऑब्जेक्ट के डीकोड पर क्रैश करें क्योंकि हमने कक्षा का नाम बदल दिया है और ऑब्जेक्टिव-सी से इसे फिर से लिखने के लिए कुछ उपयोगकर्ताओं को इसके साथ दुर्घटनाओं का अनुभव करना है। हम NSUserDefaults से NSCoding सिद्धांत के साथ एक ऑब्जेक्ट लोड करने का प्रयास कर रहे हैं।स्विफ्ट

दुर्घटना:

Thread : Crashed: com.apple.main-thread 
0 Flitsmeister     0x10018b720 specialized Place.init(coder : NSCoder) -> Place? (Place.swift) 
1 Flitsmeister     0x10018a6f4 @objc Place.init(coder : NSCoder) -> Place? (Place.swift) 
2 Foundation      0x1839ab92c _decodeObjectBinary + 2276 
3 Foundation      0x1839aaf90 _decodeObject + 304 
4 Foundation      0x1839aa124 +[NSKeyedUnarchiver unarchiveObjectWithData:] + 92 
5 Flitsmeister     0x100103fa0 +[SharedUserDefaultsManager WorkPlace] (SharedUserDefaultsManager.m:72) 
6 Flitsmeister     0x100090830 -[InvoerBestemmingTableViewController viewWillAppear:] (InvoerBestemmingTableViewController.m:106) 
7 UIKit       0x187d8074c -[UIViewController _setViewAppearState:isAnimating:] + 628 
8 UIKit       0x187d804c0 -[UIViewController __viewWillAppear:] + 156 
9 UIKit       0x187e27130 -[UINavigationController _startTransition:fromViewController:toViewController:] + 760 
10 UIKit       0x187e26a6c -[UINavigationController _startDeferredTransitionIfNeeded:] + 868 
11 UIKit       0x187e26694 -[UINavigationController __viewWillLayoutSubviews] + 60 
12 UIKit       0x187e265fc -[UILayoutContainerView layoutSubviews] + 208 
13 UIKit       0x187d63778 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 656 
14 QuartzCore      0x185772b2c -[CALayer layoutSublayers] + 148 
15 QuartzCore      0x18576d738 CA::Layer::layout_if_needed(CA::Transaction*) + 292 
16 QuartzCore      0x18576d5f8 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 32 
17 QuartzCore      0x18576cc94 CA::Context::commit_transaction(CA::Transaction*) + 252 
18 QuartzCore      0x18576c9dc CA::Transaction::commit() + 512 
19 UIKit       0x187d59c78 _afterCACommitHandler + 180 
20 CoreFoundation     0x18302c588 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32 
21 CoreFoundation     0x18302a32c __CFRunLoopDoObservers + 372 

वर्ग:

@objc(Place) 
class Place : NSObject, NSCoding, CustomDebugStringConvertible 
{ 
    let name: String 

    let location: CLLocation 
    var lastUsed: NSDate? 

    var type: PlaceType 

    var address: String? 
    //MARK: - NSCoding protocol 

    func encodeWithCoder(aCoder: NSCoder) { 
     aCoder.encodeObject(name, forKey: "name") 
     aCoder.encodeObject(address, forKey: "address") 
     aCoder.encodeInt(type.rawValue, forKey: "type") 
     aCoder.encodeObject(location, forKey: "location") 
     aCoder.encodeObject(lastUsed, forKey: "lastUsed") 
    } 

    required init?(coder aDecoder: NSCoder) { 


     if let locatieNaam : String = aDecoder.decodeObjectForKey("locatieNaam") as? String { 
      //This is the OLD object 
      name = locatieNaam 

      let nullableLocation : CLLocation? = aDecoder.decodeObjectForKey("locatie") as? CLLocation 
      if let notnulllablelocation : CLLocation = nullableLocation { 
       location = notnulllablelocation 
      } else { 
       location = CLLocation.init(latitude: 0, longitude: 0) //Not possible 
      } 
      lastUsed = aDecoder.decodeObjectForKey("lastUsed") as? NSDate 

      if aDecoder.decodeBoolForKey("isThuis") { 
       type = .Home 
      } else if aDecoder.decodeBoolForKey("isWerk") { 
       type = .Work 
      } else if aDecoder.decodeBoolForKey("isFavoriet") { 
       type = .Favoriet 
      } else { 
       type = .Other 
      } 

      address = nil 
     } 
     else { 
      name = aDecoder.decodeObjectForKey("name") as! String 
      let nullableLocation : CLLocation? = aDecoder.decodeObjectForKey("location") as? CLLocation 

      if let notnullableLocation : CLLocation = nullableLocation { 
       location = notnullableLocation 
      } else { 
       location = CLLocation.init(latitude: 0, longitude: 0) //Not possible 
      } 

      lastUsed = aDecoder.decodeObjectForKey("lastUsed") as? NSDate 
      type = PlaceType.init(rawValue: aDecoder.decodeInt32ForKey("type"))! 
      address = aDecoder.decodeObjectForKey("address") as? String 
     } 
    } 
} 

NSUserDefaults से पढ़ रहा है:

+ (Place*)WorkPlace; 
{ 
    @try { 
     NSUserDefaults *mySharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:kSharedUserDefaults]; 

     NSData *result = [mySharedDefaults objectForKey:kWerkBestemming]; 
     if(result == NULL) 
      return nil; 

     [NSKeyedUnarchiver setClass:[Place class] forClassName:@"Bestemming"]; 
     [NSKeyedUnarchiver setClass:[Place class] forClassName:@"BestemmingBase"]; 

     Place *place = [NSKeyedUnarchiver unarchiveObjectWithData:result]; 
     if(place != nil) { 
      place.type = PlaceTypeWork; //Needed because the old Bestemming class didnt saved the boolean isWerk 
     } 
     return place; 
    } 
    @catch (NSException *exception) { 
     return nil; 
    } 
} 

क्रैश लॉग यह लाइन 0 पर दुर्घटनाओं का कहना है, जो इतनी टिप्पणी है मैं लगता है कि यह init विधि में दुर्घटनाग्रस्त हो जाता है और मुझे लगता है कि यह उस वस्तु के साथ कुछ करने के लिए है जो शून्य है लेकिन शून्य नहीं हो सकता है।

मैं क्या कोशिश की है:

  • कोशिश पकड़ SharedUserDefaultsManager में
  • गैर nullables

उन उपयोगकर्ताओं जहां ऐप्लिकेशन क्रैश मैं से वस्तु को दूर करने के साथ रह सकते हैं के लिए पर अतिरिक्त चेकों NSUserDefaults। केवल अगर मैं जानूं कि यह कब होता है।

+0

बस एक टिप्पणी के रूप में तुलना करने की कोशिश करें (परिणाम == शून्य) बल्कि फिर नल। क्या आपने डीबग करने का प्रयास किया है कि aDecoder.decodeObjectForKey ("locatieNam") क्या देता है? अगर मैं दुर्घटना की गलत रेखा को देख रहा हूं तो मुझे सही करें। –

+0

अच्छी तरह से मैं इसे पुन: उत्पन्न नहीं कर सकता :(मुझे यह भी नहीं पता कि दुर्घटना किस पंक्ति में है क्योंकि क्रैशॉग कहते हैं कि लिनेंम्बर शून्य –

+0

क्या आप स्विफ्ट क्लास से पहले नवीनतम प्रतिबद्धता के लिए अपना कोड चेकआउट कर सकते हैं, ओबीजेसी ऑब्जेक्ट को डिस्क पर सहेज सकते हैं और फिर नवीनतम स्विफ्ट कोड पर चेकआउट कर सकते हैं और क्रैश को दोबारा बनाएं? –

उत्तर

0

सोचो इस NSCoding init विधि से निपटने और नहीं के बराबर है, तो चर तुम क्या नहीं की उम्मीद कर रहे हैं वापस जाने के लिए एक बेहतर तरीका है:

required convenience init?(coder decoder: NSCoder) { 
    guard let title = decoder.decodeObjectForKey("title") as? String, 
     let author = decoder.decodeObjectForKey("author") as? String, 
     let categories = decoder.decodeObjectForKey("categories") as? [String] 
     else { return nil } 

    self.init(
     title: title, 
     author: author, 
     pageCount: decoder.decodeIntegerForKey("pageCount"), 
     categories: categories, 
     available: decoder.decodeBoolForKey("available") 
    ) 
} 

NSHipster से: http://nshipster.com/nscoding/

अब देखते हैं कि कैसे करते हैं नया संस्करण काम कर रहा है।

संपादित करें: यह काम किया!