2016-09-16 6 views
52

स्पष्ट रूप से अनचाहे विकल्प स्विफ्ट 3 में स्ट्रिंग इंटरपोलेशन का उपयोग करते समय अनचाहे नहीं हैं?स्विफ्ट 3 गलत स्ट्रिंग इंटरपोलेशन को स्पष्ट रूप से अनचाहे विकल्प के साथ

उदाहरण: खेल का मैदान

var str: String! 
str = "Hello" 

print("The following should not be printed as an optional: \(str)") 

में निम्न कोड चल रहा है इस उत्पादन का उत्पादन:

The following should not be printed as an optional: Optional("Hello") 
बेशक

मैं + ऑपरेटर के साथ तार जोड़ सकते हैं, लेकिन मैं स्ट्रिंग उपयोग कर रहा हूँ मेरे ऐप में इंटरपोलेशन काफी ज्यादा है जो अब इसके कारण काम नहीं करता है (बग?)।

क्या यह भी एक बग है या क्या उन्होंने जानबूझकर स्विफ्ट 3 के साथ इस व्यवहार को बदल दिया है?

+4

ध्यान दें कि यह जल्द ही एक चेतावनी उत्पन्न करेगा: https://github.com/apple/swift/pull/5110 – jtbandes

+1

यह मेरी राय में सबसे साफ समाधान है और यह बेहतर है क्योंकि यह स्पष्ट रूप से कहता है कि 'str' कब होता है 'शून्य ':' प्रिंट (" निम्नलिखित को वैकल्पिक के रूप में मुद्रित नहीं किया जाना चाहिए: \ (str ?? "") ") ' – hashemi

+1

@ हस्हेमी यहां मूल मुद्दा यह है कि यह बिल्कुल जरूरी नहीं होना चाहिए। आईयूओ का पूरा बिंदु यह है कि आप जानते हैं कि इसका उपयोग हमेशा किया जा सकता है जब इसे एक्सेस किया जा रहा है और इसलिए आपको स्पष्ट 'शून्य' जांच करने की आवश्यकता नहीं है। इसके अलावा - जैसा कि नाम से पता चलता है - संकलक को आपके लिए सभी अनचाहे करना है, लेकिन ऐसा नहीं है। 3.0 और 3.1 में optionals और स्ट्रिंग प्रक्षेप पर – Keiwan

उत्तर

56

SE-0054 के अनुसार, ImplicitlyUnwrappedOptional<T> अब एक अलग प्रकार नहीं है; अब केवल Optional<T> है।

घोषणाएं अभी भी परोक्ष unwrapped optionals T! के रूप में टिप्पणी की जा करने की अनुमति है, लेकिन ऐसा करने में सिर्फ संकलक उनके मूल्य बल संदर्भों है कि उनके unwrapped प्रकार T मांग में unwrapped हो सकता है कि सूचित करने के लिए एक छिपा विशेषता कहते हैं, उनका वास्तविक प्रकार अब T? है।

तो तुम इस घोषणा के बारे में सोच सकते हैं:

var str: String! 

के रूप में वास्तव में इस तरह लग रही:

@_implicitlyUnwrapped // this attribute name is fictitious 
var str: String? 

केवल संकलक इस @_implicitlyUnwrapped विशेषता देखता है, लेकिन क्या इसके लिए अनुमति देता है के अंतर्निहित unwrapping है str का संदर्भ उन संदर्भों में है जो String (इसके अनचाहे प्रकार) की मांग करते हैं:

// `str` cannot be type-checked as a strong optional, so the compiler will implicitly 
// force unwrap it (causing a crash in this case) 
let x: String = str 

// We're accessing a member on the unwrapped type of `str`, so it'll also be implicitly 
// force unwrapped here 
print(str.count) 

लेकिन अन्य सभी मामलों में जहां str प्रकार की जाँच की एक मजबूत वैकल्पिक के रूप में हो सकता है, यह हो जाएगा:

// x is inferred to be a String? (because we really are assigning a String?) 
let x = str 

// str is implicitly coerced from String? to Any 
let y: Any = str 

और संकलक हमेशा unwrapping बल पर इस तरह के रूप में यह इलाज का चुनाव करेगा।

प्रस्ताव का कहना है (जोर मेरा):

अभिव्यक्ति स्पष्ट रूप से एक मजबूत वैकल्पिक प्रकार के साथ की जाँच प्रकार किया जा सकता है, तो यह हो जाएगा। हालांकि, यदि आवश्यक हो तो टाइप चेकर वैकल्पिक को मजबूर करने के लिए वापस आ जाएगा। इस व्यवहार का प्रभाव यह है कि किसी भी अभिव्यक्ति का परिणाम जो T! के रूप में घोषित मूल्य को संदर्भित करता है या तो T टाइप करेगा या T? टाइप करें।

यह स्ट्रिंग प्रक्षेप की बात आती है, हुड के नीचे संकलक आदेश एक स्ट्रिंग प्रक्षेप खंड का मूल्यांकन करने में _ExpressibleByStringInterpolation protocol से इस initialiser उपयोग करता है:

/// Creates an instance containing the appropriate representation for the 
/// given value. 
/// 
/// Do not call this initializer directly. It is used by the compiler for 
/// each string interpolation segment when you use string interpolation. For 
/// example: 
/// 
///  let s = "\(5) x \(2) = \(5 * 2)" 
///  print(s) 
///  // Prints "5 x 2 = 10" 
/// 
/// This initializer is called five times when processing the string literal 
/// in the example above; once each for the following: the integer `5`, the 
/// string `" x "`, the integer `2`, the string `" = "`, and the result of 
/// the expression `5 * 2`. 
/// 
/// - Parameter expr: The expression to represent. 
init<T>(stringInterpolationSegment expr: T) 

इसलिए जब परोक्ष अपने कोड से बुलाया:

var str: String! 
str = "Hello" 

print("The following should not be printed as an optional: \(str)") 

str वास्तविक प्रकार String? है, डिफ़ॉल्ट रूप से संकलक जेनेरिक प्लेसहोल्डरका अनुमान लगाएगाहोना। इसलिए str का मान अवांछित नहीं होगा, और आप वैकल्पिक के लिए विवरण देखने को समाप्त कर देंगे।

आप एक IUO बल जब स्ट्रिंग प्रक्षेप में इस्तेमाल unwrapped होने के लिए, आप बस बल खोलना ऑपरेटर ! उपयोग कर सकते हैं चाहते हैं: (

var str: String! 
str = "Hello" 

print("The following should not be printed as an optional: \(str!)") 

या आप अपने गैर वैकल्पिक प्रकार के लिए मजबूर कर सकते हैं इस में क्रम में मामले String) परोक्ष यह तुम्हारे लिए खोलने के लिए मजबूर करने संकलक मजबूर करने के लिए:

print("The following should not be printed as an optional: \(str as String)") 

जो दोनों, की निश्चित रूप से, अगर strnil है दुर्घटना होगा।

+23

जैसे कि यह पर्याप्त बुरा नहीं था कि आपको एक आईयूओ का उपयोग करना है, अब वे कम उपयोगी हैं और विरोधाभासी व्यवहार करते हैं। अगर मैं इसका इस्तेमाल करता हूं क्योंकि मैं चाहता हूं कि यह पूरी तरह से अनचाहे हो। उन्हें अब से श्रोडिंगर विकल्प कहा जाना चाहिए। – Andreas

+3

बस उनका उपयोग न करें। – Alexander

+4

दी गई व्याख्या महान है। तथ्य यह है कि इस स्पष्टीकरण को देने की जरूरत नहीं है। जितना अधिक मैं स्विफ्ट के साथ काम करता हूं, उतना ही मैं इस धारणा के तहत हूं कि उन्होंने एक प्रकार की जटिलता को ओबीजेसी से दूसरे प्रकार के साथ बदल दिया है, और अंत में, यह एक या दूसरे का उपयोग करने के लिए उतना ही कठिन/व्यर्थ है। कैसे इस तरह की चीजें प्रोग्रामर के जीवन को आसान बनाना चाहिए मेरे बाहर है। –

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