Посмотрите на несколько различных способов связать класс с интерфейсом SwiftUI.

Я играл со SpriteKit, и мне пришло в голову, что это может быть хорошим упражнением, чтобы напомнить себе о том, сколько разных способов я могу связать свой код SwiftUI с моей сценой / классом SpriteKit. Я не представляю их в каком-либо порядке, предпочтениях или рекомендациях; Я показываю их в том порядке, в каком они более-менее приходили мне в голову.

Краткое

Я запускаю сцену SpriteKit в приложении SwiftUI и хочу иметь возможность управлять спрайтом напрямую с помощью элемента SwiftUI, в данном случае кнопки. Присоединяйтесь ко мне, чтобы узнать, сколько способов я могу приготовить - сделать именно это.

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

С конечной целью придумать как можно больше разных способов сделать это, синий текст jump - это кнопка SwiftUI. Кролик - это SKSpriteNode внутри сцены, размещенной в моем интерфейсе SwiftUI.

Очевидно, что указанный код не совсем подходит для того, что вы здесь видите, потому что нам нужно реализовать ссылку.

1. Использование синглтонов

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

Я уже определил общий ресурс как синглтон в классе GameScene. Недостатком, конечно же, является то, что метод перехода в моем GameScene должен быть доступен всем, что, возможно, является плохим кодированием.

2. Использование PassthroughSubject

Это была моя вторая мысль, которая, честно говоря, почти такая же, как первая, за исключением того, что я перенаправляю кнопку через структуру Combine.

Главное преимущество, которое я могу придумать, - организационное. Если я получу доступ ко всем своим внешним методам, используя такую ​​технику, тогда я, возможно, смогу структурировать свой код с помощью некоторых предопределенных правил. К сожалению, jump(), конечно, все еще не конфиденциально.

3. ObservableObject

Это классическое решение Combine + SwiftUI. Он требует использования синглтона и, возможно, является самым чистым на данный момент.

Самый чистый в том смысле, что нет прямой связи между GameScene и ContentView. В нем я определил общую переменную как промежуточный класс, который используется для запуска метода jump().

С другой стороны, я не думаю, что в конечном итоге это очень масштабируемое решение, так как метод обновления быстро забивается стартовыми переменными.

4. Использование подписок

Это также классическое решение Combine + SwiftUI, хотя я не часто вижу его в таких местах, как Stack Overflow.

Я подозреваю, потому что это немного загадочно и, честно говоря, немного похоже на выражение «goto».

Я подписываюсь на участника класса jointp в моем ContentView.swift. Подписка, которая запускает метод перехода, если видит какое-либо действие. Jointp здесь снова посредник, и это хорошо, и плохо.

Причина, по которой я чувствую, что это немного похоже на goto, заключается в том, что нет правил, по которым вы настраиваете подписку.

Здесь он отлично работает, потому что мне нужно сделать это в методе didMove, но теоретически мы могли бы подписаться где угодно и создать строку, которая будет запускать метод перехода из любого места - что-то вроде goto.

В этом решении есть скрытое преимущество; теоретически вы можете отменить подписку и отключить кнопку. Прочтите эту статью, чтобы узнать, как это сделать.

5. Переменный триггер

Это решение похоже на первое. В нем я создал переменную, которая будет выполнять мой jump() метод при обращении к нему. Было бы неплохо попытаться установить некоторые командные правила, чтобы структурировать подобные вещи в коде. Это немного лучше, чем прямая версия , потому что вы не обращаетесь к методу напрямую; вы обращаетесь к переменной.

6. Глобальная тема

Это решение очень похоже на второе решение за исключением того, что PassthroughSubject виден глобально. Очевидно, что это не лучший выбор, поскольку глобальная переменная может вызвать хаос во время доступа.

jump тоже не является личным. Чем больше я об этом думаю, тем больше наихудшее решение :).

7. Безопасная подписка

Как я сказал в начале, здесь нет реального порядка, хотя, читая эту статью Санделла, я обнаружил, что могу разделить PassthroughSubject издателя.

Это имеет большое преимущество: в отличие от предыдущих решений, у меня теперь нет прямого доступа к нему. Доступ предоставляется через метод fire только в классе jointp.

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

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

Все это подводит меня к концу статьи.

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

Надеюсь, вам понравилось читать эту статью так же, как я ее исследовал и писал.

Сохранять спокойствие; продолжайте кодировать.