我知道发布者通常比闭包更强大,但是我想询问并讨论一个具体的例子:
func getNotificationSettingsPublisher() -> AnyPublisher<UNNotificationSettings, Never> {
let notificationSettingsFuture = Future<UNNotificationSettings, Never> { (promise) in
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
promise(.success(settings))
}
}
return notificationSettingsFuture.eraseToAnyPublisher()
}
Run Code Online (Sandbox Code Playgroud)
我认为这是 Future 发布者的一个有效示例,可以在这里使用它而不是使用完成处理程序。让我们用它做点什么:
func test() {
getNotificationSettingsPublisher().sink { (notificationSettings) in
// Do something here
}
}
Run Code Online (Sandbox Code Playgroud)
这有效,但是它会告诉我 sink ( AnyCancellable)的结果未使用。因此,每当我尝试获取一个值时,我都需要存储可取消对象或分配它,直到我获得一个值。
是否有类似 sinkOnce 或可取消项的自动销毁之类的东西?有时我不需要取消的任务。但是我可以这样做:
func test() {
self.cancellable = getNotificationSettingsPublisher().sink { [weak self] (notificationSettings) in
self?.cancellable?.cancel()
self?.cancellable = nil
}
}
Run Code Online (Sandbox Code Playgroud)
所以一旦我收到一个值,我就会取消订阅。(我猜我可以在水槽的完成关闭中做同样的事情)。
这样做的正确方法是什么?因为如果我使用一个闭包,它会被调用多少次函数被调用,如果它只被调用一次,那么我不需要取消任何东西。
你会说普通的完成处理程序可以用组合代替吗?如果是这样,你会如何处理接收一个值然后取消?
最后但并非最不重要的是,调用完成,我还需要取消订阅吗?我至少需要更新可取消并将其设置为 nil 对吗?我假设将订阅存储在一个集合中是为了长期运行的订阅,但是单值订阅呢?
谢谢
我创建了一个简单的UIImageView,具有以下约束:
self.view.addConstraint(imageView.topAnchor.constraint(equalTo: contentLayoutGuide.topAnchor))
self.view.addConstraint(imageView.centerXAnchor.constraint(equalTo: contentLayoutGuide.centerXAnchor))
self.view.addConstraint(imageView.heightAnchor.constraint(equalTo: contentLayoutGuide.heightAnchor))
self.view.addConstraint(imageView.widthAnchor.constraint(equalTo: contentLayoutGuide.heightAnchor))
Run Code Online (Sandbox Code Playgroud)
重要的一个是最后一个,它将宽度设置为等于图像视图的高度,图像视图的高度由顶部和底部锚定义.
但是,当设置imageView.image图像时,整个屏幕都太大了.此调试过程修复了它:
po for cn in self.imageView!.constraints { cn.isActive = false }
po CATransaction.flush()
Run Code Online (Sandbox Code Playgroud)
这使得图像适合imageView内部,但直到此时,imageView才搞砸了.
有趣的是,在设置图像之前,imageView本身没有任何约束,然后设置图像会创建这两个:
- 0 : <NSContentSizeLayoutConstraint:0x6040002b2120 UIImageView:0x7fa98f757b90.width == 488 Hug:250 CompressionResistance:750 (active)>
- 1 : <NSContentSizeLayoutConstraint:0x6040002b2180 UIImageView:0x7fa98f757b90.height == 487 Hug:250 CompressionResistance:750 (active)>
Run Code Online (Sandbox Code Playgroud)
这些限制似乎打破了它,因为禁用它们可以解决问题.它们仅在设置图像时添加
我正在更新我现有的 UIKit 以在某些部分使用 SwiftUI,我觉得能够用 SwiftUI 替换所有部分。它是一个选项卡应用程序,因此有 3 个选项卡,其中一个是设置,我将用 SwiftUI 替换它。我的标签栏被配置为只显示图像而不显示标题(我需要帮助的问题也会在显示标签时发生)。现在在 UIKit 中我这样做:
private let settingsViewController: UIViewController = UIHostingController<SettingsView>(SettingsView())
稍后在显示之前:
settingsViewController.navigationItem.title = "Settings".
然而,从那时起,SwiftUI 开始使用它的视图修饰符: .navigationBarTitle("Text"),我将其用于嵌套视图控制器(通过 推送NavigationLink),因为 UIKit 无法访问这些视图来设置标题。然而,问题是,无论何时.navigationBarTitle使用(与title在 UIKit 中设置视图的属性相同,它都会设置当前选项卡栏项的标题。对于 UIKit,总是有一种方法可以设置navigationItem.title而不是title.
有什么方法可以在 SwiftUI 中设置导航栏标题而不是标签栏标题本身?
谢谢
我正在使用这个问题的稍微更新的代码:下载 iCloud 文件的方法?非常混淆?
这是代码的摘录:
private func downloadUbiquitiousItem(atURL url: URL) -> Void {
do {
try FileManager.default.startDownloadingUbiquitousItem(at: url)
do {
let attributes = try url.resourceValues(forKeys: [URLResourceKey.ubiquitousItemDownloadingStatusKey])
if let status: URLUbiquitousItemDownloadingStatus = attributes.allValues[URLResourceKey.ubiquitousItemDownloadingStatusKey] as? URLUbiquitousItemDownloadingStatus {
if status == URLUbiquitousItemDownloadingStatus.current {
self.processDocument(withURL: url)
return
} else if status == URLUbiquitousItemDownloadingStatus.downloaded {
self.processDocument(withURL: url)
return
} else if status == URLUbiquitousItemDownloadingStatus.notDownloaded {
do {
//will go just fine, if it is unnecessary to download again
try FileManager.default.startDownloadingUbiquitousItem(at: url)
} catch {
return …Run Code Online (Sandbox Code Playgroud) 我正在关注此文档:管理会话Cookies
我的app.js看起来基本上是这样的:单击按钮即可在客户端登录用户。
(function() {
// Initialize Firebase
var config = {
//...
};
firebase.initializeApp(config);
// no local persistence because of the httpOnly flag
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.NONE);
const emailField = document.getElementById("email");
const passwordField = document.getElementById("password");
const loginButton = document.getElementById("loginButton");
loginButton.addEventListener("click", e => {
const email = emailField.value;
const password = passwordField.value;
const signInPromise = firebase.auth().signInWithEmailAndPassword(email, password);
signInPromise.catch(e => {
console.log("Login Error: " + e.message);
})
return signInPromise.then(() => {
console.log("Signed in + " + firebase.auth().currentUser.uid);
return firebase.auth().currentUser.getIdToken().then(idToken => {
// Session login …Run Code Online (Sandbox Code Playgroud) cookies firebase firebase-authentication google-cloud-functions firebase-admin
我正在实施动态链接并且一切正常,除了在我的项目设置中我更改了“团队 ID”又名“AppStore 应用程序前缀”。
如果我访问myproject.page.link/apple-app-site-association它,它仍然给我旧的团队 ID,我担心在应用程序发布时可能会破坏动态链接。
更新需要时间吗?或者有没有办法让我强制刷新值?
谢谢你。
我通过控制台和我的客户端(iOS 应用程序)创建了一个用户,我要求用户在使用之前验证他们的电子邮件。但是测试用户没有有效的电子邮件(它不存在)。电子邮件是testing@project-name.com。
有什么办法可以将帐户设置为“已验证的电子邮件”?我在控制台中没有找到任何东西,是否可以在用户上设置此状态(可能在 onCreate auth 触发器中?)?
谢谢
我有一个简单的UITableViewCell子类,其中有一个 titleLabel 属性(单元格有更多视图,但为了显示问题,我只会做一个标签,因为它也会中断)。
这是我的标签代码:
self.titleLabel = UILabel(frame: .zero)
self.titleLabel.numberOfLines = 0
self.titleLabel.font = UIFont.preferredFont(forTextStyle: .headline)
self.titleLabel.textColor = UIColor.white
self.titleLabel.adjustsFontSizeToFitWidth = false
self.titleLabel.textAlignment = .left
self.titleLabel.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(self.titleLabel)
self.titleLabel.topAnchor.constraint(equalTo: self.artworkImageView.topAnchor).isActive = true
self.titleLabel.leftAnchor.constraint(equalTo: self.artworkImageView.rightAnchor, constant: 10.0).isActive = true
self.titleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -10.0).isActive = true
self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor).isActive = true
Run Code Online (Sandbox Code Playgroud)
我也是这样设置的UITableView:
self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.estimatedRowHeight = 50.0
Run Code Online (Sandbox Code Playgroud)
然而,它不断打破约束,并出现如下错误:
"<NSLayoutConstraint:0x28211ce10 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x10859a4f0.height == 4.33333 (active)>"
Run Code Online (Sandbox Code Playgroud)
还有更多的限制,但是这个说我的单元格内容视图只有 4.3 的高度,但是我希望它随着标签的增长而增长。
我还尝试设置 contentHuggingPriorities 和底部锚点的优先级。我还将它与我在网上看到的在线代码或 IB 约束进行了比较,它们都设置了 4 个约束:顶部、左侧、底部、右侧。我也尝试过领先和尾随而不是左右 - 结果相同。
任何帮助表示赞赏
这是我的完整 …
我想在 VStack 之外使用 ScrollView,这样当 VStack 扩展超出屏幕尺寸时我的内容就可以滚动。现在我想GeometryReader在 VStack 中使用,它会导致问题,我只能通过设置 GeometryReader 框架来解决,考虑到我使用阅读器来定义视图大小,这并没有真正帮助我。
这是没有 ScrollView 的代码,它工作得很好:
struct MyExampleView: View {
var body: some View {
VStack {
Text("Top Label")
.background(Color.red)
GeometryReader { reader in
Text("Custom Sized Label")
.frame(width: reader.size.width, height: reader.size.width * 0.5)
.background(Color.green)
}
Text("Bottom Label")
.background(Color.blue)
}
.background(Color.yellow)
}
}
Run Code Online (Sandbox Code Playgroud)
这会产生以下图像:
自定义尺寸的标签应为全宽,但高度为宽度的一半。现在,如果我将相同的代码包装在 ScrollView 中,就会发生这种情况:
不仅所有东西都变小了,而且自定义尺寸标签的高度也被忽略了。如果我设置 GeometryReader 的高度,我可以调整该行为,但我希望 GeometryReader 的大小与其内容一样大。我怎样才能实现这个目标?
谢谢
我知道Firebase最近添加了对推送通知的支持,虽然这是一件好事,但我似乎只能通过通知面板手动发送推送通知.
我想做的是在用户范围内发送推送通知......让我解释一下.我的应用程序中的每个用户都有一个帐户,然后每个用户都可以加入一个组.在该组中,用户可以执行任务并具有要做的事务列表.现在,当某些任务到期时,我想提醒用户使用推送通知执行此操作.对于1-10我可以手动关闭它,但有没有办法动态地根据数据库中的数据发送推送通知?
我知道可以使用分析工具创建某些推送通知,例如"嘿,你有3天没有访问过,请回来"......但是我想注册推送通知,例如"我刚刚创建了一个任务,这项任务需要在3天内完成.如果任务仍未完成,请在3天内提醒我".
Firebase是否可以实现这一点,还是需要将自己的服务器连接到Firebase并处理这些事件?
-xCoder
swift ×5
firebase ×4
ios ×2
swiftui ×2
autolayout ×1
combine ×1
cookies ×1
icloud ×1
uiimageview ×1
uikit ×1