Why can't my app find Firebase Functions? - swift

I can't figure out why I keep getting the Swift warning: Use of unresolved identifier 'Functions on this line of my code: let functions = Functions.functions()
My imports for the viewController includes import Firebase and it works fine when I declare let db = Firestore.firestore() right above the line let functions = Functions.functions()
My podfile includes pod 'Firebase/Functions' and I've installed the pod.
I'm calling functions later using the following code and when I type "functions" it recommends adding .httpsCallable which leads me to believe that it actually does recognize the object "functions":
func getData(){
functions.httpsCallable("helloWorld").call(userData) { (result, error) in
if let error = error {
print(error)
}
if let data = result?.data {
print(data)
}
}
}

Figured it out. Importing Firebase is not enough, one must also import FirebaseFunctions (despite what Swift thinks, see screenshot below).

Related

Swift CLI app 'main' attribute cannot be used in a module that contains top-level code

I am trying to call functions from EventKit in a simple command line tool app. However, some of the functions are async, which results in 'async' call in a function that does not support concurrency. I found this SO question but neither of the given solutions work.
Putting code inside Task {} never runs, and declaring a struct with a static func main() async function wont compile with the error 'main' attribute cannot be used in a module that contains top-level code. I am trying to run a single file test.swift with the following content.
import Foundation
import EventKit
#main
struct Test {
static func main() async {
var reminders = EKEventStore.init()
print("run")
if EKEventStore.authorizationStatus(for: EKEntityType.reminder) != EKAuthorizationStatus.authorized {
do {
var ok = try await reminders.requestAccess(to: EKEntityType.reminder)
print(ok)
} catch {
print("error")
return
}
}
print("authroized")
}
}
At least for me, I had this issue when using #main in main.swift. I renamed main.swift to some random name and the error went away.
This is a bug in Swift. Running with -parse-as-library as an argument for the compiler makes it work.

Cannot pass arguments via swift function

This problem came up trying to run macOS commands within a swift file. I'm having some issues passing arguments into functions using Swift. When I run the lines within the function date outside of the function definition, things work just fine. I'm not able to see any errors within Xcode. As a Swift newbie, any advise is appreciated!
import Foundation
import Cocoa
//Command arguments
let dateLocation = "/bin/date"
let format = "+DATE: %Y-%m-%d%nTIME: %H:%M:%S"
let command = Process()
//Command function with arguments
func date(args: String) -> String {
command.executableURL = URL(fileURLWithPath: dateLocation)
command.arguments = [args]
try command.run()
}
//Run function
date(args: format)
First of all your function is declared to return a string but doesn't return anything and secondly you are calling a function that can throw an error which you correctly handles by using try but you need to either handle any possible error or throw it from your function. Here I chosed the later in my example by adding throws to the declaration
func date(args: String) throws {
command.executableURL = URL(fileURLWithPath: dateLocation)
command.arguments = [args]
try command.run()
}
Now you can call your function and catch any error like below
do {
try date(args: format)
} catch {
print(error)
}
Output:
DATE: 2020-03-31
TIME: 18:50:25

How to save custom objects to Firestore?

Hello Everyone I have a quick question. I'm trying to save a custom model to Firestore like so:
import Firebase
let city = City(name: "Los Angeles",
state: "CA",
country: "USA",
isCapital: false,
population: 5000000)
do {
try db.collection("cities").document("LA").setData(from: city)
} catch let error {
print("Error writing city to Firestore: \(error)")
}
The issue is .setData(from: city) is not working? Its saying Extraneous argument label 'from:' and when I do I get an error. Did Firestore deprecate this or do I have to import something else?
Thank you
The documentation isn't exactly wrong on this, it' just incomplete in one section. Firebase added an extension to make crafting custom obects easier but didn't mention that extension in the documentation. (I assume its an extension)
The documentation on Custom Objects is an example of the code that needs the extension
Simple fix by adding this to your podfile
pod 'FirebaseFirestoreSwift'
and then do a pod update either in terminal or cocoapods.
Then in your Class just update the imports to include that
import Cocoa
import FirebaseCore
import FirebaseFirestore
import FirebaseFirestoreSwift
For reference the code in the docs was this
try db.collection("cities").document("LA").setData(from: city)
and this
let docRef = db.collection("cities").document("LA")
docRef.getDocument { (document, error) in
let result = Result {
try document.flatMap {
try $0.data(as: City.self)
}
}
and this line
.data(as: City.self)
and
.setData(from:
were the 'troublemakers' that needed the FirebaseFirestoreSwift

IBM Watson Visual Recognition API Key fail - Xcode Swift

I'm trying to connect to Watson using VisualRecognitionV3.framework.
The framework's compiled fine (via Carthage), and I think I've got the Service Credentials configured correctly, but when I compile Xcode to the simulator I get an invalid-api-key error.
Has anyone experienced the same issues?
What am I doing wrong?
private let apiKey = "Xn5DUtQU8WzgFTL9qNEFwBjxxxxxxxxxxxxxxxxxx"
private let classifierId = "DefaultCustomModel_2051029379"
private let version = "2018-07-01"
var visualRecognition: VisualRecognition!
override func viewDidLoad() {
super.viewDidLoad()
self.visualRecognition = VisualRecognition(apiKey: apiKey, version: version)
}
override func viewDidAppear(_ animated: Bool) {
let localModels = try? visualRecognition.listLocalModels()
if let models = localModels, models.contains(self.classifierId) {
print("local model found")
} else {
self.updateModel()
}
}
Xcode Error:
Error Domain=com.ibm.watson.developer-cloud.VisualRecognitionV3 Code=403 "ERROR: invalid-api-key" UserInfo={NSLocalizedDescription=ERROR: invalid-api-key}
Watson configuration screenshot:
Watson Config
You need to initialize your VisualRecognition using another initializer, like the following
let visualRecognition = VisualRecognition(version: version, apiKey: apiKey, iamUrl: nil)
The difference is that you will need to call this 3 argument-ed constructor with the third argument, i.e. the iamUrl, even though you make it nil and anything else is the same. This tells the VisualRecognition class to authenticate your app using the IAM.
The git documentation is very confusing, which says in here https://github.com/watson-developer-cloud/swift-sdk#visual-recognition
Note: a different initializer is used for authentication with instances created before May 23, 2018:
Which means the old way should just work, UNLESS, they made a mistake and they actually mean AFTER May 23, 2018
Anyways, if you try it should just work. I was having this issue 30 mins before writing this answer.

Code runs fine on Playground; at the same time it yields an EXC_I386_GPFLT error

I'm having this curious issue in which a Playground prints the expected result but at the same time I see an error telling me the execution was stopped because of an EXC_I386_GPFLT error.
I'm using a Playground to model how should an API wrapper I'm writing be used. The idea of doing this is to plan a nice API for future developers.
The following is the entire "planning" code I have written to plan out my wrapper. Feel free to copy and paste it on a Playground to see the problem in action:
class Anilist {
init() {}
internal class UserAPIs {
weak var parent: Anilist? = nil
init(parent: Anilist) {
self.parent = parent
}
}
lazy var user: UserAPIs = { [unowned self] in
let userapi = UserAPIs(parent: self)
return userapi
}()
}
extension Anilist.UserAPIs {
func me(_ completionHandler: (results: [String]) -> Void ) {
// Do some logic, fetching stuff from parent
completionHandler(results: ["Lorem", "Sammet"])
}
}
let andy = Anilist()
andy.user.me { results in
print(results)
}
Curiously, it prints ["Lorem", "Sammet"] properly, but at the same time I get that error.
I have read (for C++) a few other questions regarding this error but unfortunately I haven't been able to solve this issue. For what I can gather is this is happening because I'm attempting to access memory that is nil? In general, I haven't been able to find much information regarding this other than it being an architecture protection.
While the code runs fine, I'm hesitant about putting this on my actual code yet, as I have no idea how it would behave. Even if it works on the first run, it's hard to predict if it will produce errors in the long run.
EDIT:
It looks like it has something to do with the calculated lazy var. Changing that line to this:
lazy var user: UserAPIs = UserAPIs(parent: self)
Works as expected (as in, it prints the array and doesn't give me the EXC_I386_GPFLT error).
EDIT 2:
Previous edit seems to be inaccurate information.
This isn't an answer really but a workaround till I figure out why this works:
let andy = Anilist()
let someVar = andy.user.me { results in
print(results)
}
This gives a compile time warning saying constant someVar inferred to have type (), which maybe unexpected.
But doing this:
let andy = Anilist()
let _ = andy.user.me { results
print(results)
}
works fine WITHOUT any errors at all. Weird enough. It'd be really good if someone could explain why this happens.