swift - क्या(U) Int8/16/32/64 प्रकारों के लिए Foundation(NSNumber) के लिए स्विफ्ट स्वचालित संख्यात्मक मान को दोहराने के लिए संभव है?



swift2 (1)

सवाल

  • क्या यह संभव है कि फाउंडेशन के लिए UInt32 न्यूमेरिक वैल्यू टाइप किया जाए, जैसे कि Int32 , UInt32 , Int64 और UInt64 प्रकार? विशेष रूप से, नीचे द्वारा कवर किए गए स्वचालित उप-असाइनमेंट को दोहराते हुए।

इस तरह के समाधान का इरादा उदाहरण उपयोग:

let foo : Int64 = 42
let bar : NSNumber = foo
    /* Currently, as expected, error:
       cannot convert value of type 'Int64' to specified type 'NSNumber */

पृष्ठभूमि

मूल स्विफ्ट संख्या (मूल्य) के कुछ प्रकारों को स्वचालित रूप से NSNumber (संदर्भ) प्रकार के लिए ब्रिज किया जा सकता है:

स्विफ्ट संख्यात्मक संरचना प्रकारों के उदाहरण, जैसे Int , UInt , Float , Double और AnyObject , को AnyObject प्रकार द्वारा प्रस्तुत नहीं किया जा सकता है, क्योंकि AnyObject केवल एक वर्ग प्रकार के उदाहरणों का प्रतिनिधित्व करता है। हालाँकि, जब Foundation को ब्रिजिंग सक्षम किया जाता है, तो स्विफ्ट संख्यात्मक मानों को NSNumber वर्ग के ब्रिज किए गए इंस्टेंसेस के रूप में AnyObject प्रकार के स्थिरांक और चर को सौंपा जा सकता है।

...

स्विफ्ट NSNumber करने के NSNumber स्वचालित रूप से कुछ मूल संख्या प्रकारों जैसे कि Int और Float को ब्रिज करता है। यह ब्रिजिंग आपको इनमें से एक प्रकार से एक NSNumber बनाने की सुविधा देता है:

let n = 42
let m: NSNumber = n

यह आपको NSNumber अपेक्षा करने वाले तर्क के लिए, Int के प्रकार का मान भी पास करने की अनुमति देता है। ...

निम्न प्रकार के सभी स्वचालित रूप से NSNumber के लिए तैयार हैं:

- Int
- UInt
- Float
- Double
- Bool

इंटरऑपरेबिलिटी से - कोको डेटा प्रकारों के साथ काम करना - नंबर

तो IntXX / UIntXX प्रकार के लिए इसे दोहराने का प्रयास क्यों?

मुख्य रूप से: जिज्ञासा, कुछ प्रश्नों को देखकर हाल ही में अंतर्निहित समस्याओं के साथ भ्रम की स्थिति को देखते हुए कि क्यों एक Int मान प्रकार प्रतीत होता है किसी AnyObject (संदर्भ) चर द्वारा प्रतिनिधित्व किया जा सकता है, जबकि Int64 , जैसे नहीं; जो स्वाभाविक रूप से ऊपर कवर किए गए ब्रिजिंग द्वारा समझाया गया है। कुछ लेने के लिए:

हालांकि, Q & A: में से कोई भी उल्लेख नहीं है, हालांकि, वास्तव में गैर- UInt16 प्रकार Int64 , UInt16 और इतने से AnyObject ( NSNumber ) पर इस तरह के स्वचालित ब्रिजिंग को लागू करने की संभावना है। इन थ्रेड्स के जवाबों के बजाय (सही ढंग से) यह AnyObject पर ध्यान केंद्रित किया जाता है कि AnyObject मान प्रकारों को क्यों नहीं पकड़ सकता है, और IntXX / UIntXX प्रकार पूर्व के अंतर्निहित फाउंडेशन प्रकारों के लिए स्वचालित रूपांतरण के लिए कैसे तैयार नहीं हैं।

दूसरी बात: 32-बिट और 64-बिट दोनों आर्किटेक्चर पर चलने वाले अनुप्रयोगों के लिए, कुछ संकीर्ण उपयोग के मामले हैं - स्विफ्ट देशी नंबर प्रकारों का उपयोग करके किसी भी संदर्भ में, किसी संदर्भ में परिवर्तित किया गया है - जहाँ Int32 या Int64 प्रकार का उपयोग करके Int पर प्राथमिकता दी जाएगी। एक (कुछ) ऐसा उदाहरण:


हां (यह संभव है): प्रोटोकॉल के अनुरूप द्वारा _ObjectiveCBridgeable

(निम्नलिखित उत्तर Swift 2.2 और XCode 7.3 का उपयोग करने पर आधारित है।)

जिस तरह मैं इस पोस्ट को पोस्ट करने या केवल इस प्रश्न को छोड़ने पर विचार कर रहा था, मैं स्विफ्ट स्रोत कोड में स्विफ्ट swift/stdlib/public/core/BridgeObjectiveC.swift पर ठोकर खा गया, विशेष रूप से प्रोटोकॉल _ObjectiveCBridgeable । मैंने संक्षेप में पहले Swiftdoc.org पर प्रोटोकॉल देखा है, लेकिन बाद में इसके वर्तमान (खाली) ब्लूप्रिंट फॉर्म में, मैंने कभी इसके बारे में ज्यादा सोचा नहीं है। हालांकि, स्विफ्ट स्रोत से _ObjectiveCBridgeable लिए ब्लूप्रिंट का उपयोग करना, हालांकि, कस्टम प्रकार के कुछ मूल निवासी को तेजी से इसके अनुरूप करने दे सकते हैं।

आगे बढ़ने से पहले, ध्यान दें कि _ObjectiveCBridgeable एक आंतरिक / छिपा हुआ प्रोटोकॉल ( _UnderScorePreFixedProtocol ) है, इसलिए इसके आधार पर समाधान आगामी स्विफ्ट संस्करणों में चेतावनी के बिना टूट सकता है।

फाउंडेशन वर्ग NSNumber लिए Int64 ब्रिजिंग को सक्षम करना

एक उदाहरण के रूप में, Int64 का विस्तार _ObjectiveCBridgeable अनुरूप करने के लिए _ObjectiveCBridgeable , और बाद में परीक्षण करें कि यह काफी सरल फिक्स Int64 से फाउंडेशन वर्ग NSNumber धारण करने के लिए निहित प्रकार रूपांतरण (ब्रिजिंग) के लिए पर्याप्त है।

import Foundation

extension Int64: _ObjectiveCBridgeable {

    public typealias _ObjectiveCType = NSNumber

    public static func _isBridgedToObjectiveC() -> Bool {
        return true
    }

    public static func _getObjectiveCType() -> Any.Type {
        return _ObjectiveCType.self
    }

    public func _bridgeToObjectiveC() -> _ObjectiveCType {
        return NSNumber(longLong: self)
    }

    public static func _forceBridgeFromObjectiveC(source: _ObjectiveCType, inout result: Int64?) {
        result = source.longLongValue
    }

    public static func _conditionallyBridgeFromObjectiveC(source: _ObjectiveCType, inout result: Int64?) -> Bool {
        self._forceBridgeFromObjectiveC(source, result: &result)
        return true
    }
}

परीक्षा:

/* Test case: scalar */
let fooInt: Int = 42
let fooInt64: Int64 = 42
var fooAnyObj : AnyObject

fooAnyObj = fooInt    // OK, natively
fooAnyObj = fooInt64  // OK! _ObjectiveCBridgeable conformance successful

/* Test case: array */
let fooIntArr: [Int] = [42, 23]
let fooInt64Arr: [Int64] = [42, 23]
var fooAnyObjArr : [AnyObject]

fooAnyObjArr = fooIntArr    // OK, natively
fooAnyObjArr = fooInt64Arr  // OK! _ObjectiveCBridgeable conformance successful

इसलिए, _ObjectiveCBridgeable यह वास्तव में संगत फाउंडेशन वर्ग के लिए स्वचालित उप-असाइनमेंट को सक्षम करने के लिए पर्याप्त है; इस मामले में, NSNumber (स्विफ्ट में, __NSCFNumber )।

Int8 , UInt8 , Int16 , UInt16 , Int32 , UInt32 , ( Int64 ), और UInt64 को NSNumber

Int64 से _ObjectiveCBridgeable उपरोक्त अनुरूप नीचे NSNumber रूपांतरण तालिका का उपयोग करके स्विफ्ट-देशी पूर्णांक प्रकारों में से किसी को कवर करने के लिए आसानी से संशोधित किया जा सकता है।

/* NSNumber initializer:               NSNumber native Swift type property
   --------------------------------    -----------------------------------
   init(char: <Int8>)                  .charValue
   init(unsignedChar: <UInt8>)         .unsignedCharValue
   init(short: <Int16>)                .shortValue
   init(unsignedShort: <UInt16>)       .unsignedShortValue
   init(int: <Int32>)                  .intValue
   init(unsignedInt: <UInt32>)         .unsignedIntValue
   init(longLong: <Int64>)             .longLongValue
   init(unsignedLongLong: <UInt64>)    .unsignedLongLongValue              */




nsnumber