#swiftui
#swiftui
Вопрос:
Я хочу реализовать кнопку SwiftUI, которая принимает onTapGesture
и onLongPressGesture
с переопределяемым обработчиком
Мне не удалось заставить встроенную кнопку работать с обоими, поэтому я прибегнул HStack
к. Кнопки используют CommandController
шаблон и отправляют команду из onTapGesture
. Базовый код был:
struct CmdButton : View {
@EnvironmentObject var appController : AppController
var command : AppCommand
init(command : AppCommand) {
self.command = command
self.onTapGesture {
self.doCommand()
}
}
var body: some View {
HStack {
Image(self.command.icon).resizable().scaledToFit().frame(width: 35)
}
.padding(6)
.cornerRadius(5)
.contentShape(Rectangle())
.animation(.default)
}
func doCommand(){
appController.dispatchCommand(command: self.command)
}
}
Цель состояла в том, чтобы CmdButton
вызывать doCommand()
from onTapGesture
по умолчанию, если он не был переопределен разработчиком, таким образом:
CmdButton(command: SomeCommand)
.onTapGesture {
doSomethingFirst()
instance.doCommand()
}
.onLongPressGesture {
doLongPressAction()
}
У меня есть 2 основные проблемы.
Кажется, я никак не могу захватить правильный self
контекст в CmdButton
реализации, чтобы добавить значение по умолчанию onTapGesture
, если я добавлю во init
время получения mutating self
ошибки. Если я добавлю жест в HStack, он не может быть переопределен, и я не вижу, как привести some View
к конкретному типу для назначения непосредственно на var body
.
Когда я переопределяю onTapGesture
, я не могу получить self
контекст экземпляра в переопределенном onTapGesture
обработчике для вызова doCommand()
метода.
Я знаю, что мог бы обойти обратные вызовы и присоединить их к реализации, но это может вызвать другие проблемы с захватом контекста и просто кажется хакерским для чего-то настолько простого и тривиального.
Редактировать
Чтобы уточнить, согласно документам Apple, допустимо:
struct MyView : View {
let img : String = "asset"
let name : String = "Some Name"
var body: some View {
Image(img).onTapGesture {
onTap()
}
}
func onTap(){
print(name)
}
}
Где захвачен правильный контекст и обработчик жестов, прикрепленный к Image
. Мой вопрос заключается в том, что вместо того, чтобы жест присваивался внутренней реализации, как я могу назначить его телу внешнего представления, чтобы его можно было переопределить.
MyView()
.onTapGesture {
doSomethingElse()
self_instance.onTap()
}
Опять же, я могу вызвать:
MyView().onTap()
Как мне заставить экземпляр представления вызывать onTap
внутри обработчика?
Комментарии:
1. Вы пытаетесь применить проактивные принципы ООП к миру SwiftUI, основанному на реактивных значениях, поэтому потерпели неудачу. Вернитесь к сеансам SwiftUI WWDC-19.
2. Работает ли исходный код вообще? Вы должны получать предупреждение типа «Результат вызова ‘onTapGesture’ не используется». Если это и работает, то из-за какого-то побочного эффекта, который почти наверняка является неопределенным поведением. Вызов
.onTapGesture
не изменяет представление. Это создает совершенно новый вид, который обтекает цель. Итак, вы создаете представление, которое реагирует на жесты касания, а затем просто выбрасываете его. Ваш подход здесь невозможен, потому что представления не являются объектами среды выполнения, такими как UIViews; это просто данные, которые описывают макет и поведение.3. Привет, Роб, никакое присвоение
onTapGesture
init
не считается изменяющим self, поэтому не может быть выполнено. Я хочу сказать, как создать обработчик жестов по умолчанию, который можно переопределить, и захватить правильный контекст в этом сценарии.