Как я могу сделать элементный инициализатор общедоступным, по умолчанию, для структур в Swift?

165

У меня есть быстрый каркас, который определяет структуру:

public struct CollectionTO {
    var index: Order
    var title: String
    var description: String
}

Тем не менее, я не могу использовать неявный член мудрый инициализатор из другого проекта, который импортирует библиотеку. Ошибка «CollectionTO» не может быть инициализирована, поскольку у нее нет доступных инициализаторов. то есть он не дает неявному члену по умолчанию инициализировать ключевое слово public.

var collection1 = CollectionTO(index: 1, title: "New Releases", description: "All the new releases")

Я должен добавить свой собственный метод init следующим образом:

public struct CollectionTO {
    var index: Order
    var title: String
    var description: String

    public init(index: Order, title: String, description: String) {
        self.index = index;
        self.title = title;
        self.description = description;
    }

}

... но я бы предпочел нет, если есть другой способ, кто-нибудь знает?

bandejapaisa
источник

Ответы:

271

Цитирование руководства:

«Инициализаторы по умолчанию для каждого элемента по умолчанию для типов структуры. Инициализатор по умолчанию для каждого элемента по умолчанию для типа структуры считается закрытым, если какое-либо из сохраненных свойств структуры является закрытым. В противном случае инициализатор имеет внутренний уровень доступа.

Как и в случае с инициализатором по умолчанию, приведенным выше, если вы хотите, чтобы публичный тип структуры мог инициализироваться с помощью членного инициализатора при использовании в другом модуле, вы должны сами предоставить публичный членский инициализатор как часть определения типа. "

Отрывок из «Языка программирования Swift» , раздел «Контроль доступа» .

bandejapaisa
источник
289
Ну, это раздражает. :(
Дэн Лёвенхерц
7
[ github.com/apple/swift-evolution/blob/master/proposals/… говорит: «Цитирование Криса Латтнера: поведение по умолчанию для элементарного инициализатора Swift имеет, по крайней мере, следующие недостатки (IMO): 2) Контроль доступа + частый инициализация часто требует, чтобы вы реализовали это сами ». Так что, возможно, это просто недостаток, который существует без особой причины. Не удалось найти больше ссылок по этому поводу.
Jano
8
@DanLoewenherz Да, это неудобно. Обоснование таково: «Публичный тип по умолчанию имеет внутренних, а не публичных членов. Если вы хотите, чтобы член типа был общедоступным, вы должны явно пометить его как таковой. Это требование гарантирует, что общедоступный API для типа - это то, что вы выбираете для публикации, и избегает ошибочного представления внутренней работы типа как публичного API ». Выдержка из: Apple Inc. «Язык программирования Swift». интерактивные книги. itun.es/gb/jEUH0.l
bandejapaisa
18
Директива компилятора была бы хороша, чтобы переопределить поведение по умолчанию и сделать его общедоступным.
bandejapaisa
9
Внутренний - ужасный выбор по умолчанию, IMO. Это в основном гарантирует, что вы столкнетесь с неожиданными проблемами при обращении к внешнему модулю в первый раз. Почему бы не использовать все по умолчанию как приватное, чтобы мы могли сразу сказать, когда что-то не имеет правильного уровня доступа, а затем решить, должно ли оно быть публичным или внутренним?
devios1
72

Хотя по умолчанию нет возможности использовать элементный инициализатор по умолчанию, вы можете сделать его быстро, выполнив следующие шаги:

  1. Сделайте объект временно классом вместо структуры
  2. Сохранить
  3. Щелкните правой кнопкой мыши имя класса и выберите refactor -> Generate Memberwise Initializer.
  4. Измените его обратно на структуру
JP Aquino
источник
блестящий. не могу отблагодарить вас, чтобы обойти этот быстрый недостаток
Антон Тропашко
1
Работает, а также мотивирует использовать классы вместо структур youtube.com/watch?v=_V2sBURgUBI
Исаак Кэрол Вайсберг,
Это супер совет!
Пейманх
6
Начиная с Xcode 11, вы также можете использовать Generate Memberwise Initializer для структур!
Брок Бэтселл
Фантастика!!! Это не правильный ответ, но очень хороший совет! Мне очень помогли!
GuiOS
3

Пока Apple не изменит это и не сделает его менее раздражающим, вы можете использовать https://github.com/Bouke/SwiftInitializerGenerator (или любой другой) эту вещь для создания публичных инициализаторов. Так будет меньше работы. Попробовал и все работает. Xcode Version 10.0, High Sierra 10.13.6

Запорожченко Александр
источник
1

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

Этот драгоценный камень называется swift_republic

Пожалуйста, ознакомьтесь со следующей документацией для запуска этого драгоценного камня:

https://github.com/mehul90/swift_republic

Мехул Пармар
источник
1
Отличное решение !! Я уже создал обертку для swift_republicи работает нормально.
Md Shahed Hossain