मैंने डीबगर के साथ परीक्षण किया है और दोनों Dictionary
और value
जिनमें मेरी दिलचस्पी है, शून्य नहीं हैं। जब मैं ऐप Sandbox
को सक्षम करता हूं तो ऐप क्रैश हो जाता है, लेकिन जब मैं इसे अक्षम करता हूं तो सब कुछ ठीक काम करता है। Sandbox
सक्षम के साथ UserDefaults का उपयोग करते समय क्या कुछ करना है?
कोड जहां दुर्घटना होती है:
func getPreferenceSettings(_ aKey: String) -> Bool
{
var lastPreferenceSetting: Bool!
if let currentSetting: Dictionary<String, Bool> = UserDefaults.standard.object(forKey: "defaultValues") as? Dictionary<String,Bool>{
lastPreferenceSetting = currentSetting[aKey]! //crash at this line
}else{
//show error to the user
}
return lastPreferenceSetting
}
मैं एक्सकोड 9.4 का उपयोग कर रहा हूं
2 जवाब
आपको जांचना है कि क्या दोनों कुंजियाँ defaultValues
और aKey
मौजूद हैं। चूंकि वापसी मूल्य गैर-वैकल्पिक वापसी false
डिफ़ॉल्ट मान के रूप में है।
यह कोड समर्पित विधि का उपयोग करता है dictionary(forKey
func getPreferenceSettings(_ aKey: String) -> Bool
{
if let currentSetting = UserDefaults.standard.dictionary(forKey: "defaultValues"),
let lastPreferenceSetting = currentSetting[aKey] as? Bool {
return lastPreferenceSetting
} else {
//show error to the user
}
return false
}
मुख्य मूल्य शून्य था (मैं डिबग के बजाय रिलीज योजनाओं का उपयोग कर रहा था, इसलिए मैं इसका मूल्य नहीं देख पा रहा था और मान लिया कि यह शून्य नहीं था)। इसके अलावा डिबगर की मदद से मैं यह देखने में सक्षम था कि कुंजी को शब्दकोश में कभी भी सहेजा नहीं गया था। अजीब बात यह है कि Sandbox
को अक्षम करने पर क्रैश नहीं होता है। मैंने विधि को निम्नलिखित तरीके से संशोधित किया है, इसलिए यह एक वैकल्पिक देता है और फिर कॉलर optional binding
के साथ जांचता है कि कोई कुंजी है या नहीं।
func getPreferenceSettings(_ aKey: String) -> Bool?
{
var lastPreferenceSetting: Bool?
if let currentSetting: Dictionary<String, Bool> = UserDefaults.standard.object(forKey: "defaultValues") as? Dictionary<String,Bool>{
lastPreferenceSetting = currentSetting[aKey]
}else{
//show error to the user
}
return lastPreferenceSetting
}
संपादित करें
@वादियान
मैं पढ़ रहा था कि
?
प्रकार का सही ढंग से उपयोग कब किया जाए और इसका उपयोग आमतौर पर किसी मान की अनुपस्थिति को इंगित करने के लिए किया जाता है उदाहरण के लिए किसी व्यक्ति का मध्य नाम। लेकिन इस मामले में वरीयता संपत्ति हमेशा परियोजना में मौजूद होती है क्योंकि यह डेवलपर द्वारा कठिन कोडित होती है (सिवाय इसके कि मेरे साथ ऐसा हुआ जब मैं इसेUserDefaults
में जोड़ना भूल गया और शब्दकोश को अपडेट करने से पहले इसे पहले साफ़ करना पड़ा नई कुंजी के साथ)। अगर मैं सही ढंग से समझता हूं, जो आपने लिखा है, मुझे एकBool?
मान वापस करना चाहिए और फिरoptional binding
के साथ कॉलर विधि में जांचना चाहिए कि यहnil
है या नहीं; यह न केवल उपयोगकर्ता पक्ष के लिए मध्य नाम के मामले के लिए बल्कि डेवलपर पक्ष के लिए भी किया जाना चाहिए क्योंकि एक और डेवलपर हो सकता है जो गलतaKey
पास कर सकता है, है ना?lastPreferenceSetting
को?
के रूप में घोषित करना भी सही है, क्योंकि यदि मैं एक डिफ़ॉल्ट मान का उपयोग करता हूं औरif let
गलत का मूल्यांकन करता है, तो फ़ंक्शन अपेक्षित मान नहीं लौटा सकता है।
aKey
मौजूद नहीं है या if let
का मूल्यांकन false
है, तो कोड क्रैश हो जाएगा।
Bool
के मामले में एक अनुपस्थित मान को false
के रूप में माना जा सकता है, जैसा कि तब होता है जब आप UserDefaults
से bool(forKey:
के साथ एक Bool
मान प्राप्त करते हैं। एक विकल्प (और Apple द्वारा अनुशंसित) सभी डिफ़ॉल्ट मानों का उपयोग करने से पहले उन्हें पंजीकरण करना है।
false
के साथ नहीं माना जाना चाहिए क्योंकि मैं संबंधित वरीयता संपत्ति के चेकबॉक्स को अक्षम करने के लिए भी गलत का उपयोग कर रहा हूं। इसके बजाय जब उपयोगकर्ता वरीयता संपत्ति की जांच करता है, तो इसका मूल्य true
होगा और कुछ क्रियाएं निष्पादित की जाएंगी। इसलिए यदि कोई शब्दकोश या कुंजी नहीं है तो मुझे यह जांचना चाहिए कि क्या यह मामला है (वैकल्पिक बाध्यकारी के साथ) और यदि ऐसा है तो मुझे किसी भी ऑपरेशन को निष्पादित नहीं करना चाहिए।
currentSettings
का कुंजीaKey
के लिए कोई मूल्य नहीं है।!
के प्रयोग से बचें और सुरक्षित रूप से खोल दें।lastPreferenceSetting
को पूरी तरह से अलिखितBool
घोषित न करें। इस मामले में, यह बेहतर होगा कि इसे प्रारंभिक मूल्य के साथ सामान्यBool
घोषित किया जाए।lastPreferenceSetting
को वैकल्पिक बनाया क्योंकि मानTrue
याFalse
हो सकता है और मुझे लगता है कि इस मामले में इसे एक डिफ़ॉल्ट मान असाइन करना सही नहीं है, बल्कि फ़ंक्शन के दौरान इसे खोलना है रिटर्न।