Я пытаюсь создать экземпляр одноэлементного класса, написанного в Objective-C. Я должен соответствовать этому протоколу делегирования. Реализация Swift выглядит примерно так:
class SomeClass: ManagerDelegate {
let manager = Manager.sharedInstance()
func someFunction(){
manager.delegate = self
}
}
Класс Single-Object Object-C выглядит примерно так:
// header
@protocol ManagerDelegate <NSObject>
@required
-(void)delegateMethod;
@end
@interface Manager : NSObject {
}
+ (id)sharedInstance;
@property (nonatomic, assign) id delegate;
@end
// class file
+ (id) sharedManager{
static Manager *theSharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
theSharedManager = [[self alloc] init];
});
return theSharedManager;
}
- (void) someInternalMethod{
[delegate delegateMethod];
}
После указания делегата (manager.delegate = self
), я получаю ошибку
Неоднозначная ссылка на делегата участника '
Является ли класс Objective-C некорректно сформированным или я его неправильно реализую? Я что-то пропустил?
Ваша проблема вызвана определением вашего метода sharedInstance
в Objective-C. Объявив это как
+ (id)sharedInstance;
он преобразуется в sharedInstance() → AnyObject! в Свифт. Swift тогда не знает, какой из многих потенциальных свойств delegate
он может найти, что вы имеете в виду. Если вы измените декларацию и реализацию Objective C:
+ (instancetype)sharedInstance;
ваша проблема исчезнет.
И как указывает @rmaddy, ваш делегат должен быть weak
не assign
. Если вы используете assign
то delegate
будет оставлен как недопустимый указатель в том случае, если делегат будет освобожден.
Кроме того, использование делегата с синглоном несколько противоречиво. Учитывая, что у вас будет только один экземпляр Manager
который может использоваться рядом других объектов, и вы можете иметь только один активный делегат одновременно, существует вероятность конфликтов.
Я бы предположил, что либо блоки/закрытия, либо NSNotification
- лучший подход к NSNotification
из одноэлементного.
Это потому, что всякий раз, когда вы приводите экземпляр из объектного кода c в swift, он дает как AnyObject, так что
let manager = Manager.sharedInstance() //manager is AnyObject due to bridging between objc and swift
дает вам свойство AnyObject для менеджера. Вам необходимо принудительно применить этот AnyObject к Manager для использования в качестве экземпляра менеджера, как показано ниже.
class SomeClass: NSObject, ManagerDelegate {
let manager = Manager.sharedInstance() as! Manager //here was your error
func someFunction(){
manager.delegate = self
}
func delegateMethod() {
print("Hello")
}
}
Надеюсь, это решает вашу проблему :)
sharedInstance
чтобы возвращать instancetype
вместо id
?
NSObject
или же он наследуется от какого-то другого объекта?