Используйте NSProxy в Swift 4.1

Как создать NSProxy подкласс в Swift?

Попытка добавить любой из init методы завершаются с ошибкой: "Super init не может быть вызван вне инициализатора" или "Super init не вызывается на всех путях до возврата из инициализатора"

Error1 Error2

Использование подкласса Objective-C в качестве базового класса работает, но больше похоже на взлом:

// Create a base class to use instead of `NSProxy`
@interface WorkingProxyBaseClass : NSProxy
- (instancetype)init;
@end

@implementation WorkingProxyBaseClass
- (instancetype)init
{
  if (self) {

  }
  return self;
}
@end



// Use the newly created Base class to inherit from in Swift
import Foundation

class TestProxy: WorkingProxyBaseClass {
  override init() {
    super.init()
  }
}

2 ответа

NSProxy - это абстрактный класс. В документации Apple о NSProxy говорится: "Абстрактный суперкласс, определяющий API для объектов, которые действуют как заместители для других объектов или для объектов, которые еще не существуют".

Документы об абстрактном классе Википедии говорят:

В языке, который поддерживает наследование, абстрактный класс или абстрактный базовый класс (ABC) - это класс, который не может быть создан, потому что он либо помечен как абстрактный, либо просто определяет абстрактные методы (или виртуальные методы).

Calling super.init()для абстрактного класса это неправильно. Во втором классе ты не звонишьsuper.init() для абстрактного класса, но из WorkingProxyBaseClassкоторый является конкретным классом. В Objective c вы не звонили[super init] следовательно, код работает.

Простое решение: создать класс Objective-C, который наследуется от NSProxy, а затем наследовать от него класс Swift.

Пример на моем GitHub: https://gist.github.com/SoundBlaster/0e53bae4ab814537c5868564d95eb553

      // Objective-C Header BaseProxyForSwift.h

NS_ASSUME_NONNULL_BEGIN

NS_SWIFT_NAME(BaseProxyForSwift)
@interface BaseProxyForSwift : NSProxy

+ (id)with:(id)object;

@end

NS_ASSUME_NONNULL_END
      // Objective-C Implementation BaseProxyForSwift.m

#import "BaseProxyForSwift.h"

@interface BaseProxyForSwift ()
@property (nonatomic, strong) id object;
@end

@implementation BaseProxyForSwift

+ (id)with:(id)object {
    BaseProxyForSwift *res = [self alloc];
    res.object = object;
    return res;
}

@end
      // Swift Implementation BaseSwiftProxy.swift

import Foundation

public class BaseSwiftProxy: BaseProxyForSwift {}
      // Usage in Swift

let a = NSObject()
let p = BaseSwiftProxy.with(a)

Не забывайте о связующих заголовках Objective-C, если вы будете смешивать языки в одном проекте: https://developer.apple.com/documentation/swift/importing-objective-c-into-swift.

Другие вопросы по тегам