2013-12-09 9 views
8

के बाद NSUserDefaults क्यों नहीं पढ़े जाते हैं मैं एनएसयूसर डीफॉल्ट का उपयोग कर रहा हूं ताकि यह स्टोर किया जा सके कि ऐप ईयूएलए और पीपी स्वीकार किए गए हैं (अन्य चीजों के साथ) यह सामान्य रूप से ठीक काम करता है। मैं शुरू कर सकता हूं, बाहर निकल सकता हूं और फिर ऐप पर वापस आ सकता हूं और यह मान जुर्माना पढ़ता है। मैं ऐप को मार सकता हूं और पुनरारंभ कर सकता हूं - डिफ़ॉल्ट को ठीक से पढ़ता है। मैं फोन को पुनरारंभ कर सकता हूं, फिर ऐप को पुनरारंभ कर सकता हूं और यह डिफ़ॉल्ट को ठीक से पढ़ता है।फ्लैट बैटरी IOS7

लेकिन जब फोन एक फ्लैट बैटरी से पुनरारंभ होता है, तो मैं ऐप खोलता हूं और मुझे अपने ईयूएलए को एक पीपी फिर से स्वीकार करने के लिए कहा जाता है। यह केवल आईओएस 7 पर मेरे आईफोन 5 पर होता है। मेरे पास आईओएस 6 पर 3 जीएस है जो एक ही व्यवहार को प्रदर्शित नहीं करता है।

मुझे संदेह है कि यह here हल करने के लिए एक समान समस्या हो सकता है, लेकिन यह कुंजीचैन में अनुमति के मुद्दों को संदर्भित करता है। क्या एनएसयूसर डीफॉल्ट पर वही अनुमतियां लागू होंगी?

क्या किसी ने आईएसओ 7 पर NSUserDefaults के साथ समान मुद्दों का अनुभव किया है?

+0

एसओ पर अन्य समान अनुत्तरित प्रश्न हैं। शायद एक अनसुलझा बग की तरह लग रहा है। आप एनएससीओडर या कोर डेटा का उपयोग कर इसके आसपास काम कर सकते हैं। –

उत्तर

21

तो प्रयोग और निष्कर्ष मैं इस प्रकार थे के लिए आया था googling के बाद:

महत्वपूर्ण अद्यतन परिवर्तन और वास्तव में किसी भी प्रक्रिया है कि लॉक स्क्रीन के पीछे ऐप्लिकेशन को लॉन्च यहाँ समस्या है। फ़ाइल। [NSUserDefaults डिफ़ॉल्ट उपयोगकर्ता] लोड को संरक्षित करें (NSFileProtectionCompleteUntilFirstUser प्रमाणीकरण) ताकि ऐप लॉन्च होने के बाद पहले अनलॉक होने तक यह पहुंच योग्य न हो। इसलिए यदि कोई प्रक्रिया पृष्ठभूमि में आपके ऐप को लॉन्च करती है और आपका ऐप डिफॉल्ट यूज़र उपयोगकर्ता डिफॉल्ट तक पहुंचने का प्रयास करता है तो यह फ़ाइल लोड नहीं कर सकता है और इसलिए आपको उपयोगकर्ता डिफ़ॉल्ट का नया रिक्त सेट देता है।

मेरे मामले में यहां क्या हुआ यह है कि ऐप तब ईयूएलए और पीपी को प्रतीक्षा करने की स्थिति में गया क्योंकि इसे डिफ़ॉल्ट से पढ़ा जाता है (जिसे पढ़ा नहीं जा सकता) कि उन्हें स्वीकार नहीं किया गया था अभी तक। फोन को अनलॉक करने और ऐप को दोबारा खोलने के बाद - कृपया ध्यान दें कि पहले ही 'लॉन्च' है - कुछ प्रक्रियाएं हैं जो एनएसयूसर डीफॉल्ट को लिखती हैं, कुछ मेरे ऐप में और कुछ मेरे ऐप का उपयोग करने वाले पुस्तकालयों में। उन मामलों में से अधिकांश में मैं डिफ़ॉल्ट पर सिंक्रनाइज़ कर रहा था इसलिए पुराने डिफ़ॉल्ट को नष्ट कर रहा था जिसे पढ़ा नहीं जा सका। मुझे कल्पना है कि यह बहुत से लोगों के लिए मामला हो सकता है।

कुछ अलग समाधान हैं।

सबसे पहले मैंने NSUserDefaults को एनएसएमयूटेबल डिक्शनरी के बराबर एक वर्ग लिखा और लाइब्रेरी/एप्लिकेशन सपोर्ट में .plist को शब्दकोश सहेज लिया। मैंने फाइल पर सुरक्षा को NSFileProtectionNone में बदल दिया। ध्यान दें कि यदि आप इस फ़ाइल में संवेदनशील जानकारी संग्रहीत करते हैं तो यह सलाह नहीं दी जाती है। यह भी ध्यान रखें कि जब भी आप इसे लिखते हैं तो आपको फ़ाइल पर अनुमतियां सेट करनी होंगी। कुछ की तरह:

NSError *error; 
BOOL saved = [defaultsDic writeToURL:defaultsFileUrl atomically:YES]; 
[[NSFileManager defaultManager] setAttributes:[NSDictionary dictionaryWithObject:NSFileProtectionNone forKey:NSFileProtectionKey]ofItemAtPath:[defaultsFileUrl path] error:&error]; 

इस विधि ठीक काम करता है, लेकिन के रूप में यह पता चला है मैं डेटा मैं पढ़ रहा था और कीचेन से लिखित रूप से एक और मुद्दा था। उपरोक्त मेरे प्रश्न में लिंक देखें, यह वही समस्या है। ऐप लॉन्च होने के बाद पहले अनलॉक होने तक कीचेन मानों में समान सुरक्षा होती है। मैं कीचेन से सुरक्षा को हटाना नहीं चाहता था और मैं वास्तव में अपने कस्टम उपयोगकर्ता डिफ़ॉल्ट से सुरक्षा को हटाने के साथ बहुत सहज नहीं था।

तो अगला समाधान वास्तव में समस्या को हल करना है। यदि लॉक स्क्रीन के पीछे ऐप लॉन्च किया गया है तो सुरक्षित डेटा तक पहुंचने का प्रयास न करें! इसका मतलब है कि मुझे यह पता लगाना है कि ऐप लॉक स्क्रीन के पीछे लॉन्च किया गया है और तब तक ऐप अनलॉक होने तक प्रतीक्षा करें जब तक कि मैं अपने उपयोगकर्ता डिफ़ॉल्ट और कीचेन मानों को पढ़ने के लिए आगे बढ़ूं।

संरक्षित डेटा उपलब्ध होने पर संभवतः एप्लिकेशन लॉन्च पर जांच करना है, इसलिए शायद एप्लिकेशन डिडलंच या कहीं और उपयुक्त।

[[UIApplication sharedApplication]isProtectedDataAvailable] 

यदि ऐप लॉन्च होने पर यह सच नहीं है तो आप लॉक स्क्रीन के पीछे हैं। आपको इस बिंदु पर रोकना चाहिए और NSUserDefaults या Keychain (या उस मामले के लिए किसी भी संरक्षित फ़ाइल तक पहुंचने वाले किसी भी ऑपरेशन से बचना चाहिए)। इसके बाद आपको एक संकेत की प्रतीक्षा करनी होगी कि सुरक्षित डेटा उपलब्ध हो गया है।

-(void)applicationProtectedDataDidBecomeAvailable:(UIApplication *)application 

एक बार जब आप प्राप्त है कि आप अपने आवेदन के निष्पादन पर ले जा सकता है: उपयोगकर्ता लॉक स्क्रीन बातें बताता है जब AppDelegate निम्नलिखित प्राप्त करता है।

मेरे मामले में मैं एक सिंगलटन कक्षा में सबकुछ नियंत्रित करता हूं। जब उस वर्ग बनाई गई है (जो केवल एप्लिकेशन लॉन्च पर होता है) मैं अगर सुरक्षित डेटा उपलब्ध है देखने के लिए जाँच या नहीं और एक ही अधिसूचना के लिए NSNotificationCenter की सदस्यता:

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(applicationProtectedDataDidBecomeAvailable) name:UIApplicationProtectedDataDidBecomeAvailable object:nil]; 
इस दूसरी विधि के साथ

तो, समस्या हल हो जाता है और डेटा सुरक्षित रहता है और हर कोई खुश है।

+0

आपके उत्तर के लिए धन्यवाद, क्या आपको पता है कि यह सामान्य है कि NSDocumentDirectory में फ़ाइलें एनएसयूसर डीफॉल्ट की तरह व्यवहार करती हैं जब स्क्रीन लॉक हो जाती है? – franck

+0

@muldercnc इसे साझा करने के लिए बहुत बहुत धन्यवाद। यदि उपयोगकर्ता अपनी स्क्रीन को अनलॉक करता है तो पृष्ठभूमि ऐप रीफ्रेश शुरू होने के 30 मिनट बाद, क्या हम अभी भी पृष्ठभूमि में डेटा ला सकते हैं? (जैसा कि हमारे पास ओएस कटौती करने से एक मिनट से भी कम समय पहले है) इसके अलावा, UIBackgroundFetchResult के समापन हैंडलर के साथ क्या करना है? – Serluca

+0

@ सेरलाका मुझे विश्वास है। चूंकि यह एक ईवेंट उत्पन्न करता है क्योंकि आपका ऐप घटना का जवाब देगा और 30 मिनट के बाद भी पृष्ठभूमि में खुशी से ऐसा करना चाहिए। आपको पुष्टि करने के लिए निश्चित रूप से प्रयास करना होगा। मैं आउटपुट XCODE => विंडो => डिवाइसों की निगरानी के लिए एक्सकोड में डिवाइस कंसोल का उपयोग करता हूं, जिस डिवाइस के साथ आप परीक्षण कर रहे हैं उसके लिए कंसोल विकल्प का उपयोग करें (क्योंकि आप डिबगिंग के दौरान अपने डिवाइस को पुनरारंभ कर सकते हैं)। – muldercnc

1

यह अभी भी आईओएस 9.0 जीएम पर व्यवहार है।

संबंधित मुद्दे