Виджет iOS 14 работает локально, но не работает через TestFlightIOS

Программируем под IOS
Ответить
Anonymous
 Виджет iOS 14 работает локально, но не работает через TestFlight

Сообщение Anonymous »

У меня есть приложение SwiftUI с виджетом. Когда я запускаю приложение через Xcode (прямо на своем устройстве или в симуляторе), виджет работает точно так, как ожидалось.
Однако, когда я запускаю приложение через TestFlight, виджет появляется, но не отображает никаких данных — это просто пустой заполнитель. Виджет должен отображать изображение и текст, но он не отображает ни того, ни другого.
Я видел несколько сообщений на форумах разработчиков Apple о подобных проблемах. В одном из принятых ответов говорится следующее:
  • Убедитесь, что вы используете Xcode 12 beta 4 и iOS 14 beta 4 на своих устройствах. Убедитесь, что у вас реализован заполнитель (in:). Убедитесь, что у вас нет заполнителя (с:), потому что это то, что предлагалось в предыдущей бета-версии Xcode с автозаполнением, и без этого заполнитель не заработает. Я думаю, что вся эта проблема вызвана переименованием методов WidgetKit, но это уже другая история.
  • В соответствии с примечаниями к выпуску вам необходимо установить для параметра «Dead Code Stripping» значение NO в целевом расширении. настройки сборки. Это необходимо только для цели расширения.
  • При загрузке архива в App Store Connect снимите флажок «Включить биткод для контента iOS».
  • Удалите старую сборку с устройства при установке новой бета-версии.
Я выполнил эти предложения, но безрезультатно.
Вот мой код виджета. Сначала он извлекает игровые данные через CloudKit, а затем создает временную шкалу:

Код: Выделить всё

import WidgetKit
import SwiftUI
import CloudKit

struct WidgetCloudKit {
static var gameLevel: Int = 0
static var gameScore: String = ""
}

struct Provider: TimelineProvider {
private var container = CKContainer(identifier: "MyIdentifier")
static var hasFetchedGameStatus: Bool = false

func placeholder(in context: Context) -> SimpleEntry {
return SimpleEntry(date: Date(), gameLevel: 0, gameScore: "0")
}

func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry: SimpleEntry

if context.isPreview && !Provider.hasFetchedGameStatus {
entry = SimpleEntry(date: Date(), gameLevel: 0, gameScore: "0")
} else {
entry = SimpleEntry(date: Date(), gameLevel: WidgetCloudKit.gameLevel, gameScore: WidgetCloudKit.gameScore)
}
completion(entry)
}

func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) {
let pred = NSPredicate(value: true)
let sort = NSSortDescriptor(key: "creationDate", ascending: false)
let q = CKQuery(recordType: "gameData", predicate: pred)
q.sortDescriptors = [sort]

let operation = CKQueryOperation(query: q)
operation.desiredKeys = ["level", "score"]
operation.resultsLimit = 1

operation.recordFetchedBlock = { record in
DispatchQueue.main.async {
WidgetCloudKit.gameLevel = record.value(forKey: "level") as? Int ?? 0
WidgetCloudKit.gameScore = String(record.value(forKey: "score") as? Int ?? 0)
Provider.hasFetchedGameStatus = true

var entries: [SimpleEntry] = []
let date = Date()

let entry = SimpleEntry(date: date, gameLevel: WidgetCloudKit.gameLevel, gameScore: WidgetCloudKit.gameScore)
entries.append(entry)

// Create a date that's 15 minutes in the future.
let nextUpdateDate = Calendar.current.date(byAdding: .minute, value: 15, to: date)!
let timeline = Timeline(entries: entries, policy: .after(nextUpdateDate))
completion(timeline)
}
}

operation.queryCompletionBlock = { (cursor, error) in
DispatchQueue.main.async {
if let error = error {
print("queryCompletion error: \(error)")
} else {
if let cursor = cursor {
print("cursor: \(cursor)")
}
}
}
}

self.container.publicCloudDatabase.add(operation)
}

}

struct SimpleEntry: TimelineEntry {
var date: Date
var gameLevel: Int
var gameScore: String
}

struct WidgetEntryView : View {
var entry: Provider.Entry

var body: some View {
GeometryReader { geo in
VStack {
Image("widgetImage")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geo.size.width)
HStack {
VStack {
Text("LEVEL")
Text(entry.gameLevel == 0 ? "-" : "\(entry.gameLevel)")
}
VStack {
Text("SCORE")
Text(entry.gameScore == "0" ? "-"  : entry.gameScore)
}
}
}
}
}
}

@main
struct Widget: SwiftUI.Widget {
let kind: String = "MyWidget"

var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
WidgetEntryView(entry: entry)
}
.configurationDisplayName("Game Status")
.description("Shows an overview of your game status")
.supportedFamilies([.systemSmall])
}
}
Вопрос: Почему мой виджет не работает при распространении через TestFlight? Какие у меня есть варианты?
Спасибо!
Обновление:
Если я использую неотредактированные () виджет, виджет показывает изображение и текст «УРОВЕНЬ» и «ОЦЕНКА», но по-прежнему не отображает никаких фактических данных. Итак, мое представление SwiftUI теперь выглядит так:

Код: Выделить всё

struct WidgetEntryView : View {
var entry: Provider.Entry

var body: some View {
GeometryReader { geo in
VStack {
Image("widgetImage")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geo.size.width)
HStack {
VStack {
Text("LEVEL")
Text(entry.gameLevel == 0 ? "-" : "\(entry.gameLevel)")
}
VStack {
Text("SCORE")
Text(entry.gameScore == "0" ? "-" : entry.gameScore)
}
}
}
.unredacted() // 

Подробнее здесь: [url]https://stackoverflow.com/questions/67482411/ios-14-widget-works-locally-but-fails-via-testflight[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»