Подтвердить что ты не робот

Протокол Swift в классе Objective-C

Я написал SearcherProtocol в Swift и вам нужно реализовать класс Objective-C FileSearcher, который должен использовать этот протокол.

Итак, я пробовал это:

#import <Foundation/Foundation.h>

@interface FileSearcher : NSObject <SearcherProtocol>

// ... class content

@end

Компилятор сообщает мне

Невозможно найти объявление протокола для "SearcherProtocol"

Соответствующий мостовой файл заголовка (modulename-Swift.h) импортируется в пределах FileSearcher.m.

Импортирование SearcherProtocol в FileSearcher.h вызывает другую ошибку компилятора: module name-swift.h file not found

Кто-нибудь знает, что я делаю неправильно?

Я использую Xcode 6 Beta 5.

Edit

Вот объявление протокола в Swift:

@objc protocol SearcherProtocol
{    
    var searchNotificationTarget: SearchCompletedProtocol? { get }
    var lastSearchResults: [AnyObject] { get set }

    func search(searchParam: String, error: NSErrorPointer) -> Bool
}

И SearchCompletedProtocol:

@objc protocol SearchCompletedProtocol
{
    func searchCompletedNotification(sender: AnyObject!)
}
4b9b3361

Ответ 1

Для этого существуют две общие причины:

  • Получение неправильного имени модуля, см. мой ответ.
  • Имея круговую ссылку - см. ниже ответ на митенегаты.

1. Получить имя модуля правильно:

Если и быстрый протокол, и Objective C находятся в одном проекте, то в соответствии с apple вам просто нужно убедиться вы получите правильное имя модуля.

Для Xcode6 beta 5 вы можете найти его в разделе BuildSettings- > Packaging- > Product Module Name

Общей ошибкой было бы думать, что каждый быстрый файл/класс получает свой собственный файл, но вместо этого все они помещаются в один большой, который является именем проекта.

Другие ошибки заключаются в том, что если имя модуля имеет пробелы, они должны быть заменены символами подчеркивания.

Edit:

С вашим протоколом я создал тестовый проект под названием "Тест", который отлично компилируется и имеет файлы:

TestObjClass.h

#import <Foundation/Foundation.h>
#import "Test-Swift.h"

@interface TestObjCClass : NSObject <SearcherProtocol>

@end

TestObjClass.m

#import "TestObjCClass.h"


@implementation TestObjCClass

@end

TestProtocol.swift

import Foundation

@objc protocol SearcherProtocol
{
    var searchNotificationTarget: SearchCompletedProtocol? { get }
    var lastSearchResults: [AnyObject] { get set }

    func search(searchParam: String, error: NSErrorPointer) -> Bool
}

@objc protocol SearchCompletedProtocol
{
    func searchCompletedNotification(sender: AnyObject!)
}

2. Избегайте круговой ссылки:

Ответ Mitrenegades объясняет это, но если вашему проекту нужно использовать явный класс objc, который использует быстрый протокол (вместо использования протокола), тогда у вас будут проблемы с округлостью. Причина в том, что быстрый протокол определяется заголовком swift-objc, а затем вашим определением класса obj-c, который затем снова возвращается к заголовку swift-objc.

Решение Mitrenegades заключается в использовании протокола objective-c, это один из способов, но если вы хотите быстрый протокол, то другой будет реорганизовать код, чтобы не использовать класс objective-c напрямую, а вместо этого использовать протокол (например, шаблон на основе протокола factory). В любом случае это может быть подходящим для ваших целей.

Ответ 2

Если у вас

#import "moduleName-Swift.h" 

в файле .h, который вы хотите быть делегатом, и у вас есть этот файл .h также в файле заголовков мостов, есть круговая ссылка, которая приводит к сбою компиляции moduleName-Swift.h. для проекта тестирования @james_alvarez, он, вероятно, работает, потому что вам не нужно включать TestObjClass.h в заголовок моста.

Лучший способ для меня объединить файлы objc, которые должны быть делегатом для класса, написанного в swift, но который также должен быть включен в заголовок моста, чтобы другие быстрые файлы могли получить доступ к этому классу objc, заключается в создании отдельный файл протокола в objc:

MyProtocol.h:

@protocol MyDelegate <NSObject>

-(void)didDoThis;
-(void)didDoThat;

@end

ViewController.h:

#import "MyProtocol.h"

@interface ViewController : UIViewController <MyDelegate>

MyProject-мост-header.h

#import "MyProtocol.h"
#import "ViewController.h"

Ответ 3

Я знаю, что это было давно, но я просто боролся с той же проблемой при добавлении протокола к моему Swift-коду, и он не добавлялся в заголовочный файл -Swift.h, следовательно, "Не удается найти протокол декларация"

Проблема заключалась в том, что мой протокол не был помечен как Public. Я изменил свой протокол:

@objc protocol MyProtocol { //etc.... }

:

@objc public protocol MyProtocol { //etc.... }

Я все еще не совсем уверен, зачем мне "публиковать", но никто больше не кажется, но он работает...

Ответ 4

Убедитесь, что вы включили автоматически созданный заголовок Swift в файл ObjectiveC. Он будет иметь то же имя, что и ваш модуль проекта, за которым следует -Swift.h.

Например, если ваш модуль проекта MyTarget, вы должны использовать:

#import "MyTarget-Swift.h"

Если вы вводите импорт в свой файл Objective C, он не будет автозаполнен. Вы можете убедиться, что у вас есть правильный файл, нажав Command на заголовок после ввода его.

Ответ 5

Импортировать делегат как это в файле .h

@protocol AnalyticProtocol;

и добавьте это в файл .swift

@objc public protocol AnalyticProtocol {

}

Ответ 6

Попробуйте добавить #import "Product_Module_Name-Swift.h" в ваш Product_Module_Name-Prefix.pch файл. Это исправило это для меня, плюс теперь у вас будет доступ к вашим быстрым файлам из любого файла objc.