WIP Add SwiftUI Quickstart for Storage#1134
WIP Add SwiftUI Quickstart for Storage#1134codeblooded wants to merge 1 commit intofirebase:mainfrom
Conversation
ac7f271 to
d818aa3
Compare
paulb777
left a comment
There was a problem hiding this comment.
Great progress!
Just a few structure comments for now. I'll review the code later.
storage/Podfile
Outdated
|
|
||
| use_frameworks! | ||
| platform :ios, '10.0' | ||
| platform :ios, '14.4' |
There was a problem hiding this comment.
Is 13.0 or 14.0 possible?
Also, please factor the platform spec into the targets so we can keep 10.0 for the old quickstart.
| @@ -11,6 +11,8 @@ | |||
| 1073487D20333C27004A66D1 /* StorageExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1073487C20333C27004A66D1 /* StorageExampleUITests.m */; }; | |||
There was a problem hiding this comment.
Run pod deintegrate before merging to keep the Xcode project more easily mergeable and able to support Swift PM.
| @@ -0,0 +1,77 @@ | |||
| // | |||
There was a problem hiding this comment.
I know this repo isn't consistent with this, but please use the standard Firebase open source copyright like https://github.com/firebase/firebase-ios-sdk/blob/master/FirebaseStorageSwift/Sources/SwiftAPIExtension.swift#L1
There was a problem hiding this comment.
Awesome job– this is great! 🥳
Some additional suggestions/tips:
- add the
Image.xcassetsto the new app’s target so the new app picks up the standard qs icon - use SFSymbols when possible
- check out Apple's Human Interface Guidelines (if you'd like more design inspo, Im happy to share some apps I refer to for their design)
- provide a screenshot of the latest UI to the PR (I should have done this when I helped make some qs 😅 )
I helped implement qs for Auth, Remote Config, and Analytics last summer. They are in UIKit but could be helpful in with design, etc. I tried to make use of the Firebase APIs clear and copy-and-paste-able by simplifying and abstracting the other stuff away.
Some examples of areas where I tried to make Firebase API usage really clear:
• AuthViewController
• ConfigViewController
All that to say, I think the usage of Firebase APIs is really clear here. I just think this is the ultimate goal for all the qs!
Sorry, there’s a lot of comments but my hope is that they are helpful. Again, great job so far!! Feel free to ping me if you have questions/want me to try and demo one/etc
p.s. i cloned your fork to have a look around. feel free branch off of the main repo if that is any easier for you 🙂
| Auth.auth().signInAnonymously(completion: { (authResult, error) in | ||
| if let error = error { | ||
| print("Failed to sign in: \(error.localizedDescription)") | ||
| } | ||
| }) |
There was a problem hiding this comment.
Optional refactor: use a trailing closure
Auth.auth().signInAnonymously { authResult, error in
if let error = error {
print("Failed to sign in: \(error.localizedDescription)")
}
}| struct StorageExampleSwiftUIApp: App { | ||
| init() { | ||
| FirebaseApp.configure() | ||
| if Auth.auth().currentUser == nil { |
There was a problem hiding this comment.
Not suggesting a change, just making a note here.
This might be a good example to one day update with an Auth+Combine solution. Like instead of having this logic here, subscribing to an auth publisher and handing the app's evolving login states in some coordinator object that subscribes to the auth publisher.
Does this sound like a good use case for the Auth+Combine work that's underway? @peterfriese
| }() | ||
|
|
||
| public init(withStorage storage: Storage) { | ||
| self.storage = storage |
There was a problem hiding this comment.
nit: I think Swift's design guidelines prefer to avoid having init methods that form a phrase. From here
So instead, something like:
public init(storage: Storage) { ... }| } | ||
|
|
||
| func downloadImage() { | ||
| UserDefaults.standard.synchronize() |
There was a problem hiding this comment.
I think synchronize() might not need to get called at all these days. See here
There was a problem hiding this comment.
Interesting. I will fix that.
| guard let imagePath = UserDefaults.standard.string(forKey: self.photoStore.imagePathKey) else { return } | ||
| self.photoStore.downloadImage(atPath: imagePath) |
There was a problem hiding this comment.
optional refactor:
if let imagePath = UserDefaults.standard.string(forKey: self.photoStore.imagePathKey) {
self.photoStore.downloadImage(atPath: imagePath)
}Suggesting because it looks like we only do one thing after the guard statement and the style script might make line 69 look odd if it truncates it for being over the maximum char length
| if self.source == .camera { | ||
| imagePicker.sourceType = .camera | ||
| imagePicker.cameraCaptureMode = .photo | ||
| } else { | ||
| imagePicker.sourceType = .photoLibrary | ||
| } |
There was a problem hiding this comment.
optional: Since source is an enum, could do a switch case here
| } | ||
| } | ||
|
|
||
| extension ImagePickerRepresentable.Coordinator: UIImagePickerControllerDelegate { |
There was a problem hiding this comment.
If you haven't considered it, check out PHPickerViewController as well. There's a cool WWDC 2020 video where I learned about it
There was a problem hiding this comment.
ive read a few cool articles about it. like this this one
There was a problem hiding this comment.
Hey @ncooke3, I really wanted to use it too haha. I started with the PHPickerViewController. I got it working but I found two issues:
-
PHPickerViewController does not provide any access to the camera yet, so I was forced to also incorporate UIImagePickerController or get a camera manually.
-
There is a bug I found when using search in the PHPickerViewController and SwiftUI on an actual device. On my iPhone 12 Pro Max, the picker view process crashes whenever using the search bar. The rest of the controller behaves as usual. I opened feedback with Apple to address it.
There was a problem hiding this comment.
I didnt know that but that's good to know! 👍
| .navigationTitle("Firebase Storage") | ||
| .toolbar { | ||
| ToolbarItemGroup(placement: .bottomBar) { | ||
| if !showUploadMenu { |
There was a problem hiding this comment.
nit: maybe refactor so it's:
if showUploadMenu {
// ...
} else {
// !showUploadMenu related logic
}| Button("❌") { | ||
| showUploadMenu = false | ||
| } |
There was a problem hiding this comment.
You can use sfsymbols in conjunction with the Button API to make some really clean looking buttons
Button(action: {
showUploadMenu = false
}, label: {
Image(systemName: "xmark.circle.fill")
})There was a problem hiding this comment.
There was a problem hiding this comment.
@ncooke3 Absolutely. This was a temporary fix for the selector. I was hoping to incorporate something a little more exciting and maybe some animation here.
| import SwiftUI | ||
| import Firebase | ||
|
|
||
| struct ImagePickerRepresentable { |
There was a problem hiding this comment.
nice job with what you have going on this file. 👏 hopefully Apple provides us with a standard PhotoPicker view that saves us from having to do all of this 🤞
There was a problem hiding this comment.
Thank you. Maybe there will be something announced in June. It really seems like SwiftUI was a second class citizen for the new photo APIs, so I expect them to fix that.
d818aa3 to
b3a1d88
Compare
b3a1d88 to
e05a887
Compare

This is an incomplete migration of the Storage Quickstart to Swift UI. It is an active work in-progress.
To Do