When I try to run a Firebase Function from Swift, I get an error saying:
Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
This is the Firebase Function:
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!")
})
This is my Swift code:
Functions.functions().httpsCallable("helloWorld").call { (result, error) in
if error == nil {
print("Success: \(result?.data)")
} else {
print(error.debugDescription)
}
}
You may see this error if you haven't specified the correct region on the client side. For example:
lazy var functions = Functions.functions(region: "europe-west1")
My issue was that I used http://localhost:5000 instead of the correct http://localhost:5001. The emulator by default emulates the hosted website at port 5000 and the functions at port 5001.
I realized this by evaluating the response in FIRFunctions.m#261. It was the html of the hosted website which obviously cannot be parsed as json.
response.send("Hello from Firebase!")
You are not returning a JSON TEXT here but you are returning a string.
You need to return something like
response.send('{"message": "Hello from Firebase!"}')
Related
I am trying to do an API request to the backend using alamofire and responseDecodable.
AF.request(Router.registerFacebookUser(facebookToken: token)).validate().responseDecodable(of: UserConfig.self) { result in
switch result.result {
case let .success(userConfig):
onAuthentication(userConfig)
case let .failure(error):
print(error)
//somehow get the message from ERROR JSON and pass it here
onFailure(error.localizedDescription)
}
}
When call succeeds, it successfully parses JSON to the model. However, there as some special cases, when it should fail. For example if user is already registered, I get a response JSON:
{
"error":{
"message":"User already exist"
}
}
Is it possible to override the AF error that we receive? Or maybe it's possible to parse another object if request fails? Or are there other ways how I can access the error message?
There are several ways to approach this in Alamofire.
In the validate() method that takes a closure, parse the error body and produce a .failure result with a custom associated error:
.validate { request, response, data
// Check request or response state, parse data into a custom Error type.
return .failure(MyCustomErrorType.case(parsedError))
}
Then, in your response handler, you'll need to cast to your custom error type from the AFError's underlyingError property:
.responseDecodable(of: SomeType.self) { response in
switch response.result {
case let .success(value): // Do something.
case let .failure(error):
let customError = error.underlyingError as? MyCustomErrorType
// Do something with the error, like extracting the associated value.
}
Use a Decodable container type to parse your responses as either the type you expect or your error representation. You should be able to find examples elsewhere, but on Alamofire's side it would work like this:
.responseDecodable(of: ContainerType<SomeType>.self) { response in
// Do something with response.
}
Write a custom ResponseSerializer type that checks the response and parses the error type when a failure is detected, otherwise parsing the expected type. We have examples in our documentation.
Of these options I usually go with the wrapper type unless I'm already using my own custom Error type, in which case the validator is fairly easy. A custom serializer is the most work but gives you the most flexibility as well, especially if you need to customize other aspects of your response handling.
I have the following code where I want to check for the type of error instance.
if let error = error {
// error is Error
if error is CMErrorMotionActivityNotAuthorized {
}
}
It is giving me error that CMErrorMotionActivityNotAuthorized is not a type. How can I check that if the error is of type CMErrorMotionActivityNotAuthorized
Try this:
if error as? CMError == CMErrorMotionActivityNotAuthorized {
// handle the error
}
You can either try this
But CMErrorMotionActivityNotAuthorized means that the app is not currently authorized to use motion activity support.
Required:
var CMErrorMotionActivityNotAuthorized: CMError { get }
To learn more on this you can check iOS - is Motion Activity Enabled in Settings > Privacy > Motion Activity on Stackoverflow , here is the link
I am using the Kentico-cloud Swift SDK to grab a bunch of elements from the CMS using the Delivery API in the background.
One of the Swift SDK methods allows me to get a ContentType for a certain element on the CMS so I can then map it to an object in my code. Here's the code:
self.client.getContentType(name: codename, completionHandler: { (isSuccess, contentType, error) in
guard error == nil else {
print(error!)
return
}
if isSuccess {
if let type = contentType {
print(type)
self.client.getItem(modelType: type, itemName: codename, completionHandler: { (isSuccess, deliveryItem, error) in
if isSuccess {
// save this Element
print(deliveryItem)
} else {
if let error = error {
print(error)
}
}
})
}
}
})
the attribute codename is the name of the object I am trying to find the ContentType for. The call succeeds and I get my ContentType object, unfortunately, it does not have any properties in it that aren't nil.
I assume it should give me the name of the type as a String so I can then map it to my class.
Could you verify you have valid content type codename in the name parameter? I've tried to reproduce it (see attached screenshot) and everything works on my side (there is also test for this feature which passes as well in GetContentType.swift).
Could you post the value of a requestUrl property from DeliveryClient.swift getContentType() method line 176?
Edit: Oh, from your screen on the GitHub issue I can see you are trying to get the content type with the codename of the item which in wrong. You should use the codename of the content type.
From the docs for getContentType() method:
/**
Gets single content type from Delivery service.
- Parameter name: The codename of a specific content type.
- Parameter completionHandler: A handler which is called after completetion.
- Parameter isSuccess: Result of the action.
- Parameter contentTypes: Received content type response.
- Parameter error: Potential error.
*/
You can learn more about content types here.
I also had the same thought usps tracking but thanks that you have provided a question.
Thanks and Regards,
Shane.
I am trying to implement the same code in https://www.andrewcbancroft.com/2015/06/17/creating-calendars-with-event-kit-and-swift/, but I get an error stating "json error: An unexpected error occurred." I am developing this project for macOS.
This is my following code,
#IBAction func addPressed(_ sender: NSButton) {
// Create an Event Store instance
let eventStore = EKEventStore();
// Use Event Store to create a new calendar instance
// Configure its title
let newCalendar = EKCalendar(for: .event, eventStore: eventStore)
// Probably want to prevent someone from saving a calendar
// if they don't type in a name...
newCalendar.title = "DCU"
// Access list of available sources from the Event Store
let sourcesInEventStore = eventStore.sources
// Filter the available sources and select the "Local" source to assign to the new calendar's
// source property
newCalendar.source = sourcesInEventStore.filter{
(source: EKSource) -> Bool in
source.sourceType.rawValue == EKSourceType.local.rawValue
}.first!
// Save the calendar using the Event Store instance
do {
try eventStore.saveCalendar(newCalendar, commit: true)
} catch {
print("json error: \(error.localizedDescription)")
}
}
When I build the project and click run it gives me the error "json error: An unexpected error occurred.". When I try to add an event to defaultcalendar it gives me an error "json error: No calendar was set". I have tried all the available sources online but couldn't find a solution. Somehow neither eventStore.save or eventStore.saveCalendar is working for me. Can someone please let me know where might I be going wrong?
Two possible reasons
From the documentation of EKEventStore
To access the user’s Calendar data, all sandboxed macOS apps must include the com.apple.security.personal-information.calendars entitlement. To learn more about entitlements related to App Sandbox, see Enabling App Sandbox.
Check the authorizationStatus of the store and call requestAccess if necessary.
Your error message is misleading, the error has nothing to do with JSON.
I'm trying to connect an iOS project, coded in Swift, to an instance of a Watson Assistant that I've already created. The issue is, I can't get past a "Contextual Closure type" error in compiling.
I'm relatively new to Swift and I have yet to come across a solution.
The error arises in the block of code provided by IBM themselves (here's the link: https://console.bluemix.net/docs/swift/machine_learning/conversation.html#before-you-begin). The one thing I could find was that this is likely a result of the update to Swift 4. Below is the function that's producing the error; more specifically, it's the "response in" statement, after the third comment.
func assistantExample() {
// Assistant credentials
let username = "shawn.soneja85#gmail.com"
let password = "Shawn8135!"
let workspace = "199b1f99-b28c-4b3f-b610-5933328141d5"
// instantiate service
let assistant = Assistant(username: username, password: password, version: "2018-03-01")
// start a conversation
assistant.message(workspaceID: workspace) { response in
print("Conversation ID: \(response.context.conversationID!)")
print("Response: \(response.output.text.joined())")
// continue assistant
print("Request: turn the radio on")
let input = InputData(text: "turn the radio on")
let request = MessageRequest(input: input, context: response.context)
assistant.message(workspaceID: workspace, request: request) { response in
print("Response: \(response.output.text.joined())")
}
}
}
Here's the error itself:
Contextual closure type '(RestResponse?, WatsonError?) -> Void' (aka '(Optional>, Optional) -> ()') expects 2 arguments, but 1 was used in closure body
Update:
I've tried replacing "response" with "(response, error)", but that leads to the following error messages:
Value of type 'RestResponse?' has no member 'context'
Value of type 'RestResponse?' has no member 'output'
And with "(error, response)", it leads to the following error:
Value of type 'WatsonError?' (aka 'Optional') has no member 'output'
Value of type 'WatsonError?' (aka 'Optional') has no member 'context'
Here is documentation on .message function:
first screenshot
second screenshot
Thanks in advance for the help!
RestResponse contains a result of the .message call in a field called result. So to access the output or context, use response.result.output and response.result.context.
It would be helpful if you gave more description like:
Swift version you are using to compile your target
Line number of the error
That being said, I think your problem is in the nested .message method, i've copied your code above but deleted some lines to try and make it clear (at least what I am proposing), you may have added the second parameter to the callback in the first call to .message but had forgotten to do so in the second (nested) call, the one where you pass in the request. So you might have added the second, error parameter in the first call but got the same exact error message for a missing parameter because you forgot to do the same thing for the nested call. I hope this helps :)
// start a conversation
assistant.message(workspaceID: workspace) { response, error in
let input = InputData(text: "turn the radio on")
let request = MessageRequest(input: input, context: response.context)
assistant.message(workspaceID: workspace, request: request) { response, error in
print("Response: \(response.output.text.joined())")
}
}