在下面的代码中,观察到的对象被更新,但观察它的视图没有更新。知道为什么吗?
代码在屏幕上显示 10 个数字 (0..<10) 和一个按钮。每当按下按钮时,它会随机选择 10 个数字之一并翻转其可见性(可见?隐藏,反之亦然)。
打印语句显示按钮正在更新数字,但视图不会相应更新。我知道更新数组中的值不会改变数组值本身,所以我使用手册objectWillChange.send()调用。我原以为应该触发更新,但屏幕永远不会改变。
任何的想法?我对NumberLine用作类或结构的解决方案感兴趣,或者根本不使用NumberLine类型,而只是在ContentView结构中使用数组变量。
这是代码:
import SwiftUI
struct ContentView: View {
@ObservedObject var numberLine = NumberLine()
var body: some View {
VStack {
HStack {
ForEach(0 ..< numberLine.visible.count) { number in
if self.numberLine.visible[number] {
Text(String(number)).font(.title).padding(5)
}
}
}.padding()
Button(action: {
let index = Int.random(in: 0 ..< self.numberLine.visible.count)
self.numberLine.objectWillChange.send()
self.numberLine.visible[index].toggle()
print("\(index) now \(self.numberLine.visible[index] ? "shown" : "hidden")")
}) {
Text("Change")
}.padding()
}
}
}
class NumberLine: ObservableObject …Run Code Online (Sandbox Code Playgroud) 对于某些字体,内置行距过大令人不快。
SwiftUI 为我们提供了调整文本行间距的Text修饰符.lineSpacing()(也称为引导,与引导/拖尾无关)。它的值指定放置在连续文本行之间的额外间距的点数,因此不会.lineSpacing(0)产生任何变化。不幸的是,它似乎对负值没有反应;.lineSpacing(-10)产生与 相同的结果lineSpacing(0)。
有没有人知道一种在不使用 UIKit 的情况下减少 SwiftUI 中行间距的方法?
我需要录制我的应用程序的视频以用于应用程序商店中的预览。对我来说,展示实际的应用程序音频至关重要(因为它是针对音乐家的交互式教育应用程序)。
\nXcode Simulator 12.5 有一个很棒的新功能,可以轻松录制视频\xe2\x80\xa6\xc2\xa0,但录制的视频不包含声音。
\n有谁知道用应用程序声音录制应用程序视频演示的好方法?
\n(使用 QuickTime 和实际的 iPhone/iPad\xe2\x80\xa6 很容易做到,但这只是一个解决方案,如果您碰巧有一组与每个所需的应用程序预览分辨率匹配的设备\xe2\x80\ xa6,我不知道。)
\n更新:我尝试单独录制音频,认为我总是可以将其与 Final Cut/Premiere 等中的视频合并。为此,我安装了BlackHole;我的计划是使用 QuickTime Player 来录制音频,选择 BlackHole 作为音频源。不幸的是,BlackHole 似乎不包括 Simulator 的音频输出。
\n在 SwiftUI 中,Pickerof 样式SegmentedPickerStyle占据其封闭视图的整个宽度。我怎样才能让它只占据它需要的宽度?
struct ContentView: View {
@State var value = 1
var body: some View {
Picker("Value", selection: $value) {
Text("One").tag(1)
Text("Two").tag(2)
}
.pickerStyle(SegmentedPickerStyle())
.padding()
}
}
Run Code Online (Sandbox Code Playgroud)
如何从两个选择器选择中删除较大的边距,使选择器仅达到所需的宽度?这似乎是一个非常基本的问题,但我却找不到答案。
SwiftUI 具有出色的动画功能,但它处理TextView 内容更改的方式存在问题。它对文本框的变化进行动画处理,但在没有动画的情况下立即更改文本。因此,当TextView的内容变长时,动画过渡会导致省略号 (...) 出现,直到文本框达到其全宽。例如,在这个小应用程序中,按下Toggle按钮在较短和较长的文本之间切换:
这是代码:
import SwiftUI
struct ContentView: View {
@State var shortString = true
var body: some View {
VStack {
Text(shortString ? "This is short." : "This is considerably longer.").font(.title)
.animation(.easeInOut(duration:1.0))
Button(action: {self.shortString.toggle()}) {
Text("Toggle").padding()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Run Code Online (Sandbox Code Playgroud)
问题是:如何避免省略号?将一个字符串动画化为两个字符串时,情况更糟,因为短字符串在动画化为较长字符串时完全被省略号替换。
例如,一种可能性是通过添加修饰符,.id(self.shortString ? 0 : 1)然后添加修饰符,为处于一种或另一种状态的视图分配一个单独的 id .transition()。这会将文本视为两个不同的视图,之前和之后。不幸的是,在我的情况下,我需要在更改期间移动文本位置,而不同的 id 使动画变得不可能。
我想解决方案是创造性地使用AnimatableData. …
我希望能够测试哪些文本转语音可供我的 iOS 应用程序与 AVSpeechSynthesis 一起使用。生成已安装声音的列表很容易,但 Apple 将其中一些设置为禁止应用程序使用,我想知道哪些。
例如,考虑以下测试代码 (swift 5.1):
import AVFoundation
...
func voiceTest() {
let speechSynthesizer = AVSpeechSynthesizer()
let voices = AVSpeechSynthesisVoice.speechVoices()
for voice in voices where voice.language == "en-US" {
print("\(voice.language) - \(voice.name) - \(voice.quality.rawValue) [\(voice.identifier)]")
let phrase = "The voice you're now listening to is the one called \(voice.name)."
let utterance = AVSpeechUtterance(string: phrase)
utterance.voice = voice
speechSynthesizer.speak(utterance)
}
}
Run Code Online (Sandbox Code Playgroud)
当我打电话时voiceTest(),控制台输出是这样的:
en-US - Nicky (Enhanced) - 2 [com.apple.ttsbundle.siri_female_en-US_premium]
en-US - Aaron - 1 [com.apple.ttsbundle.siri_male_en-US_compact] …Run Code Online (Sandbox Code Playgroud) 是否可以在 iOS 应用程序中自动加载新的语音合成语音?多种高质量的“增强”声音可供下载Settings > Accessibility > Spoken Content > Voices > English。我想使用其中一种高质量的应用程序,但不想向应用程序用户解释他们必须通过深入“设置”导航来手动下载它们。
Siri 声音似乎是我手机上预装的唯一高质量声音,不幸的是 Apple 不允许我们在 AVSpeech\xe2\x80\x8bSynthesizer 中使用这些声音。(选择其中之一作为 AVSpeechSynthesisVoice\xe2\x80\x94 例如
\n\nlet utterance = AVSpeechUtterance(string: "This is a test.")\nutterance.voice = AVSpeechSynthesisVoice(identifier: "com.apple.ttsbundle.siri_female_en-US_premium")\nspeechSynthesizer.speak(utterance)\nRun Code Online (Sandbox Code Playgroud)\n\n没有影响;而是使用质量较低的默认语音。)
\n我想将 SwiftUI 中的 ObservableObject 行为扩展到嵌套类,我正在寻找正确的方法来做到这一点。它可以使用Combine“手动”完成,但我想使用SwiftUI有一种更简洁的方法,我希望你能指出我正确的方向。这就是我的意思……
下面是 ObservableObject 的一个典型应用,它使 View 动态响应引用类型的变化。点击按钮切换showText值,使文本在屏幕上出现/消失:
import SwiftUI
class MyClass: ObservableObject {
@Published var showText = false
}
struct ContentView: View {
@ObservedObject var instance = MyClass()
var body: some View {
VStack(spacing: 10) {
Button(action: {
print(self.instance.showText)
self.instance.showText.toggle()
}) {
Text("BUTTON").bold().padding()
.foregroundColor(.white)
.background(Color.red)
}
if instance.showText {
Text("Hello, World!")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这工作正常。
但是下面的修改呢,其中包含的类showText是 an InnerClass,它本身包含在 an 中OuterClass?按钮切换showText得很好,但值更改的通知不再通过OuterClass实例传播到视图,因此视图根本不再显示文本。
import SwiftUI
class OuterClass: ObservableObject …Run Code Online (Sandbox Code Playgroud) 我的应用程序通常运行很多代码,我想在预览中跳过它们。代码耗时且没有可见效果(例如初始化音频设备)。我正在尝试弄清楚如何跳过它进行预览。
\n\n有一种简单的方法可以使用 DEBUG 宏仅在应用程序的生产版本中运行代码。但我不知道非预览版有什么类似的东西(因为预览版可能会构建与非预览版相同的代码)。
\n\n我认为previewMode在我的 ViewModel 中设置一个变量 是可行的。这样我就可以只在 PreviewProvider 中将其设置为 true:
struct MainView_Previews: PreviewProvider {\n\n static var previews: some View {\n let vm = ViewModel(previewMode: true)\n return MainView(viewModel: vm)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n当我在 SceneDelegate 中创建 ViewModel 时,我可以设置previewMode为false:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {\n\n let vm = ViewModel(previewMode: false)\n let mainView = MainView(viewModel: vm)\n\n // Use a UIHostingController as window root view controller.\n if let windowScene = …Run Code Online (Sandbox Code Playgroud) 我想在同一项目上识别TapGesture和。LongPressGesture它工作正常,但有以下例外: the LongPressGesturealone 在我指定的持续时间后响应,即 0.25 秒,但是当我将它与 结合使用时TapGesture,至少需要 1 秒\xe2\x80\x94我找不到使其响应更快的方法。这是一个演示:
这是它的代码:
\nstruct ContentView: View {\n @State var message = ""\n\n var body: some View {\n Circle()\n .fill(Color.yellow)\n .frame(width: 150, height: 150)\n .onTapGesture(count: 1) {\n message = "TAP"\n }\n .onLongPressGesture(minimumDuration: 0.25) {\n message = "LONG\\nPRESS"\n }\n .overlay(Text(message)\n .font(.title).bold()\n .multilineTextAlignment(.center)\n .allowsHitTesting(false))\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n请注意,除了长按的持续时间(远长于 0.25 秒)之外,它工作正常。
\n有任何想法吗?提前致谢!
\n