Swift 3 首次发送后无法使用 Firebase 数据库的照片共享扩展
Swift 3 Photo Share Extension with Firebase Database Not Working After First Send
我正在 Swift 3 中开发一个 iOS 照片共享扩展程序,它可以在 iOS 照片应用程序中捕获 user-selected 照片以及 user-entered caption 并将其存储在 Firebase 中。照片存储在 Firebase 存储中。 Firebase 存储中照片的标题和路径存储在 Firebase 实时数据库中。
我遇到的问题是共享扩展在第一次发送后停止工作。奇怪的是,如果我在 iOS 应用程序的常规视图控制器中执行类似的方法,代码就可以工作。我注意到共享扩展有两个问题:
问题 #1:共享扩展视图没有完全关闭。在正常情况下,视图会 return 到照片的 "gallery" 模式。但是,共享扩展视图将消失,但包含可用于共享的完整应用程序列表的共享菜单不会关闭。
Screenshot of what the Photos view looks like after the second send
问题 #2:数据没有被发送到 Firebase 存储或 Firebase 数据库。
下面请找到我的 ShareViewController 代码:
import UIKit
import Social
import Firebase
import MobileCoreServices
class ShareViewController: SLComposeServiceViewController {
var ref: DatabaseReference!
var storageRef: StorageReference!
override func isContentValid() -> Bool {
// Do validation of contentText and/or NSExtensionContext attachments here
return true
}
override func didSelectPost() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
FirebaseApp.configure()
ref = Database.database().reference()
storageRef = Storage.storage().reference()
// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
if let item = self.extensionContext?.inputItems[0] as? NSExtensionItem {
for ele in item.attachments!{
let itemProvider = ele as! NSItemProvider
if itemProvider.hasItemConformingToTypeIdentifier("public.jpeg"){
itemProvider.loadItem(forTypeIdentifier: "public.jpeg", options: nil, completionHandler: { (item, error) in
do {
var imgData: Data!
if let url = item as? URL{
imgData = try Data(contentsOf: url)
}
if let img = item as? UIImage{
imgData = UIImagePNGRepresentation(img)
}
var updateRef = self.ref.child("demo_group").child("demo_patient").child("demo_updates").childByAutoId()
var updateStorageRef = self.storageRef.child("demo_photos" + "/\(Double(Date.timeIntervalSinceReferenceDate * 1000)).jpg")
updateRef.child("event_name").setValue(self.contentText)
updateRef.child("sender").setValue("demo_ff")
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
updateStorageRef.putData(imgData, metadata: metadata) { (metadata, error) in
if let error = error {
print("Error uploading: \(error)")
return
}
// use sendMessage to add imageURL to database
updateRef.child("photos").childByAutoId().setValue(metadata?.path)
}
} catch let err{
print(err)
}
})
}
}
}
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
override func configurationItems() -> [Any]! {
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
return []
}
}
如果我能做些什么来解决这个问题,请告诉我!我将不胜感激。
FirebaseApp.configure() 如果连续调用多次,您的扩展程序将崩溃,因为系统没有完全释放为扩展程序创建的 firebase 应用程序实例。
我的解决方案是:
if let _ = FirebaseApp.app() {...} else {
FirebaseApp.configure()
}
这应该可以解决您的问题。
编辑:另请注意,您应该在存储和数据库更新完成后调用 extensionContext.complete...而不是在
之前
因此,您将需要使用带有完成块的 setValue 方法。
1- 任务完成后上传到存储
2-更新数据库参考,
3-当调用完成块时...然后调用 extensionContext.completeWith() 或 .cancel()
我正在 Swift 3 中开发一个 iOS 照片共享扩展程序,它可以在 iOS 照片应用程序中捕获 user-selected 照片以及 user-entered caption 并将其存储在 Firebase 中。照片存储在 Firebase 存储中。 Firebase 存储中照片的标题和路径存储在 Firebase 实时数据库中。
我遇到的问题是共享扩展在第一次发送后停止工作。奇怪的是,如果我在 iOS 应用程序的常规视图控制器中执行类似的方法,代码就可以工作。我注意到共享扩展有两个问题:
问题 #1:共享扩展视图没有完全关闭。在正常情况下,视图会 return 到照片的 "gallery" 模式。但是,共享扩展视图将消失,但包含可用于共享的完整应用程序列表的共享菜单不会关闭。
Screenshot of what the Photos view looks like after the second send
问题 #2:数据没有被发送到 Firebase 存储或 Firebase 数据库。
下面请找到我的 ShareViewController 代码:
import UIKit
import Social
import Firebase
import MobileCoreServices
class ShareViewController: SLComposeServiceViewController {
var ref: DatabaseReference!
var storageRef: StorageReference!
override func isContentValid() -> Bool {
// Do validation of contentText and/or NSExtensionContext attachments here
return true
}
override func didSelectPost() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
FirebaseApp.configure()
ref = Database.database().reference()
storageRef = Storage.storage().reference()
// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
if let item = self.extensionContext?.inputItems[0] as? NSExtensionItem {
for ele in item.attachments!{
let itemProvider = ele as! NSItemProvider
if itemProvider.hasItemConformingToTypeIdentifier("public.jpeg"){
itemProvider.loadItem(forTypeIdentifier: "public.jpeg", options: nil, completionHandler: { (item, error) in
do {
var imgData: Data!
if let url = item as? URL{
imgData = try Data(contentsOf: url)
}
if let img = item as? UIImage{
imgData = UIImagePNGRepresentation(img)
}
var updateRef = self.ref.child("demo_group").child("demo_patient").child("demo_updates").childByAutoId()
var updateStorageRef = self.storageRef.child("demo_photos" + "/\(Double(Date.timeIntervalSinceReferenceDate * 1000)).jpg")
updateRef.child("event_name").setValue(self.contentText)
updateRef.child("sender").setValue("demo_ff")
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
updateStorageRef.putData(imgData, metadata: metadata) { (metadata, error) in
if let error = error {
print("Error uploading: \(error)")
return
}
// use sendMessage to add imageURL to database
updateRef.child("photos").childByAutoId().setValue(metadata?.path)
}
} catch let err{
print(err)
}
})
}
}
}
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
override func configurationItems() -> [Any]! {
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
return []
}
}
如果我能做些什么来解决这个问题,请告诉我!我将不胜感激。
FirebaseApp.configure() 如果连续调用多次,您的扩展程序将崩溃,因为系统没有完全释放为扩展程序创建的 firebase 应用程序实例。
我的解决方案是:
if let _ = FirebaseApp.app() {...} else {
FirebaseApp.configure()
}
这应该可以解决您的问题。
编辑:另请注意,您应该在存储和数据库更新完成后调用 extensionContext.complete...而不是在
之前因此,您将需要使用带有完成块的 setValue 方法。 1- 任务完成后上传到存储 2-更新数据库参考, 3-当调用完成块时...然后调用 extensionContext.completeWith() 或 .cancel()