在新的 Swift 5.5 中使用 async/await 并发机制时如何返回主线程?我应该只用@MainActor 标记函数、类吗?我还能用吗DispatchQueue.main.async
?会是正确的吗?因为新机制不使用 GCD 并且异步任务和线程之间没有像以前那样的映射?
例如我正在使用List
SwiftUIrefreshable
List { }
.refreshable {
viewModel.fetchData()
}
Run Code Online (Sandbox Code Playgroud)
这个可以吗
List { }
.refreshable {
DispatchQueue.main.async {
viewModel.fetchData()
}
}
Run Code Online (Sandbox Code Playgroud)
或者我需要在 ViewModel 类上添加 @MainActor ?我在项目中没有使用 async/await,因此仅使用 MainActor 来实现这个单一的可刷新似乎是多余的,我也不知道添加此类属性如何影响 ViewModel 类的其余方法和属性,他们现在使用合并。
但另一方面 Xcode 显示
运行时:SwiftUI:不允许从后台线程发布更改;确保在模型更新时从主线程发布值(通过像 receive(on:) 这样的运算符)。
此外,在将 @MainActor 添加到 ViewModel 后,我收到多个这样的警告
与全局参与者“MainActor”隔离的属性“标题”无法满足协议“OnlineBankingListViewModelProtocol”的相应要求
我收到这样的通知
读取 Sqlite 数据库时出错:无法对数据库 (id=3) 执行操作。数据库可能已经关闭。
在 Android Studio 模拟器中调试我的应用程序时,如果我快速更改数据库检查器的进程,那么应用程序在模拟器上运行正常,否则它会立即断开连接并崩溃。
我有3个活动:主要,登录,向导.
对于每个Activity,我都有单独的导航图和片段目的地.
主导航图还具有登录活动目的地,以便在注销时启动登录屏幕.
从Action.MAIN启动器意图启动时,应用程序似乎正常工作.
但是在使用Deep Link时遇到问题.我想将URI添加到Login Nav Graph(更改密码片段).此导航图使用单独的NavHostFragment.我用过2种方法.
START DESTINATION
(登录片段目的地).这里也退回按钮不能正常工作,即完成应用程序而不是返回主导航图主要目的地.Login Activity Destination
in Main Nav Graph
和again,这里Back按钮确实正常工作,我按预期登陆Login Fragment Destination.但在这里我想手动导航到更改密码片段目的地,我遇到另一个问题,即Intent Action.View与Uri数据不会传递到此登录活动目的地.它仅传递给主要活动,主要活动主持人.总结一下.我认为由活动目的地连接的多个导航图之间的深层链接行为不能正常工作.我不知道是否有任何解决方案.
我能以某种方式从NavController检索Deep Link Arguments(Uri数据)吗?或者唯一的解决方案是从getIntent().data获取它?在这里,正如我所说,这个Intent不会转发到最终目标Activity,而只会转移到创建的Activities堆栈中的第一个Activity.
现在我回到手动处理没有Android导航架构的Deep Links,因为如果有比单个Nav Graph更复杂的导航结构,单个Activity并且只有内部Fragment导航,它似乎毫无用处.
在 SwiftUI 中有这个功能,我可以将标签分配给 View
func tag<V>(_ tag: V) -> some View where V : Hashable
Run Code Online (Sandbox Code Playgroud)
有没有可能像这样访问这个标签
MenuItem().tag(1)
Run Code Online (Sandbox Code Playgroud)
然后在 MenuItem 中我有一些 Button(action: ..., label: ...) 并且想要访问 Button 的标签
self.tag
Run Code Online (Sandbox Code Playgroud)
我知道我可以像这样传递给 MenuItem(tag: Int) 但考虑我是否可以实现类似于 TabView 中每个 tabItem 都分配有 tag() 的东西。它如何使用它?
我想设置我的文本视图的样式,使其显示的字符串对于 2 个单词中的每个单词具有不同的颜色。我知道我只能使用 2 x 不同风格的文本。但是我应该将这个字符串词保存在单独的状态变量中。但是我考虑是否可以为字符串的不同部分定义不同的 .font().foregroundColor() 。
在某些情况下,前导更长,我们只希望第一个句子或第一个单词加粗,其余文本使用常规字体。
知道如何在 SwiftUI 中实现这一点吗?
我不知道为什么,但我的代码在这个 $searchTerm 发布者上崩溃了。我的代码中有很多这样的发布者,其他一切正常。它只在这个新的 Xcode 版本中不起作用,而在以前的版本中起作用。如果我评论了这一行并用 _searchTerm.projectedValue 替换它,它就会像往常一样开始工作!
_searchTerm.projectedValue
//$searchTerm
.debounce(for: .milliseconds(350), scheduler: DispatchQueue.global())
.flatMap { term in
self.search(by: term)
}
.print("searching")
.receive(on: DispatchQueue.main)
.assign(to: \.results, on: self)
.store(in: &disposables)
Run Code Online (Sandbox Code Playgroud)
我有错误
致命错误:调用已删除的方法
我有代码应该使用流将 SharedPreferences 更改为可观察的存储,所以我有这样的代码
internal val onKeyValueChange: Flow<String> = channelFlow {
val callback = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
coroutineScope.launch {
//send(key)
offer(key)
}
}
sharedPreferences.registerOnSharedPreferenceChangeListener(callback)
awaitClose {
sharedPreferences.unregisterOnSharedPreferenceChangeListener(callback)
}
}
Run Code Online (Sandbox Code Playgroud)
或这个
internal val onKeyValueChange: Flow<String> = callbackFlow {
val callback = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
coroutineScope.launch {
send(key)
//offer(key)
}
}
sharedPreferences.registerOnSharedPreferenceChangeListener(callback)
awaitClose {
sharedPreferences.unregisterOnSharedPreferenceChangeListener(callback)
}
}
Run Code Online (Sandbox Code Playgroud)
然后我观察令牌、userId、companyId 的这个偏好,然后登录,但有一点很奇怪,因为我需要构建应用程序三次,比如更改令牌不会导致 tokenFlow 发出任何东西,然后第二次新的 userId 不会导致 userIdFlow 发出任何东西,然后在第三次登录后,我可以注销/登录并且它可以工作。注销时,我正在清除 prefs 令牌、userId、companyId 中的所有 3 个属性存储。
我花了大约一天(可能多一点)试图按照它在macOS启动(用户登录)启动的顺序将我的应用程序添加到Login Item.
所以按照这个步骤,我做了:
在项目设置>功能中,我将App Sandbox切换为ON.
我的Launcher应用程序中的代码看起来像这样(我以前甚至使用Swift来做同样的事情)
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
NSArray *pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents];
pathComponents = [pathComponents subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)];
NSString *path = [NSString pathWithComponents:pathComponents];
[[NSWorkspace sharedWorkspace] launchApplication:path];
[NSApp terminate:nil];
}
Run Code Online (Sandbox Code Playgroud)最后,我在主应用程序中有魔术代码,以启用应用程序作为登录项
Run Code Online (Sandbox Code Playgroud)if(!SMLoginItemSetEnabled("click.remotely.Remotely-Click-Server-Launcher" as CFString, Bool(checkboxButton.state as NSNumber) ) ) { let alert: NSAlert = NSAlert() alert.messageText = "Remotely.Click Server - Error"; …
你好我有一个关于阿拉伯语格式的问题我应该如何正确格式化这个字符串,似乎我无法管理这个:
????? %1$s…
?? ????? ???????. %1$d/%2$d!
Run Code Online (Sandbox Code Playgroud)
这是在崇高的文本2中 - 但我认为存在从左到右的顺序
编辑:在Eclipse中,从Sublime Text复制的内容变得有些混乱.我聘请了一些人从英语翻译成阿拉伯语strings.xml.他使用了Word编辑器,但在处理eclipse时事情变得混乱了,我建议在Sublime Text中改变它,我认为它会像在Eclipse中一样正确地支持它并且是更轻的编辑器.我看到在Sublime Text中似乎是从左到右的顺序,这也是错误的.
*当我使用这个混乱的特殊字符运行应用程序时,它似乎正确运行.我是否怀疑某些交际词是否也没有搞砸,例如:已经下载了第5/10项.将是已下载的项目.5/10或类似的东西.*
需要一种首选方法来获取某人英文写的strings.xml,将其翻译,然后复制到/ values-ar并正常工作?
我已经在应用程序中实现了 Google Pay 并提出了 paymentData 请求我使用 AutoResolveHelper 来显示底部表格,然后通过 onActivityResult 获取结果。我是从 Fragment 而不是 Activity 发出这个请求。所以我正在传递这样的父活动。
paymentsClient?.loadPaymentData(gpayViewModel.paymentDataRequest)?.let { task ->
AutoResolveHelper.resolveTask(task, requireActivity(), LOAD_PAYMENT_DATA_REQUEST_CODE)
}
Run Code Online (Sandbox Code Playgroud)
问题是这个 AutoResolveHelper 不是在 Fragment 上调用 onActivityResult,而是只在 Activity 上调用。
我读过这样的东西:
如果您从片段中调用 startActivityForResult(),那么您应该调用 startActivityForResult(),而不是 getActivity().startActivityForResult(),因为它会导致片段 onActivityResult()。
所以它建议当 AutoResolveHelper 在传递的活动上调用 startActivityForResult() 时,片段的 onActivityResult 将永远不会被调用。
所以现在我唯一的选择是在 Activity 中实现 onActivityResult 并以某种方式将控制权从这个 Activity 传递给我的孩子 Fragment 但这需要一些样板代码,因为我的 Fragment 是可重用的,所以这个解决方案并不完美。
同时,我发现这段代码以正确的方式 startActivityForResult 并且比 Fragment 的 onActivityResult 被正确调用:
val intent = Intent(activity, CardIOActivity::class.java)
intent.putExtra(CardIOActivity.EXTRA_REQUIRE_EXPIRY, true)
intent.putExtra(CardIOActivity.EXTRA_REQUIRE_CVV, true)
intent.putExtra(CardIOActivity.EXTRA_REQUIRE_CARDHOLDER_NAME, true)
startActivityForResult(intent, CARD_IO_REQUEST_CODE)
Run Code Online (Sandbox Code Playgroud)
那么我可以以某种方式替换这个 AutoResolveHelper.resolveTask() 来执行这个任务,这样就不需要 onActivityResult 或者我可以自己 startActivityForResult …
swift ×5
android ×4
swiftui ×2
arabic ×1
async-await ×1
cocoa ×1
deep-linking ×1
formatted ×1
google-pay ×1
kotlin ×1
kotlin-flow ×1
macos ×1
macos-sierra ×1
objective-c ×1
resources ×1
string ×1
xcode ×1
xcode11.4 ×1