ios - उद्देश्य-सी के अंदर स्विफ्ट कक्षाओं का उपयोग नहीं कर सकते हैं




objective-c swift (13)

@ एसआईजी उत्तर सबसे अच्छा है, हालांकि, यह मेरे लिए पुरानी परियोजना (नया नहीं!) के साथ काम नहीं करता है, मुझे कुछ संशोधनों की आवश्यकता है। कई बदलावों के बाद मुझे मेरे लिए नुस्खा मिला (एक्सकोड 7.2 का उपयोग करके):

  1. उत्पाद मॉड्यूल का नाम: $ (PRODUCT_NAME: c99extidentifier)
  2. मॉड्यूल परिभाषित करता है: नहीं
  3. एम्बेडेड सामग्री में स्विफ्ट शामिल है: नहीं
  4. उद्देश्य-सी संगतता शीर्षलेख स्थापित करें: हाँ
  5. उद्देश्य-सी ब्रिजिंग हैडर: ProjectName-Bridging-Header.h

अंतिम बिंदु (5) महत्वपूर्ण था। मैंने इसे केवल दूसरे खंड (लक्ष्य फ़ील्ड) पर रखा है, परियोजना क्षेत्र खाली छोड़ा जाना चाहिए: अन्यथा, यह मेरे लिए सही "प्रोजेक्ट-स्विफ्ट.h" फ़ाइल उत्पन्न नहीं करता है (इसमें स्विफ्ट विधियां शामिल नहीं थीं)।

मैं अपने ऐप में Swift कोड को एकीकृत करने की कोशिश करता हूं। मेरा ऐप Objective-C में लिखा गया Objective-C और मैंने एक Swift क्लास जोड़ा है। मैंने here वर्णित सब कुछ किया here । लेकिन मेरी समस्या यह है कि -Swift.h ने -Swift.h फ़ाइल नहीं बनाई है, केवल ब्रिजिंग हेडर। तो मैंने इसे बनाया, लेकिन यह वास्तव में खाली है। मैं स्विफ्ट में अपने सभी ओबीजेसी कक्षाओं का उपयोग कर सकता हूं, लेकिन मैं इसके विपरीत नहीं कर सकता। मैंने अपनी स्विफ्ट क्लास को @objc साथ चिह्नित किया लेकिन इससे मदद नहीं मिली। अब मैं क्या कर सकता हूँ?

संपादित करें: ऐप्पल कहता है: "जब आप ऑब्जेक्टिव-सी में स्विफ्ट कोड आयात करते हैं, तो आप ऑब्जेक्टिव-सी में उन फ़ाइलों को बेनकाब करने के लिए Xcode-generated हेडर फ़ाइल पर भरोसा करते हैं। [...] इस हेडर का नाम आपका उत्पाद मॉड्यूल नाम है "-Swift.h" जोड़कर। "

अब जब मैं उस फ़ाइल को आयात करना चाहता हूं, तो यह एक त्रुटि देता है:

    //MainMenu.m

    #import "myProjectModule-Swift.h" //Error: 'myProjectModule-Swift.h' file not found

    @implementation MainMenu

यहां मेरी FBManager.swift फ़ाइल है:

@objc class FBManager: NSObject {

    var descr = "FBManager class"

    init() {
        super.init()
    }

    func desc(){
        println(descr)
    }

    func getSharedGameState() -> GameState{
        return GameState.sharedGameState() //OK! GameState is written in Objective-C and no error here
    }
}

एक्सकोड को अपना काम करने की अनुमति दें, स्विफ्ट हेडर मैन्युअल रूप से जोड़ें / बनाएं। बस अपने स्विफ्ट कक्षा पूर्व से पहले @objc जोड़ें।

@objc class YourSwiftClassName: UIViewController

अपनी प्रोजेक्ट सेटिंग में नीचे झंडे की खोज करें और इसे YES में बदलें (परियोजना और लक्ष्य दोनों)

Defines Module : YES
Always Embed Swift Standard Libraries : YES
Install Objective-C Compatibility Header : YES

फिर प्रोजेक्ट को साफ करें और सफल होने के बाद, इसे अपने उद्देश्य-सी क्लास .m फ़ाइल में शीर्षलेख फ़ाइल के नीचे आयात करें

#import "YourProjectName-Swift.h" 

Boooom!


बस .m या .h फ़ाइल में #import "myProject-Swift.h" शामिल करें

पीएस आपको फाइल इंस्पेक्टर में "myProject-Swift.h" नहीं मिलेगा, यह छिपा हुआ है। लेकिन यह स्वचालित रूप से ऐप द्वारा उत्पन्न होता है।


मुझे इसमें समस्याएं थीं, मैं अपने उद्देश्य-सी ब्रिजिंग हेडर में कक्षाएं जोड़ूंगा, और उन उद्देश्यों-सी शीर्षकों में आयात किए गए थे, वे तेजी से हेडर आयात करने की कोशिश कर रहे थे। यह पसंद नहीं आया।

तो मेरे सभी उद्देश्य-सी वर्गों में जो तेजी से उपयोग करते हैं, लेकिन वे भी ब्रिज किए जाते हैं, कुंजी यह सुनिश्चित करना था कि आप हेडर में आगे की कक्षा घोषणाओं का उपयोग करें, फिर .m फ़ाइल में "* -Swift.h" फ़ाइल आयात करें।


मुझे बिल्ड में किसी भी सेटिंग्स को बदलने या कक्षा में @obj जोड़ने की ज़रूरत नहीं थी।

मुझे बस इतना करना था कि ब्रिज-हेडर बनाना जो स्वचालित रूप से बनाया गया था जब मैंने ऑब्जेक्टिव-सी प्रोजेक्ट में स्विफ्ट क्लासेस बनाए। और फिर मुझे बस करना पड़ा

"बेडटाइम-स्विफ्ट.h" आयात करें <- उद्देश्य-सी फ़ाइल के अंदर जो उस त्वरित फ़ाइल का उपयोग करने के लिए आवश्यक है।


मेरा मुद्दा यह था कि -swift.h फ़ाइल की स्वत: पीढ़ी कस्टमडिबगस्ट्रिंग कन्वर्टिबल के उप-वर्ग को समझने में सक्षम नहीं थी। मैंने वर्ग को बदले में एनएसओब्जेक्ट का उप-वर्ग बनने के लिए बदल दिया। उसके बाद, -swift.h फ़ाइल में अब कक्षा को ठीक से शामिल किया गया है।


मेरे पास एक ही त्रुटि है: myProjectModule-Swift.h फ़ाइल नहीं मिली ", लेकिन, मेरे मामले में, वास्तविक कारण गलत तैनाती लक्ष्य में था:" 10.9 से पहले ओएस एक्स पर Swift अनुपलब्ध है; कृपया MACOSX_DEPLOYMENT_TARGET को 10.9 या बाद में सेट करें (वर्तमान में यह '10 .7 'है) "इसलिए, जब मैंने तैनाती लक्ष्य को 10.9 में बदल दिया है - परियोजना को सफलतापूर्वक संकलित किया गया था।


मेरे पास एक ही समस्या थी और मॉड्यूल नाम में विशेष प्रतीकों को बदल दिया गया है xcode द्वारा प्रतिस्थापित किया गया है (मेरे मामले में डैश अंडरस्कोर होने पर समाप्त हो गया है)। प्रोजेक्ट सेटिंग्स में अपनी प्रोजेक्ट के लिए मॉड्यूल नाम खोजने के लिए "मॉड्यूल नाम" की जांच करें। इसके बाद या तो ModuleName-Swift.h उपयोग करें या सेटिंग्स में मॉड्यूल का नाम बदलें।


मैंने अपने Xcode उद्देश्य-सी आधारित परियोजना में Swift को सक्षम करने के लिए लगभग 4 घंटे बिताए। मेरी " myproject-Swift.h " फ़ाइल सफलतापूर्वक बनाई गई थी, लेकिन मेरे myproject-Swift.h मेरी Swift-classes दिखाई नहीं दे रही थीं। इसलिए, मैंने एक नया एक्सकोड ओबीजेसी-आधारित प्रोजेक्ट बनाने का फैसला किया और अंत में मुझे सही जवाब मिला! उम्मीद है कि यह पोस्ट किसी की मदद करेगा :-)

Xcode Objc- आधारित प्रोजेक्ट के लिए चरण स्विफ्ट एकीकरण द्वारा कदम:

  1. नई *.swift फ़ाइल ( *.swift में) बनाएं या फ़ाइंडर का उपयोग करके इसे जोड़ें
  2. जब एक्सकोड आपको इसके बारे में पूछता है तो एक Objective-C bridging header बनाएं
  3. @objc विशेषता के साथ अपने स्विफ्ट क्लास को कार्यान्वित करें:

    import UIKit
    
    @objc public class CustomView: UIView {
        override func draw(_ rect: CGRect) {
            // Drawing code
        }
    }
    
  4. बिल्ड सेटिंग्स खोलें और उन पैरामीटर को जांचें:

    • मॉड्यूल परिभाषित करता है: YES
    • उत्पाद मॉड्यूल नाम: myproject

      सुनिश्चित करें कि आपके उत्पाद मॉड्यूल नाम में कोई विशेष वर्ण नहीं है

    • उद्देश्य-सी संगतता शीर्षलेख स्थापित करें: YES

      एक बार जब आप परियोजना में *.swift फ़ाइल जोड़ *.swift यह प्रॉपर्टी बिल्ड सेटिंग्स में दिखाई देगी

    • उद्देश्य-सी जेनरेटेड इंटरफेस हैडर: myproject-Swift.h

      यह हेडर एक्सकोड द्वारा स्वतः उत्पन्न होता है

    • उद्देश्य-सी ब्रिजिंग हैडर: $(SRCROOT)/myproject-Bridging-Header.h
  5. अपने * .m फ़ाइल में स्विफ्ट इंटरफेस हेडर आयात करें

    #import "myproject-Swift.h"
    

    त्रुटियों और चेतावनियों पर ध्यान न दें।

  6. अपने एक्सकोड परियोजना को साफ और पुनर्निर्माण करें
  7. फायदा!

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


हेडर फ़ाइल स्वयं न बनाएं। आपके द्वारा बनाए गए एक को हटाएं।

सुनिश्चित करें कि आपकी स्विफ्ट कक्षाओं को @objc साथ टैग किया @objc या @objc से प्राप्त (सीधे या अप्रत्यक्ष रूप से) कक्षा से प्राप्त होता है।

यदि आपके प्रोजेक्ट में कोई कंपाइलर त्रुटियां हैं तो एक्सकोड फ़ाइल उत्पन्न नहीं करेगा - सुनिश्चित करें कि आपकी परियोजना साफ-सुथरा हो।


दो शर्त है,

  • उद्देश्य सी फ़ाइल में अपनी स्विफ्ट फ़ाइल का प्रयोग करें।
  • स्विफ्ट फ़ाइल में अपनी उद्देश्य सी फ़ाइल का प्रयोग करें।

तो, उस उद्देश्य के लिए, आपको इन चरणों का पालन करना होगा:

  • एक उद्देश्य-सी परियोजना या इसके विपरीत में अपनी स्विफ्ट फ़ाइल जोड़ें।
  • हेडर (.h) फ़ाइल बनाएं।
  • बिल्ड सेटिंग्स पर जाएं और खोज के साथ नीचे दिए गए चरणों को करें,

    1. इस पाठ को "ब्रिज" के लिए खोजें और अपनी हेडर फ़ाइल का पथ सेट करें।
    2. "मॉड्यूल परिभाषित करता है": हाँ।
    3. "हमेशा स्विफ्ट मानक पुस्तकालय एम्बेड करें": हाँ।
    4. "उद्देश्य-सी संगतता शीर्षलेख स्थापित करें": हाँ।

उसके बाद, अपनी परियोजना को साफ और पुनर्निर्माण करें।

उद्देश्य सी फ़ाइल में अपनी स्विफ्ट फ़ाइल का प्रयोग करें।

उस स्थिति में, सबसे पहले अपनी कक्षा से पहले स्विफ्ट फ़ाइल में "@objc" लिखें।

उसके बाद, अपनी उद्देश्य सी फ़ाइल में, इसे लिखें,

  #import "YourProjectName-Swift.h"

स्विफ्ट फ़ाइल में अपनी उद्देश्य सी फ़ाइल का प्रयोग करें।

उस स्थिति में, अपनी हेडर फ़ाइल में, इसे लिखें,

  #import "YourObjective-c_FileName.h"

उम्मीद है इससे आपको मदद मिलेगी।


विवरण: एक्सकोड 8.1 में स्विफ्ट 3 कोड के साथ उद्देश्य-सी परियोजना

कार्य:

  1. उद्देश्य-सी कक्षा में तेजी से enum का उपयोग करें
  2. स्विफ्ट क्लास में उद्देश्य-सी enum का प्रयोग करें

पूर्ण नमूना

1. उद्देश्य-सी वर्ग जो स्विफ्ट एनम का उपयोग करती है

ObjcClass.h

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, ObjcEnum) {
    ObjcEnumValue1,
    ObjcEnumValue2,
    ObjcEnumValue3
};

@interface ObjcClass : NSObject

+ (void) PrintEnumValues;

@end

ObjcClass.m

#import "ObjcClass.h"
#import "SwiftCode.h"

@implementation ObjcClass

+ (void) PrintEnumValues {
    [self PrintEnumValue:SwiftEnumValue1];
    [self PrintEnumValue:SwiftEnumValue2];
    [self PrintEnumValue:SwiftEnumValue3];
}

+ (void) PrintEnumValue:(SwiftEnum) value {
    switch (value) {
        case SwiftEnumValue1:
            NSLog(@"-- SwiftEnum: SwiftEnumValue1");
            break;

        case SwiftEnumValue2:
        case SwiftEnumValue3:
            NSLog(@"-- SwiftEnum: long value = %ld", (long)value);
            break;
    }
}

@end

उद्देश्य-सी कोड में स्विफ्ट कोड का पता लगाएं

मेरे नमूने में मैं उद्देश्य-सी में स्विफ्ट कोड का पता लगाने के लिए SwiftCode.h का उपयोग करता हूं। यह फ़ाइल स्वचालित रूप से उत्पन्न होती है (मैंने प्रोजेक्ट में इस हेडर फ़ाइल की भौतिक प्रति नहीं बनाई है), और आप केवल इस फ़ाइल का नाम सेट कर सकते हैं:

यदि संकलक आपकी हेडर फ़ाइल स्विफ्ट कोड नहीं ढूंढ पा रहा है, तो प्रोजेक्ट को संकलित करने का प्रयास करें।

2. स्विफ्ट क्लास जो उद्देश्य-सी enum का उपयोग करें

import Foundation

@objc
enum SwiftEnum: Int {
    case Value1, Value2, Value3
}

@objc
class SwiftClass: NSObject {

    class func PrintEnumValues() {
        PrintEnumValue(.Value1)
        PrintEnumValue(.Value2)
        PrintEnumValue(.Value3)
    }

    class func PrintEnumValue(value: ObjcEnum) {
        switch value {
        case .Value1, .Value2:
            NSLog("-- ObjcEnum: int value = \(value.rawValue)")

        case .Value3:
            NSLog("-- ObjcEnum: Value3")
            break
        }

    }
}

स्विफ्ट कोड में उद्देश्य-सी कोड का पता लगाएं

आपको ब्रिजिंग हेडर फ़ाइल बनाने की आवश्यकता है। जब आप ऑब्जेक्टिव-सी प्रोजेक्ट में स्विफ्ट फ़ाइल जोड़ते हैं, या स्विफ्ट प्रोजेक्ट में ऑब्जेक्टिव-सी फ़ाइल एक्सकोड आपको ब्रिजिंग हेडर बनाने का सुझाव देगा।

आप ब्रिजिंग हेडर फ़ाइल नाम यहां बदल सकते हैं:

ब्रिजिंग-Header.h

#import "ObjcClass.h"

प्रयोग

#import "SwiftCode.h"
...
[ObjcClass PrintEnumValues];
[SwiftClass PrintEnumValues];
[SwiftClass PrintEnumValue:ObjcEnumValue3];

परिणाम

अधिक नमूने

पूर्ण एकीकरण कदम ऊपर वर्णित उद्देश्य सी और स्विफ्ट । अब मैं कुछ अन्य कोड उदाहरण लिखूंगा।

3. उद्देश्य-सी कोड से स्विफ्ट क्लास कॉल करें

स्विफ्ट क्लास

import Foundation

@objc
class SwiftClass:NSObject {

    private var _stringValue: String
    var stringValue: String {
        get {
            print("SwiftClass get stringValue")
            return _stringValue
        }
        set {
            print("SwiftClass set stringValue = \(newValue)")
            _stringValue = newValue
        }
    }

    init (stringValue: String) {
        print("SwiftClass init(String)")
        _stringValue = stringValue
    }

    func printValue() {
        print("SwiftClass printValue()")
        print("stringValue = \(_stringValue)")
    }

}

उद्देश्य-सी कोड (कॉलिंग कोड)

SwiftClass *obj = [[SwiftClass alloc] initWithStringValue: @"Hello World!"];
[obj printValue];
NSString * str = obj.stringValue;
obj.stringValue = @"HeLLo wOrLd!!!";

परिणाम

4. स्विफ्ट कोड से उद्देश्य-सी वर्ग पर कॉल करें

उद्देश्य-सी वर्ग (ObjcClass.h)

#import <Foundation/Foundation.h>

@interface ObjcClass : NSObject
@property NSString* stringValue;
- (instancetype) initWithStringValue:(NSString*)stringValue;
- (void) printValue;
@end

ObjcClass.m

#import "ObjcClass.h"

@interface ObjcClass()

@property NSString* strValue;

@end

@implementation ObjcClass

- (instancetype) initWithStringValue:(NSString*)stringValue {
    NSLog(@"ObjcClass initWithStringValue");
    _strValue = stringValue;
    return self;
}

- (void) printValue {
    NSLog(@"ObjcClass printValue");
    NSLog(@"stringValue = %@", _strValue);
}

- (NSString*) stringValue {
    NSLog(@"ObjcClass get stringValue");
    return _strValue;
}

- (void) setStringValue:(NSString*)newValue {
    NSLog(@"ObjcClass set stringValue = %@", newValue);
    _strValue = newValue;
}

@end

स्विफ्ट कोड (कॉलिंग कोड)

if let obj = ObjcClass(stringValue:  "Hello World!") {
    obj.printValue()
    let str = obj.stringValue;
    obj.stringValue = "HeLLo wOrLd!!!";
}

परिणाम

5. उद्देश्य-सी कोड में स्विफ्ट एक्सटेंशन का उपयोग करें

स्विफ्ट एक्सटेंशन

extension UIView {
    static func swiftExtensionFunc() {
        NSLog("UIView swiftExtensionFunc")
    }
}

उद्देश्य-सी कोड (कॉलिंग कोड)

[UIView swiftExtensionFunc];

6. स्विफ्ट कोड में उद्देश्य-सी एक्सटेंशन का उपयोग करें

उद्देश्य-सी एक्सटेंशन (UIViewExtension.h)

#import <UIKit/UIKit.h>

@interface UIView (ObjcAdditions)
+ (void)objcExtensionFunc;
@end

UIViewExtension.m

@implementation UIView (ObjcAdditions)
+ (void)objcExtensionFunc {
    NSLog(@"UIView objcExtensionFunc");
}
@end

स्विफ्ट कोड (कॉलिंग कोड)

UIView.objcExtensionFunc()




swift