Swift डेवलपर को क्लास नाम स्ट्रिंग के रूप में क्यों चाहिए?
\n\nएक स्थिति की कल्पना करें: आप एक जटिल एप्लिकेशन के लिए लॉगिंग विकसित कर रहे हैं। प्रत्येक इवेंट में न केवल संदेश होना चाहिए, बल्कि उस क्लास का नाम भी होना चाहिए जिसमें वह हुआ। या आप एक सार्वभौमिक JSON पार्सर बना रहे हैं जिसे स्ट्रिंग कुंजी द्वारा मॉडल प्रकार निर्धारित करना होगा। या आप retain cycle को डीबग कर रहे हैं और मेमोरी में सभी ऑब्जेक्ट्स को उनके क्लास नामों के साथ डायनामिक रूप से प्रदर्शित करना चाहते हैं।
\n\nइन सभी मामलों में, आपको एक ही चीज़ चाहिए: Swift में ऑब्जेक्ट का क्लास नाम स्ट्रिंग के रूप में प्राप्त करना। यह आसान लगता है, है ना? लेकिन यह उतना सीधा नहीं है। Objective-C के विपरीत, Swift में कोई एक "जादुई" तरीका नहीं है जो सभी स्थितियों में पूरी तरह से काम करे। इसके अलावा, अलग-अलग तरीके अलग-अलग प्रदर्शन देते हैं, और कुछ तो अप्रत्याशित परिणाम भी देते हैं।
\n\nइस लेख में, हम केवल तैयार उत्तर नहीं देंगे, बल्कि Swift में क्लास नाम प्राप्त करने के सभी तरीकों का विश्लेषण करेंगे, उनकी गति की तुलना करेंगे और दिखाएंगे कि कब कौन सा तरीका इस्तेमाल करना चाहिए। आप सीखेंगे कि खतरों से कैसे बचें और ऐसा कोड लिखें जो प्रोडक्शन में विफल न हो।
\n\nक्लासिक तरीका: String(describing: type(of:))
\n\nइस विषय पर Stack Overflow पर सबसे लोकप्रिय उत्तर type(of:) और String(describing:) के संयोजन का उपयोग करना है। आइए देखें कि यह कैसे काम करता है।
class Car {\n var model: String\n init(model: String) {\n self.model = model\n }\n}\n\nlet myCar = Car(model: "Tesla Model 3")\nlet className = String(describing: type(of: myCar))\nprint(className) // "Car"\n\nयह तरीका वास्तव में सरल और सहज है। type(of:) ऑब्जेक्ट का मेटाटाइप लौटाता है, और String(describing:) इसे स्ट्रिंग में बदल देता है। लेकिन एक बारीकी है: यह ऑप्शनल टाइप और प्रोटोकॉल के लिए सही ढंग से काम नहीं करता।
ऑप्शनल के साथ समस्या
\n\nlet optionalCar: Car? = Car(model: "BMW")\nlet optionalName = String(describing: type(of: optionalCar))\nprint(optionalName) // "Optional<Car>" — यह वह नहीं है जो आपने उम्मीद की थी!\n\n"Car" के बजाय आपको "Optional<Car>" मिलता है। ऐसा इसलिए होता है क्योंकि type(of:) मान के प्रकार को लौटाता है, न कि उसकी सामग्री को। ऑप्शनल के लिए, यह Optional<Car> है।
प्रोटोकॉल और इनहेरिटेंस के साथ समस्या
\n\nprotocol Drivable { }\nextension Car: Drivable { }\n\nlet drivableObject: Drivable = Car(model: "Audi")\nlet protocolName = String(describing: type(of: drivableObject))\nprint(protocolName) // "Car" — यहाँ काम कर गया, लेकिन हमेशा नहीं\n\nप्रोटोकॉल के साथ, परिणाम अप्रत्याशित हो सकता है, खासकर यदि प्रोटोकॉल कंपोज़िशन या Any का उपयोग किया जाता है। निष्कर्ष: यह तरीका सरल मामलों के लिए अच्छा है, लेकिन ऑप्शनल और जटिल टाइप वाले प्रोडक्शन कोड के लिए नहीं।
Objective-C विरासत: NSStringFromClass
\n\nयदि आप Objective-C से आए हैं, तो आपको शायद NSStringFromClass([self class]) याद होगा। Swift में भी यह काम करता है, लेकिन कुछ शर्तों के साथ:
import Foundation\n\nclass Motorcycle {\n var brand: String\n init(brand: String) {\n self.brand = brand\n }\n}\n\nlet bike = Motorcycle(brand: "Harley")\nlet objcClassName = NSStringFromClass(type(of: bike))\nprint(objcClassName) // "_TtC11YourModule11Motorcycle" — मैंगल्ड नाम!\n\nSwift में क्लास के नाम "विकृत" (mangled) होते हैं। "Motorcycle" के बजाय आपको कुछ इस तरह मिलता है _TtC11YourModule11Motorcycle। साफ नाम पाने के लिए, आपको इसे मैन्युअल रूप से "पार्स" करना होगा या String(describing:) का उपयोग करना होगा।
हालांकि, एक महत्वपूर्ण लाभ है: NSStringFromClass किसी भी ऑब्जेक्ट के साथ काम करता है, जिसमें ऑप्शनल भी शामिल हैं, और nil पर क्रैश नहीं होता। लेकिन कोड की सफाई के लिए इसे सीधे उपयोग न करना बेहतर है।
NSStringFromClass की आवश्यकता कब होती है?
\n- \n
- Obje