Cant't upload file to Firebase. SwiftUI, imagePickerController Error code: 13000 - firebase

I want to upload a video file to Firebase storage.
This is my code:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let uid = Firebase.Auth.auth().currentUser?.uid else {return}
let ref = Storage.storage().reference(withPath: uid)
if let url = info[.mediaURL] as? URL {
ref.putFile(from: url, metadata: nil) { metadata, error in
if error != nil{
print(error)
return
}else{
print("Succes")
}
}
}
picker.dismiss(animated: true)
}
Im getting error:
Optional(Error Domain=FIRStorageErrorDomain Code=-13000 "An unknown
error occurred, please check the server response."
UserInfo={bucket=skidays-d2cc1.appspot.com,
_NSURLErrorFailingURLSessionTaskErrorKey=BackgroundUploadTask <75FCF919-3959-45EC-9C02-50824E91E9AA>.<1>,
object=jsZqif4oxSUCJHUA1YOlbbCctjh1,
_NSURLErrorRelatedURLSessionTaskErrorKey=(
"BackgroundUploadTask <75FCF919-3959-45EC-9C02-50824E91E9AA>.<1>" ), NSLocalizedDescription=An unknown error occurred, please check the
server response., ResponseErrorDomain=NSURLErrorDomain,
NSErrorFailingURLStringKey=https://firebasestorage.googleapis.com/v0/b/skidays-d2cc1.appspot.com/o/jsZqif4oxSUCJHUA1YOlbbCctjh1?uploadType=resumable&name=jsZqif4oxSUCJHUA1YOlbbCctjh1&upload_id=ADPycduSbMdqLIs3k9y0sfgwm0ut8V98dae0HJ5e1Vto_Yt9eWq7Hc_HqQsV-zFE_sX6YDMjG71JzJJyAESn0cGYrubuRQ&upload_protocol=resumable,
NSErrorFailingURLKey=https://firebasestorage.googleapis.com/v0/b/skidays-d2cc1.appspot.com/o/jsZqif4oxSUCJHUA1YOlbbCctjh1?uploadType=resumable&name=jsZqif4oxSUCJHUA1YOlbbCctjh1&upload_id=ADPycduSbMdqLIs3k9y0sfgwm0ut8V98dae0HJ5e1Vto_Yt9eWq7Hc_HqQsV-zFE_sX6YDMjG71JzJJyAESn0cGYrubuRQ&upload_protocol=resumable,
ResponseErrorCode=-1})

Related

Problem with WatchConnectivity transferFile (watch -> iphone)

I want to send a file created on the watch to the iOS companion-app, using WatchConnectivity and a setup WCSession, but it does not get through to the iPhone. When I use send a message containing a Dictionary in stead, the data does get to the iPhone.
Both AppDelegate and ExtensionDelegate uses NotificationCenter to communicate with ViewController and ExtensionController. They are left out for simplicity, but the notifications work fine.
iOS' AppDelegate.swift
extension AppDelegate: WCSessionDelegate {
// 1
func sessionDidBecomeInactive(_ session: WCSession) {
print("WC Session did become inactive")
}
// 2
func sessionDidDeactivate(_ session: WCSession) {
print("WC Session did deactivate")
WCSession.default.activate()
}
// 3
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
if let error = error {
print("WC Session activation failed with error: \(error.localizedDescription)")
return
}
print("WC Session activated with state: \(activationState.rawValue)")
}
func setupWatchConnectivity() {
// 1
if WCSession.isSupported() {
// 2
let session = WCSession.default
// 3
session.delegate = self
// 4
session.activate()
}
}
func session(_ session: WCSession, didFinish fileTransfer: WCSessionFileTransfer, error: Error?) {
print("didFinish fileTransfer")
}
func session(_ session: WCSession, didReceive file: WCSessionFile) {
print("didReceive file")
}
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: #escaping ([String : Any]) -> Void) { // 2
print("didReceiveMessage reached")
}
}
On the watch I have:
ExtensionDelegate.swift
extension ExtensionDelegate: WCSessionDelegate {
func setupWatchConnectivity() {
if WCSession.isSupported() {
let session = WCSession.default
session.delegate = self
session.activate()
}
}
func session(_ session: WCSession, activationDidCompleteWith
activationState: WCSessionActivationState, error: Error?) {
if let error = error {
print("WC Session activation failed with error: " +
"\(error.localizedDescription)")
return
}
print("WC Session activated with state: " +
"\(activationState.rawValue)")
}
func sendFileToPhone(_ notification:Notification) {
// 1
if WCSession.isSupported() && WCSession.default.isReachable {
// 2
if let fileURL = notification.object as? URL {
print("Sending file for URL: \(fileURL.absoluteURL.absoluteString)")
WCSession.default.transferFile(fileURL, metadata: nil) // <- if I use sendMessage here stuff works...
}
}
}
func session(_ session: WCSession, didFinish fileTransfer: WCSessionFileTransfer, error: Error?) {
// handle filed transfer completion
print("File transfer complete")
print("Outstanding file transfers: \(WCSession.default.outstandingFileTransfers)")
print("Has content pending: \(WCSession.default.hasContentPending)")
}
func session(_session: WCSession, didFinishFileTransfer fileTransfer: WCSessionFileTransfer, error: NSError?) {
print("error: ", error as Any)
}
}
After the file is sent from the Watch I inspect, as you see, outstandingFileTransfers and hasContentPending properties of the WCSession, and they indicate that the file should have been transferred, but my :didReceive: method of my AppDelegate extension doesn't get called. Again, when I use sendMessage, the AppDelegate's :didReceiveMessage: is invoked as expected.
What am I missing?
Note: I've tried to run this Apple's demo project that features the different communication methods, and I experience the same thing: transferFile does not trigger anything on counterpart.
It seems to be a bug of iOS 13/watchOS 6 simulator. I've tried to change Xcode simulators to iOS 12 and watchOS 5, how it's suggested in this thread and the issue disappeared.

Decode Cloud Firestore data result item to NSObject

I've a cloud firebase result item:
let mpUserRef = db?.collection(MPUser.PROPERTY_DB)
.whereField(MPUser.PROPERTY_FIREBASE_USER_ID, isEqualTo: firebaseUSer.uid)
.limit(to: 1).getDocuments() { (document, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in document!.documents {
let mpUser = fromJsonToMpUser( userJson: "\(document.data())" )
if mpUser != nil{
delegate.mpUser = mpUser
}
}
}
}
And i want to decode result item in my business Object calling the method:
class func fromJsonToMpUser( userJson: String ) -> MPUser?{
let decoder = JSONDecoder()
do{
let json = userJson.data(using: .utf8)!
let mpUser = try decoder.decode(MPUser.self, from: json)
return mpUser
}catch{
print("Errore while ecode Club")
return nil
}
}
But this does not work, the error message that i have is:
"The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Badly formed array around character 17." UserInfo={NSDebugDescription=Badly formed array around character 17.}))).
So, how can i converte cloud firestore item result in valid Json?
I've resolved my question using CodableFirebase library ( https://github.com/alickbass/CodableFirebase created by #alickbass )

Swift 4 Load 3D Models from Firebase

I'm trying to get a 3D Model which is stored in Firebase into my iOS Application.
Right now I stored the default Object (ship.scn) into my Firebase Storage.
How can I convert the Data, which I get from Firebase, to a SCNNode?
This is my Code right now:
let storage = Storage.storage().reference()
let modelPath = storage.child("models/ship.scn")
print("ModelPath: \(modelPath)")
modelPath.getMetadata { (metaData, error) in
if error != nil {
print("ERROR: ", error!)
}else{
print("Metadata: \(metaData!)")
}
}
// this is what firebase shows for images
// how can i get the Data as SCNNode?
modelPath.getData(maxSize: 1 * 1024 * 1024) { (data, error) in
if error != nil {
print("Error getData: \(error!)")
}else {
print(data)
}
}
I solved this problem by downloading the 3D Object from firebase into the devices document folder.
So when I need the 3D-object I create a reference to the downloaded 3D-Object
write To Directory: (where modelPath is the storage.child('your path') in firebase)
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let tempDirectory = URL.init(fileURLWithPath: paths, isDirectory: true)
let targetUrl = tempDirectory.appendingPathComponent("ship.scn")
modelPath.write(toFile: targetUrl) { (url, error) in
if error != nil {
print("ERROR: \(error!)")
}else{
print("modelPath.write OKAY")
}
}
load 3D file from directory:
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let tempDirectory = URL.init(fileURLWithPath: paths, isDirectory: true)
let targetUrl = tempDirectory.appendingPathComponent("\ship.scn")
var sceneForNode: SCNScene? = nil
do {
// load the 3D-Model node from directory path
sceneForNode = try SCNScene(url: targetUrl, options: nil)
}catch{
print(error)
}
// create node to display on scene
let node: SCNNode? = sceneForNode?.rootNode.childNode(withName: "ship", recursively: true)

Realm in Swift3.0 unexpected status code: -34018

run this code
SyncUser.authenticate(with: Credential.usernamePassword(username: username, password: password, actions: [.useExistingAccount]), server: Constants.syncAuthURL) { (user, error) in }
return -34018 error code
libc++abi.dylib: terminating with uncaught exception of type realm::keychain::KeychainAccessException: Keychain returned unexpected status code: -34018
breakpoint in
_dispatch_once(dispatch_once_t *predicate,
DISPATCH_NOESCAPE dispatch_block_t block){
if (DISPATCH_EXPECT(*predicate, ~0l) != ~0l) {
dispatch_once(predicate, block);
} else {
dispatch_compiler_barrier();
}
DISPATCH_COMPILER_CAN_ASSUME(*predicate == ~0l);}
THX
-34018 means errSecMissingEntitlement. Try to specify an entitlements file, even if it contains no entitlements, can work around this problem.
See more at: https://github.com/realm/realm-cocoa/issues/4158

Downloading image on Swift 2 form Firebase Storage

Whenever I download an image from Firebase Storage it download's perfectly, but once I try to change the imageview "my" to it, the imageview disappears. I don't have constraints and I navigated to the local URL and found the image perfectly there. Any help? Am I doing something wrong?
func loadImages(){
let documentDirectoryURL = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
let newRef = storageRef!.child("Images/0.jpg")
let fileDestinationUrl = documentDirectoryURL.URLByAppendingPathComponent("p.jpg")
let downloadTask = newRef.writeToFile(fileDestinationUrl){ (URL, error) -> Void in
if (error != nil) {
print("problem")
} else {
print("done")
}
}
downloadTask.observeStatus(.Success) { (snapshot) -> Void in
print(fileDestinationUrl)
var temp = String(fileDestinationUrl)
print(temp)
var my = UIImage(contentsOfFile: temp)
self.image.image = my
}
}
Print the destinationUrl in your console .Go to your downloaded file location , open your terminal , drag and drop the DOWNLOADED image in the terminal and the terminal will give you its actual path.Now compare both the path the one that terminal gave you and the one that console gave you, match those. most like they are to be different ,change them accordingly.
Example code :-
Uploading Code : -
func profilePictureUploading(infoOnThePicture : [String : AnyObject],completionBlock : (()->Void)) {
if let referenceUrl = infoOnThePicture[UIImagePickerControllerReferenceURL] {
print(referenceUrl)
let assets = PHAsset.fetchAssetsWithALAssetURLs([referenceUrl as! NSURL], options: nil)
print(assets)
let asset = assets.firstObject
print(asset)
asset?.requestContentEditingInputWithOptions(nil, completionHandler: { (ContentEditingInput, infoOfThePicture) in
let imageFile = ContentEditingInput?.fullSizeImageURL
print("imagefile : \(imageFile)")
let filePath = FIRAuth.auth()!.currentUser!.uid + "/\(Int(NSDate.timeIntervalSinceReferenceDate() * 1000))/\(imageFile!.lastPathComponent!)"
print("filePath : \(filePath)")
FIRControllerClass.storageRef.child("ProfilePictures").child(filePath).putFile(imageFile!, metadata: nil, completion: { (metadata, error) in
if error != nil{
print("error in uploading image : \(error)")
}
else{
print("metadata in : \(metadata!)")
print(metadata?.downloadURL())
print("The pic has been uploaded")
print("download url : \(metadata?.downloadURL())")
self.uploadSuccess(metadata!, storagePath: filePath)
completionBlock()
}
})
})
}else{
print("No reference URL found!")
}
}
Downloading code : -
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
print("paths in user home page : \(paths)")
let documentDirectory = paths[0]
print("documents directory in homePage : \(documentDirectory)")
let filePath = "file:\(documentDirectory)/\(user!.uid).jpg"
var filePath2 : String = filePath
print(filePath)
let storagePath = NSUserDefaults.standardUserDefaults().objectForKey("storagePath") as! String
print("storagePath is : \(storagePath)")
storageRef.child("ProfilePictures").child(storagePath).writeToFile(NSURL.init(string: filePath)! , completion :
{ (url, err) -> Void in
if let error = err{
print("error while downloading your image :\(error)")
}else{
print("Download successful !")
print("the file filePath of the downloaded file : \(filePath)")
filePath2 = "\(documentDirectory)/\(self.user!.uid).jpg"
if let downloadedImage = UIImage(contentsOfFile: filePath2){
self.profilePictureImageView.image = downloadedImage
print("displayed")
}else{
print("unable to display")
}
}
})
where storagePath is something that you stored in your NSUserDefaults for later reference , such as this, while uploading your image to your firebase storage
The codeBlocks that i gave you are just one of many solutions, there are plenty of ways to do this, go to https://firebase.google.com/docs/storage/ios/download-files

Resources