У меня есть приложение UIKit (оно прекрасно обрабатывает и поддерживает APNS), я добавляю ActivityAttributes
и таким образом запускаю активность.
Итак, это TestAttributes
;
обратите внимание, что используется в виджете TestWidg
;
и используется в качестве контента в Activity#request
.
Нужно каким-то образом получить это «в» цели, поэтому я поместил это в TestWidgBundle
, весь код ниже.
Все это работает отлично, и когда вы lactivities.test()
. Вы получаете жетон и др.,
** check true
** activity ID woot 0384DF90-795E-487A-ADAC-185203E25F22
** traverse ok
** token woot gPk5RJkfAi/dCrZG4GVc7/4E48uQ...Po3vz+9jKcD4C4qjg+M=
Естественно, я
и т. д. и т. д.
НО живая активность так и не появляется.
Наверняка, я делаю что-то концептуально неправильно, потому что фактически не поместил Виджет/WidgetBundle в проект - ???
т. е. рассматриваемый проект имеет только одну цель — основную сборку iOS.
Я запускал другие проекты (например, тестовые проекты из Интернета) на своих телефонах и сим-картах, которые четко показывают, что Live Activity / Happy Island отображаются правильно.
Нужно ли struct TestWidgBundle: WidgetBundle
что-то большее, чем объявление, чтобы добавить новую цель, или ?
import UIKit
import ActivityKit
import WidgetKit
import SwiftUI
/// singleton for Live Activity Feat. "dynamic island" etc
let lactivities = Lactivities.shared
/// access using `lactivities.`
final class Lactivities: NSObject {
static let shared = Lactivities()
private override init() { super.init() }
///Give it a go ...
func test() {
print("** check", ActivityAuthorizationInfo().areActivitiesEnabled )
let att = TestAttributes(name: "test")
let cs = TestAttributes.ContentState(news: "test")
let cont = ActivityContent.init(state: cs, staleDate: nil, relevanceScore: 1.0)
do {
let activity = try Activity.request(attributes: att, content: cont, pushType: .token)
print("** activity ID woot", activity.id)
Task {
for await pushToken in activity.pushTokenUpdates {
print("** token woot", pushToken.base64EncodedString()
)
}
}
}
catch let error { print("** lactivity ERR!!!!", error) }
print("** traverse ok")
}
}
.. и структуры ..
struct TestAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
var news: String
}
var name: String
}
struct TestWidg: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: TestAttributes.self) { context in
SimpleView(state: context.state, stuff: context.attributes)
} dynamicIsland: { context in
DynamicIsland { DynamicIslandExpandedRegion(.bottom) {
VStack { Text(context.attributes.name) } }
} compactLeading: { Text(context.attributes.name)
} compactTrailing: { Image(systemName: "testtube.2")
} minimal: { Image(systemName: "testtube.2")
}
}
}
}
struct SimpleView: View {
let state: TestAttributes.ContentState
let stuff: TestAttributes
var body: some View {
VStack {
Text(state.news)
Text(stuff.name)
}
}
}
и вот оно! ...
///Here it is!
struct TestWidgBundle: WidgetBundle {
var body: some Widget {
TestWidg()
}
}
// end of file
Возможно, эта информация поможет людям, гуглящим здесь. Я действительно не понимаю, как «сделать это в коде», но в качестве обходного пути:
в проекте Xcode просто нажмите «Добавить цель -> Виджет», вам нужно выбрать как живую активность, так и намерение; позаботьтесь о том, чтобы встроить его в соответствующую цель, а не в цель по умолчанию.
Подсказка: похоже, что одна часть автоматизации примера Xcode не работает: просто в вашей основной цели вы добавили источники компиляции специально для исходного файла «NameLiveActivity.swift». Казалось бы, это единственный необходимый шаг.
(И вам придется вручную обновить CFBundleVersion в созданной вами новой цели.)
Если вы сделаете это, может показаться, что пример кода в вопросе, например, будет работать.
Я отметил этот ответ, потому что, похоже, никто не знает и не имеет больше фактов, чем этот! Казалось бы, opne может сделать это только «в Xcode», это невозможно «в коде».