खोज…


संपत्ति, एक प्रोटोकॉल एक्सटेंशन में, संबंधित वस्तु का उपयोग करके हासिल की।

स्विफ्ट में, प्रोटोकॉल एक्सटेंशन में सच्चे गुण नहीं हो सकते।

हालांकि, व्यवहार में आप "संबंधित वस्तु" तकनीक का उपयोग कर सकते हैं। परिणाम लगभग "वास्तविक" संपत्ति की तरह है।

प्रोटोकॉल एक्सटेंशन में "संबंधित वस्तु" जोड़ने की सटीक तकनीक यहां दी गई है:

मूल रूप से, आप ऑब्जेक्टिव- c "objc_getAssociatedObject" और _set कॉल का उपयोग करते हैं।

मूल कॉल हैं:

get {
   return objc_getAssociatedObject(self, & _Handle) as! YourType
   }
set {
   objc_setAssociatedObject(self, & _Handle, newValue, .OBJC_ASSOCIATION_RETAIN)
    }

यहाँ एक पूर्ण उदाहरण है। दो महत्वपूर्ण बिंदु हैं:

  1. प्रोटोकॉल में, आपको उत्परिवर्तन समस्या से बचने के लिए ": वर्ग" का उपयोग करना चाहिए।

  2. विस्तार में, आपको पुष्टिकरण प्रकार देने के लिए "जहां स्व: यूवाईवीकॉन्ट्रोलर" (या जो भी उपयुक्त वर्ग) का उपयोग करना चाहिए।

इसलिए, एक उदाहरण संपत्ति "पी" के लिए:

import Foundation
import UIKit
import ObjectiveC          // don't forget this

var _Handle: UInt8 = 42    // it can be any value

protocol Able: class {
    var click:UIView? { get set }
    var x:CGFloat? { get set }
    // note that you >> do not << declare p here
}

extension Able where Self:UIViewController {
       
    var p:YourType { // YourType might be, say, an Enum
      get {
          return objc_getAssociatedObject(self, & _Handle) as! YourType
          // HOWEVER, SEE BELOW
          }
      set {
          objc_setAssociatedObject(self, & _Handle, newValue, .OBJC_ASSOCIATION_RETAIN)
          // often, you'll want to run some sort of "setter" here...
          __setter()
          }
    }
    
    func __setter() { something = p.blah() }
    
    func someOtherExtensionFunction() { p.blah() }
    // it's ok to use "p" inside other extension functions,
    // and you can use p anywhere in the conforming class
}

किसी भी अनुरूप वर्ग में, आपने अब "गुण" "p" जोड़ दिया है:

आप "पी" का उपयोग कर सकते हैं जैसे आप अनुरूप वर्ग में किसी भी सामान्य संपत्ति का उपयोग करेंगे। उदाहरण:

class Clock:UIViewController, Able {
    var u:Int = 0

    func blah() {
      u = ...
      ... = u
      // use "p" as you would any normal property
      p = ...
      ... = p
    }

    override func viewDidLoad() {
      super.viewDidLoad()
      pm = .none // "p" MUST be "initialized" somewhere in Clock 
    }
}

ध्यान दें। आप छद्म संपत्ति को शुरू करना चाहिए।

Xcode आपको अनुरूपता वर्ग में "p" को इनिशियलाइज़ नहीं करेगा

यह जरूरी है कि आप "पी" को इनिशियलाइज़ करें, शायद कन्फर्मिंग क्लास के व्यूडलड में।

यह याद रखने योग्य है कि पी वास्तव में केवल एक गणना की गई संपत्ति है । पी वास्तव में सिंटैक्टिक शुगर के साथ केवल दो कार्य हैं। कहीं भी कोई p "वेरिएबल" नहीं है: कंपाइलर किसी भी अर्थ में "p के लिए कुछ मेमोरी असाइन नहीं करता है"। इस कारण से, "प्रारंभिक पी" को लागू करने के लिए Xcode की अपेक्षा करना व्यर्थ है।

वास्तव में, अधिक सटीक बोलने के लिए, आपको "पहली बार पी का उपयोग करना याद रखना चाहिए, जैसे कि आप इसे शुरू कर रहे थे"। (फिर से, यह आपके viewDidLoad कोड में होने की संभावना है।)

पाने वाले के संबंध में।

ध्यान दें कि अगर "p" सेट होने के लिए गेटर को वैल्यू से पहले कॉल किया जाता है तो यह क्रैश हो जाएगा

इससे बचने के लिए, कोड पर विचार करें:

    get {
        let g = objc_getAssociatedObject(self, &_Handle)
        if (g == nil) {
            objc_setAssociatedObject(self, &_Handle, _default initial value_, .OBJC_ASSOCIATION)
            return _default initial value_
        }
        return objc_getAssociatedObject(self, &_Handle) as! YourType
        }

दोहराना। Xcode आपको अनुरूप वर्ग में पी को इनिशियलाइज़ करने के लिए लागू नहीं करेगा । यह जरूरी है कि आप पी को इनिशियलाइज़ करें, कन्फर्मिंग क्लास के व्यूडलड में कहें।

कोड को सरल बनाना ...

आप इन दो वैश्विक कार्यों का उपयोग करना चाह सकते हैं:

func _aoGet(_ ss: Any!, _ handlePointer: UnsafeRawPointer!, _ safeValue: Any!)->Any! {
    let g = objc_getAssociatedObject(ss, handlePointer)
    if (g == nil) {
        objc_setAssociatedObject(ss, handlePointer, safeValue, .OBJC_ASSOCIATION_RETAIN)
        return safeValue
    }
    return objc_getAssociatedObject(ss, handlePointer)  
}

func _aoSet(_ ss: Any!, _ handlePointer: UnsafeRawPointer!, _ val: Any!) {
    objc_setAssociatedObject(ss, handlePointer, val, .OBJC_ASSOCIATION_RETAIN)
}

ध्यान दें कि वे कुछ भी नहीं करते हैं, जो कुछ भी है, टाइपिंग को बचाने के अलावा और कोड को अधिक पठनीय बनाते हैं। (वे अनिवार्य रूप से मैक्रोज़ या इनलाइन फ़ंक्शन हैं।)

आपका कोड तब बन जाता है:

protocol PMable: class {
    var click:UILabel? { get set } // ordinary properties here
}

var _pHandle: UInt8 = 321

extension PMable where Self:UIViewController {

    var p:P {
        get {
            return _aoGet(self, &_pHandle, P() ) as! P
        }
        set {
            _aoSet(self, &_pHandle, newValue)
            __pmSetter()
        }
    }
    
    func __pmSetter() {
        click!.text = String(p)
    }
    
    func someFunction() {
        p.blah()
    }
}

(उदाहरण में _aoGet पर, P initalizable है: P () के बजाय आप "", 0, या कोई डिफ़ॉल्ट मान उपयोग कर सकते हैं।)



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow