Я делаю тестовый проект, чтобы увидеть, можно ли включить Apple ClassKit для школ в существующее учебное приложение ios с классами Objective-C ++ и C ++ в файлах .mm, и я получаю сообщение об ошибке в ...- Swift.h bridging header (автоматически создается xcode при добавлении файла swift), даже перед импортом bridging header в файлы ObjectiveC ++, чтобы предоставить им доступ к классам Swift.
В качестве простого тестового проекта ObjectiveC-Test, Я создал класс:
// Quiz.swift
import Foundation
import ClassKit
@objcMembers public class Quiz : NSObject
{
var mTitle : String
var mNumberOfProblems : Double
var mNumberCorrect : Double
var context = CLSContext (type : CLSContextType.quiz, identifier : "Test", title : "Parent Test")
override init ()
{
self.mTitle = ""
self.mNumberOfProblems = 0
self.mNumberCorrect = 0
super.init()
}
init (title : String)
{
self.mTitle = title
self.mNumberOfProblems = 0
self.mNumberCorrect = 0
}
} // end class
protocol Node
{
var parent : Node? { get }
var children : [Node]? { get }
var identifier : String { get }
var contextType : CLSContextType { get }
}
extension Quiz : Node
{
var parent : Node? { return nil }
var children : [Node]? { return nil }
var identifier : String { return mTitle }
var contextType : CLSContextType { return .quiz }
}
«Узел протокола» и «Расширение Quiz: Node» взяты из проекта Apple GreatPlays, который иллюстрирует, как включить ClassKitв проекты, но это строго Swift код.CLSContext является классом ClassKit и не вызывает никаких проблем, но "CLSContextType", перечисление в ClassKit, вызывает и приводит к ошибке в заголовке ...- Swift.h: "Неизвестное имя типа 'CLSContextType'.
Однако в классе викторины "CLSContextType.quiz" в "var context = CLSContext (...)" не вызывает никаких проблем. Но если я добавлю строку "" var contextType = CLSContextType.quiz "в класс викториныЯ получаю сообщение об ошибке.
Соответствующий код в сгенерированном xcode заголовке быстрого моста (ObjectiveC_Test-Swift.h):
@class CLSContext;
SWIFT_CLASS("_TtC15ObjectiveC_Test4Quiz")
@interface Quiz : NSObject
@property (nonatomic, copy) NSString * _Nonnull mTitle;
@property (nonatomic) double mNumberOfProblems;
@property (nonatomic) double mNumberCorrect;
@property (nonatomic, strong) CLSContext * _Nonnull context;
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
- (nonnull instancetype)initWithTitle:(NSString * _Nonnull)title OBJC_DESIGNATED_INITIALIZER;
@end
@interface Quiz (SWIFT_EXTENSION(ObjectiveC_Test))
@property (nonatomic, readonly, copy) NSString * _Nonnull identifier;
@property (nonatomic, readonly) CLSContextType contextType;
@end
Ошибка возникает в следующей за последней строкой:"CLSContextType contextType": "Неизвестное имя типа 'CLSContextType'".Он также генерирует ошибку: «Тип интерфейса не может быть статически распределен», но я думаю, что это связано с первой ошибкой.«CLSContext» в восьмой строке не вызывает никаких ошибок.
Если я закомментирую строки CLSContextType в протоколе и в расширении узла, проект будет работать нормально.
Проект находится подxcode 10.0 и ios 11.4.
Настройки сборки включают в себя:
Packaging
Defines Module: Yes
Build Options
Always Embed Swift Standard Libraries: Yes
Swift Compiler - General:
Install Objective-C Compatibility Header: Yes
Objective-C Bridging Header: ObjectiveC-Test/ObjectiveC-Test-Bridging-Header.h
Objective-C-Generated Interface Header Name: ObjectiveC_Test-Swift.h
Apple Clang - Language - C++
C++ Language Dialect: GNU++14 [std=gnu++14]
C++ Standard Library: libcc++ (LLVM C++ standard library with C++11 support)
Любая помощь будет принята с благодарностью.
Обновление:
Удаление "@objcMembers"из класса Quiz устранена ошибка CLSContextType в заголовочном мосте, созданном xcode, но свойства класса больше не были доступны из файлов Objective-C ++ .mm.Добавление «@obj» к исправленным, но не работающим с contextType.
Доступ к свойствам класса и их печать в файле Objective-C ++ .mm.
Свойства протокола, включая CLSContextType, может быть напечатан в файле Objective-C ++ .mm из функции swift (начало) и функции расширения узла (printContextTypeFromNodeExtension).
// @objcMembers public class Quiz : NSObject
public class Quiz : NSObject
{
@objc var mTitle : String
@objc var mNumberOfProblems : Double
@objc var mNumberCorrect : Double
// @objc var mLessonContextType : CLSContextType { return .lesson } // doesn't work
// causes same bridging error
@objc func start ()
{
print ("printing title from start() in swift: \(mTitle)")
print ("printing identifier from start() in swift: \(identifier)")
print ("printing CLSContextType from start() in swift: \(contextType.rawValue)")
printContextTypeFromNodeExtension ()
}
} // end class
extension Node
{
func printContextTypeFromNodeExtension ()
{
print ("printing CLSContextType from Node extension: \(contextType.rawValue)")
}
}
Файл Objective-C ++ .mm:
Quiz * Q1 = [ [Quiz alloc] init];
Q1.mTitle = @"Place Value Blocks";
Q1.mNumberOfProblems = 10;
Q1.mNumberCorrect = 3;
printf ("printing mTitle from objc: %s \n", [Q1.mTitle UTF8String] );
printf ("printing mNumberCorrect from objc: %f \n", Q1.mNumberCorrect);
[Q1 start];
Results:
printing mTitle from objc: Place Value Blocks
printing mNumberCorrect from objc: 3.000000
printing title from start() in swift: Place Value Blocks
printing identifier from start() in swift: Place Value Blocks
printing CLSContextType from start() in swift: 8
printing CLSContextType from Node extension: 8
Добавление "@objc" к протоколу Node позволило получить доступ ко всем свойствам Node в файлах Objective-C ++ .mm, кроме CLSContextType.Если его оставить, возвращается ошибка заголовка быстрого моста.
@objc protocol Node
{
var parent : Node? { get }
var children : [Node]? { get }
var identifier : String { get }
// var contextType : CLSContextType { get } // error if included when "@objc" added
}
extension Quiz : Node
{
var parent : Node? { return nil }
var children : [Node]? { return nil }
var identifier : String { return mTitle }
// var contextType : CLSContextType { return .quiz }
}
Objective-C++ .mm file:
printf ("printing parent from objc: %p \n", [Q1 parent] );
printf ("printing children from objc: %p \n", [Q1 children] );
printf ("printing identifier from objc: %s \n", [Q1.identifier UTF8String] );
Results:
printing parent from objc: 0x0
printing children from objc: 0x0
printing identifier from objc: Place Value Blocks
Вывод: в другом посте я нашел комментарий, в котором говорилось, что перечисления и структуры, определенные в Swift, недоступны в Objective-C, но не могутне найти ссылку, поэтому может быть предпочтительнее использовать классы вместо структур и работать с перечислениями только в быстрых файлах.