Свойство нельзя объявить открытым, так как его тип использует внутренний тип (Typealias).

Я видел этот трюк для реализации независимого от платформы интерфейса (скажем) для классов изображений UIImage/NSImage:

#if os(iOS)
    import UIKit
    typealias Image = UIImage

#elseif os(macOS)
    import Cocoa
    typealias Image = NSImage

#endif

Теперь я пытаюсь принять его в рамках. Скажем, у меня есть такой класс:

public final class MyClass {

    public var image: Image // < Compiler Error (see below)

    init?(imageURL: URL) {
        guard let image = Image(contentsOf: imageFileURL) else {
        return nil
        }
        self.image = image
    }
}

Я получаю сообщение об ошибке:

Свойство нельзя объявить открытым, так как его тип использует внутренний тип

Относится ли «внутренний тип» к NSImage? Как это обойти?


Примечание. Я не думаю, что это дубликат этот вопрос: я использую < strong>typealias, неясно, какое объявление я должен пометить как "общедоступное".


person Nicolas Miari    schedule 07.09.2017    source источник


Ответы (1)


В этом конкретном случае (при использовании в целевом фреймворке) обнародование typealias не решит проблему. Вам также необходимо использовать проверку условия платформы при объявлении свойства изображения следующим образом:

#if os(iOS)
    import UIKit
    typealias Image = UIImage
#elseif os(macOS)
    import Cocoa
    typealias Image = NSImage
#endif

public final class MyClass {

    #if os(iOS)
        public var image: UIImage
    #elseif os(macOS)
        public var image: NSImage
    #endif

    init?(imageURL: URL) {
        guard let image = Image(contentsOf: imageFileURL) else {
            return nil
        }
        self.image = image
    }
}

То же самое относится к любым общедоступным методам, использующим этот тип, будь то параметр или возвращаемый тип функции.

Не по теме: обязательно инициализируйте этот класс в фоновой очереди/потоке, чтобы избежать блокировки основного потока и зависания пользовательского интерфейса во время загрузки изображения.

person Eneko Alonso    schedule 07.09.2017
comment
Спасибо. Это немного отстойно, что я должен #if os(... везде трясти, но я вижу смысл почему-то. - person Nicolas Miari; 07.09.2017
comment
@NicolasMiari Создание общедоступных компиляций typealias на моей стороне нормально, не уверен, почему это не так на вашей ... - person nyg; 07.09.2017
comment
@nyg, ты пробовал это в фреймворке? У меня есть фреймворк, который делает именно это, и мне нужно проверять ОС при объявлении общедоступных свойств или общедоступных методов, которым нужен этот тип. Разоблачения typealias недостаточно для фреймворка, не знаю почему. - person Eneko Alonso; 07.09.2017
comment
@EnekoAlonso Re: фоновая загрузка, это всегда URL-адреса локальных файлов. Мне это нравится больше, чем использование (сейчас) нерекомендуемых API-интерфейсов пути/строки. - person Nicolas Miari; 07.09.2017