Swift Language
सी और ऑब्जेक्टिव-सी के साथ काम करना
खोज…
टिप्पणियों
अधिक जानकारी के लिए, कोको और ऑब्जेक्टिव-सी के साथ स्विफ्ट का उपयोग करने पर एप्पल के दस्तावेज देखें।
उद्देश्य-सी कोड से स्विफ्ट कक्षाओं का उपयोग करना
एक ही मॉड्यूल में
" MyModule " नाम के एक मॉड्यूल के अंदर, Xcode MyModule-Swift.h
नाम का एक हेडर MyModule-Swift.h
जो ऑब्जेक्टिव-सी के लिए सार्वजनिक स्विफ्ट क्लासेस को उजागर करता है। स्विफ्ट कक्षाओं का उपयोग करने के लिए इस हेडर को आयात करें:
// MySwiftClass.swift in MyApp
import Foundation
// The class must be `public` to be visible, unless this target also has a bridging header
public class MySwiftClass: NSObject {
// ...
}
// MyViewController.m in MyApp
#import "MyViewController.h"
#import "MyApp-Swift.h" // import the generated interface
#import <MyFramework/MyFramework-Swift.h> // or use angle brackets for a framework target
@implementation MyViewController
- (void)demo {
[[MySwiftClass alloc] init]; // use the Swift class
}
@end
प्रासंगिक निर्माण सेटिंग्स:
- Objective-C Generated Interface Header Name : उत्पन्न ओब्ज-सी हेडर के नाम को नियंत्रित करता है।
- ऑब्जेक्टिव-सी कम्पेटिबिलिटी हैडर स्थापित करें : क्या -Swift.h हेडर एक सार्वजनिक हेडर (फ्रेमवर्क टारगेट के लिए) होना चाहिए।
एक अन्य मॉड्यूल में
@import MyFramework;
का उपयोग करना @import MyFramework;
पूरे मॉड्यूल को आयात करता है, जिसमें स्विफ्ट कक्षाओं के लिए ओब्ज-सी इंटरफेस शामिल है (यदि उपरोक्त निर्माण सेटिंग सक्षम है)।
स्विफ्ट कोड से ऑब्जेक्टिव-सी कक्षाओं का उपयोग करना
यदि MyFramework में इसके सार्वजनिक हेडर (और छाता हेडर) में ऑब्जेक्टिव-सी कक्षाएं शामिल हैं, तो import MyFramework
को import MyFramework
करें, जो स्विफ्ट से उनका उपयोग करने के लिए आवश्यक है।
शीर्षासन करते हुए
एक ब्रिजिंग हेडर अतिरिक्त उद्देश्य-सी और सी घोषणाओं को स्विफ्ट कोड को दिखाई देता है। प्रोजेक्ट फ़ाइलें जोड़ते समय, Xcode स्वतः ही ब्रिजिंग हेडर बनाने की पेशकश कर सकता है:
मैन्युअल रूप से एक बनाने के लिए, ऑब्जेक्टिव-सी ब्रिजिंग हैडर बिल्ड सेटिंग को संशोधित करें:
ब्रिजिंग हेडर के अंदर, कोड से उपयोग करने के लिए जो भी फाइलें आवश्यक हैं आयात करें:
// MyApp-Bridging-Header.h
#import "MyClass.h" // allows code in this module to use MyClass
उत्पन्न इंटरफ़ेस
संबंधित आइटम बटन पर क्लिक करें (या ⌃1 दबाएं), फिर स्विफ्ट इंटरफ़ेस देखने के लिए जेनरेट किए गए इंटरफ़ेस का चयन करें जो कि ऑब्जेक्टिव-सी हेडर से उत्पन्न होगा।
एक ब्रिडिंग हेडर को स्विचेस में निर्दिष्ट करें
-import-objc-header
ध्वज के लिए एक हैडर निर्दिष्ट करता swiftc
आयात करने के लिए:
// defs.h
struct Color {
int red, green, blue;
};
#define MAX_VALUE 255
// demo.swift
extension Color: CustomStringConvertible { // extension on a C struct
public var description: String {
return "Color(red: \(red), green: \(green), blue: \(blue))"
}
}
print("MAX_VALUE is: \(MAX_VALUE)") // C macro becomes a constant
let color = Color(red: 0xCA, green: 0xCA, blue: 0xD0) // C struct initializer
print("The color is \(color)")
$ swiftc demo.swift -import-objc-header defs.h && ./demo MAX_VALUE is: 255 The color is Color(red: 202, green: 202, blue: 208)
सी हेडर आयात करने के लिए एक मॉड्यूल मैप का उपयोग करें
मॉड्यूल मैप बस सी हेडर फ़ाइलों को पढ़ने और उन्हें स्विफ्ट फ़ंक्शंस के रूप में प्रदर्शित करने के लिए कॉन्फ़िगर करके import mymodule
कर सकता है।
नाम की एक फ़ाइल जगह module.modulemap
एक नामी निर्देशिका के अंदर mymodule
:
मॉड्यूल मैप फ़ाइल के अंदर:
// mymodule/module.modulemap
module mymodule {
header "defs.h"
}
फिर मॉड्यूल import
करें:
// demo.swift
import mymodule
print("Empty color: \(Color())")
जहां मॉड्यूल खोजने के लिए swiftc
बताने के लिए -I directory
ध्वज का उपयोग करें:
swiftc -I . demo.swift # "-I ." means "search for modules in the current directory"
मॉड्यूल मैप सिंटैक्स के बारे में अधिक जानकारी के लिए, मॉड्यूल मैप्स के बारे में क्लैंग प्रलेखन देखें।
उद्देश्य-सी और स्विफ्ट के बीच बारीक-बारीक हस्तक्षेप
जब एक API को NS_REFINED_FOR_SWIFT
से चिह्नित किया NS_REFINED_FOR_SWIFT
, तो यह स्विफ्ट के लिए आयात होने पर दो अंडरस्कोर ( __
) के साथ उपसर्ग किया जाएगा:
@interface MyClass : NSObject
- (NSInteger)indexOfObject:(id)obj NS_REFINED_FOR_SWIFT;
@end
उत्पन्न इंटरफ़ेस इस तरह दिखता है:
public class MyClass : NSObject {
public func __indexOfObject(obj: AnyObject) -> Int
}
अब आप एपीआई को अधिक "स्विफ्टी" एक्सटेंशन के साथ बदल सकते हैं। इस स्थिति में, हम एक वैकल्पिक रिटर्न मान का उपयोग कर सकते हैं, NSNotFound को छानकर :
extension MyClass {
// Rather than returning NSNotFound if the object doesn't exist,
// this "refined" API returns nil.
func indexOfObject(obj: AnyObject) -> Int? {
let idx = __indexOfObject(obj)
if idx == NSNotFound { return nil }
return idx
}
}
// Swift code, using "if let" as it should be:
let myobj = MyClass()
if let idx = myobj.indexOfObject(something) {
// do something with idx
}
ज्यादातर मामलों में आप प्रतिबंधित कर सकते हैं कि क्या ऑब्जेक्टिव-सी फ़ंक्शन का तर्क nil
हो सकता है या नहीं। यह _Nonnull
कीवर्ड का उपयोग करके किया जाता है, जो किसी भी पॉइंटर या ब्लॉक संदर्भ को योग्य _Nonnull
:
void
doStuff(const void *const _Nonnull data, void (^_Nonnull completion)())
{
// complex asynchronous code
}
उस लिखित के साथ, संकलक एक त्रुटि का उत्सर्जन करेगा जब भी हम अपने स्विफ्ट कोड से उस फ़ंक्शन को nil
पास करने की कोशिश करते हैं:
doStuff(
nil, // error: nil is not compatible with expected argument type 'UnsafeRawPointer'
nil) // error: nil is not compatible with expected argument type '() -> Void'
के विपरीत _Nonnull
है _Nullable
, जिसका अर्थ है कि इसे पारित करने के स्वीकार्य है nil
इस तर्क में। _Nullable
भी डिफ़ॉल्ट है; हालाँकि, यह स्पष्ट रूप से निर्दिष्ट करने से अधिक स्व-प्रलेखित और भविष्य-प्रूफ कोड की अनुमति मिलती है।
अपने कोड को अनुकूलित करने के साथ कंपाइलर की मदद करने के लिए, आप यह भी बताना चाहेंगे कि ब्लॉक बच रहा है या नहीं:
void
callNow(__attribute__((noescape)) void (^_Nonnull f)())
{
// f is not stored anywhere
}
इस विशेषता के साथ हम फ़ंक्शन के निष्पादन के बाद ब्लॉक संदर्भ को बचाने और ब्लॉक को कॉल न करने का वादा करते हैं।
C मानक पुस्तकालय का उपयोग करें
स्विफ्ट की सी इंटरऑपरेबिलिटी आपको सी मानक लाइब्रेरी से कार्यों और प्रकारों का उपयोग करने की अनुमति देती है।
लिनक्स पर, सी मानक लाइब्रेरी को Glibc
मॉड्यूल के माध्यम से उजागर किया Glibc
है; Apple प्लेटफार्मों पर इसे Darwin
कहा जाता है।
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
import Darwin
#elseif os(Linux)
import Glibc
#endif
// use open(), read(), and other libc features