Як я можу зробити за замовчуванням загальнодоступний ініціалізатор для структур у Swift?


165

У мене є швидкий фреймворк, який визначає структуру:

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

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

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;
    }

}

... але я вважаю за краще ні, якщо є інший спосіб, коли хтось знає?

Відповіді:


270

Цитуючи посібник:

"Ініціалізатори типових структур для типових структур Стандартні ініціалізатори для типу структури за замовчуванням вважаються приватними, якщо будь-яка з збережених властивостей структури є приватною. Інакше ініціалізатор має внутрішній рівень доступу.

Як і у випадку з ініціалізатором за замовчуванням, наведеним вище, якщо ви хочете, щоб тип публічної структури ініціалізувався з ініціалізатором, що належить до членства, коли використовується в іншому модулі, ви повинні надати публічний ініціалізатор відкритий член як частину визначення типу. "

Уривок з "Мова швидкого програмування" , розділ "Контроль доступу" .


289
Ну, це дратує. :(
Dan Loewenherz

7
[ github.com/apple/swift-evolution/blob/master/proposals/… говорить: “Цитування Кріса Леттнера: поведінка ініціалізатора за замовчуванням Swift має принаймні такі недоліки (IMO): 2) Контроль доступу + членство init часто вимагає, щоб ти сам це реалізував ». Тож, можливо, це просто недолік, який існує без особливих причин. Не вдалося знайти більше посилань на це.
Яно

8
@DanLoewenherz Так, це незручно. Обгрунтування таке: “За замовчуванням публічний тип має внутрішні члени, а не громадські члени. Якщо ви хочете, щоб член типу був загальнодоступним, ви повинні чітко позначити його як такого. Ця вимога гарантує, що відкритий для API тип для типу - це те, що ви вирішили опублікувати, і уникає представлення внутрішніх функцій типу як публічного API помилково. " Уривок: Apple Inc. "Мова швидкого програмування". iBooks. itun.es/gb/jEUH0.l
bandejapaisa

18
Директива компілятора було б непогано змінити поведінку за замовчуванням та оприлюднити її.
bandejapaisa

9
Внутрішній - це страшний вибір для дефолту, imo. Це в основному гарантує, що у вас виникнуть несподівані проблеми при посиланні на модуль вперше. Чому б за замовчуванням все не було приватним, щоб ми могли негайно сказати, коли щось не задано правильним рівнем доступу, а потім вирішити, чи має бути воно публічним чи внутрішнім?
devios1

72

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

  1. Зробіть об'єкт тимчасово класом замість структури
  2. Зберегти
  3. Клацніть правою кнопкою миші назву класу та виберіть рефактор -> Створити ініціалізатор
  4. Змініть його назад до структури

блискучий. не можу подякувати вам достатньо, щоб
подолати

1
Працює, а також мотивує фактично використовувати класи замість структури youtube.com/watch?v=_V2sBURgUBI
Ісаак Керол Вайсберг

Це супер порада !!
Пейманх

6
Станом на Xcode 11, ви також можете використовувати Generate Memberwise Initializer і на структури!
Брок Батселл

Фантастичний !!! Це не правильна відповідь, але це дуже гарна порада! Мені дуже допомогли!
GuiOS

3

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


1

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

Цей самоцвіт називається swift_republic

Перевірте наступну документацію для запуску цього дорогоцінного каменю:

https://github.com/mehul90/swift_republic


1
Дивовижне рішення !! Я вже створив обгортку для swift_republicроботи і чудово працюю.
Md Shahed
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.