I am facing issue on debug as well as release mode,
Xcode 10.2.1
macOS Mojave 10.14 .5
swift5.09
Fatal error: Binding error to behavior relay: objectDeleted: file /Users/webwerks/Desktop/Monster/iOS/monstar_mukesh/project_name/Pods/RxCocoa/RxCocoa/Common/Observable+Bind.swift, line 90
2019-07-04 15:42:33.074374+0530 target_name[2731:1953909] Fatal error: Binding error to behavior relay: objectDeleted: file
Note
There was not any issue & crash on existing code on macOS High Sierra 10.13.6 , Xcode 10.1 (swift4.2)
What I suspect is, there is issue in the following code,
private func logoutAction() -> CocoaAction {
return CocoaAction { [weak self] in
guard let `self` = self else { return .empty() }
let subject = PublishSubject<Void>()
func changeRootView() {
let authScene = AuthScene.signin(coordinator: self.sceneCoordinator)
self.sceneCoordinator.transition(to: authScene, type: .root(animationType: .present))
.asObservable()
.mapTo(())
.bind(to: subject)
.disposed(by: self.disposeBag)
}
self.logoutRequestAction.execute(())
.subscribe { changeRootView() }
.disposed(by: self.disposeBag)
subject
.subscribe{
APITokenManager.shared.removeToken()
RealmDBManager.shared.deleteAllData()
OneSignalManager.shared.unsubscribe()
}
.disposed(by: self.disposeBag)
return subject
}
}
Culprit was PublishSubject object. I was deleting the all realm data by calling RealmDBManager.shared.deleteAllData() before executing the AuthScene.signin call.
What I did is,
subject
.subscribe( onNext: { _ in
APITokenManager.shared.removeToken()
RealmDBManager.shared.deleteAllData()
OneSignalManager.shared.unsubscribe()
})
.disposed(by: self.disposeBag)
It works like champ.
Related
I am adding siri Shortcuts to my existing app. There are three shortcuts, one to start the app with a specific value, one to increase the value by an amount and one to decrease the value by an amount. The shortcut code, for the start the app is attached here:
//
// StartMeetingIntentHandler.swift
//
import Intents
import SwiftUI
class StartMeetingIntentHandler: NSObject, StartMeetingIntentHandling {
#ObservedObject var meeting = Meeting()
func handle(intent: StartMeetingIntent, completion: #escaping (StartMeetingIntentResponse) -> Void) {
if let attendees = intent.attendees {
meeting.meetingStarted()
meeting.addAttendee(numberToAdd: Int(truncating: attendees))
completion(StartMeetingIntentResponse.success(result: attendees))
} else {
print("failure")
}
}
func resolveAttendees(for intent: StartMeetingIntent, with completion: #escaping (StartMeetingAttendeesResolutionResult) -> Void) {
let people = Int(truncating: intent.attendees ?? 0)
if people < 0 {
completion(StartMeetingAttendeesResolutionResult.unsupported(forReason: StartMeetingAttendeesUnsupportedReason.negativeNumbersNotSupported))
} else if people > 1000 {
completion(StartMeetingAttendeesResolutionResult.unsupported(forReason: StartMeetingAttendeesUnsupportedReason.greaterThanMaximumValue))
} else {
completion(StartMeetingAttendeesResolutionResult.success(with: people))
}
}
}
When I run the shortcut from the Shortcuts app, I get the message "An unknown error has occurred". How does one go about debugging that?
After reviewing the console for the simulator I found two errors:
1)
[INCExtensionRequest _extensionContextHost] Unexpected extension context class (null)
and 2)
-[WFAction runWithInput:userInterface:parameterInputProvider:variableSource:completionHandler:]_block_invoke Action <WFHandleCustomIntentAction: 0x7ffe845b1a10, identifier: com.theapapp.wastedtime.AddAttendeeIntent, parameters: 2> finished with error {domain: WFIntentExecutorErrorDomain, code: 103}. Error Domain=WFIntentExecutorErrorDomain Code=103 "An unknown error occurred." UserInfo={NSLocalizedDescription=An unknown error occurred., WFIntentExecutorIntentResponseErrorKey=<INIntentResponse: 0x600003f63f80> {
userActivity = <null>;
code = INIntentResponseCodeFailure;
}, WFIntentExecutorIntentErrorKey=<INIntent: 0x6000018f0630> {
people = 1;
}, NSLocalizedFailureReason=Could Not Run Add Attendee}
I had this exact same error because I was accidentally returning my CustomIntent instead of my CustomIntentHandler in the IntentHandler.swift file
Before:
class IntentHandler: INExtension {
override func handler(for intent: INIntent) -> Any {
if intent is CustomIntent {
return CustomIntent()
}
return self
}
}
After:
class IntentHandler: INExtension {
override func handler(for intent: INIntent) -> Any {
if intent is CustomIntent {
return CustomIntentHandler()
}
return self
}
}
In order to track server errors from a Restfull Api on an SwiftUI IOS App I am feeding the error message from NSData to the "reason" parameter of next NetworkErrors enum:
enum NetworkError: Error {
case domainError(reason:String)
case decodingError(reason:String)
case encodingError(reason:String)
}
The error reason is fed when decoding the NSURLSession response:
static func postRequest<T:Decodable, U:Codable>(_ endpoint:String, _ input:U?, completion: #escaping (Result<T,NetworkError>) -> Void) {
...
do {
let retval = try JSONDecoder().decode(T.self, from: data)
completion(.success(retval))
} catch let DecodingError.dataCorrupted(context) {
let responseData = String(data: data, encoding: String.Encoding.utf8)
completion(.failure(.decodingError(reason: responseData ?? "Data corrupted from response")))
} catch {
...
}
...
}
The error reason should be available on next code, but I'm only able to print the localizedDescription:
Button(action:{
self.postRequest(endpoint, self.value){ (result: Result<Bool,NetworkError>) in
switch result {
case .success:
print("value saved successfully")
case .failure(let error):
print("failure to save value")
print(error.localizedDescription)
}
}
}){
Image(systemName:"icloud.and.arrow.up")
}
In the failure case, we know that error is a NetworkError, so now disassemble that error with another switch:
switch error {
case .domainError(let reason): // do something
case .decodingError(let reason): // do something
case .encodingError(let reason): // do something
}
Trying to poll the content of a website, no matter if JSON or REST API, I cannot seem to make it work. The same code works for iOS App, but will not get the content when being used within a Swift macOS Terminal application. What's the main reason?
The project does not have an Info.plist file.
Here's a code example that works within an iOS application, but not within the macOS Terminal application. I call the function with a simple jsonParser(), which initiates the NSURLSession and prints the JSON when it's arrived.
enum JSONError: String, ErrorType {
case NoData = "ERROR: no data"
case ConversionFailed = "ERROR: conversion from JSON failed"
}
func jsonParser() {
let urlPath = "https://api.coindesk.com/v1/bpi/currentprice.json"
guard let endpoint = NSURL(string: urlPath) else {
print("Error creating endpoint")
return
}
let request = NSMutableURLRequest(URL:endpoint)
NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) in
do {
guard let data = data else {
throw JSONError.NoData
}
guard let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary else {
throw JSONError.ConversionFailed
}
print(json)
} catch let error as JSONError {
print(error.rawValue)
} catch let error as NSError {
print(error.debugDescription)
}
}.resume()
}
I was able to solve my problem by adding
dispatch_main()
at the end of my main program code. Listed above was the function to request the web data. Thanks to Martin and Eric for pointing it out.
Using the latest XCode, I'm getting this error:
'logInWithReadPermissions(_:handler:)' is deprecated:
use logInWithReadPermissions:fromViewController:handler: instead'
How would I alternatively re-format my code? here is the whole function that it is in:
#IBAction func fbBtnPressed(sender: UIButton!) {
let facebookLogin = FBSDKLoginManager()
facebookLogin.logInWithReadPermissions(["email"]) {
(facebookResult: FBSDKLoginManagerLoginResult!,facebookError: NSError!) in
print("Facebook login failed. Error \(facebookError)")
}
}
Xcode 8.2 beta (8C30a) :
fbLoginManager.logIn(withReadPermissions:["email"], from: self, handler: {
(result, error) -> Void in
if (error == nil){
let fbloginresult : FBSDKLoginManagerLoginResult? = result
if(fbloginresult?.isCancelled)! {
//Show Cancel alert
} else if(fbloginresult?.grantedPermissions.contains("email"))! {
//self.returnUserData()
//fbLoginManager.logOut()
}
}
})
Figured it out guys! If anyone is lurking on this post, here is the new code:
#IBAction func fbBtnPressed(sender: UIButton!) {
let facebookLogin = FBSDKLoginManager()
facebookLogin.logInWithReadPermissions(["email"], fromViewController: self) { (facebookResult: FBSDKLoginManagerLoginResult!, facebookError: NSError!) -> Void in
print("Facebook login failed. Error \(facebookError)")
}
}
If your fbBtnPressed function is in a view controlle class, just pass self to the fromViewController parameter.
facebookLogin.logInWithReadPermissions(["email"], fromViewController: self) { ... }
A note though, it's encouraged in Swift and Obj-C that your function names prioritize readability over being compact. For example, I would name your button handler facebookLoginButtonPressed. It's longer but much more readable.
I use the signing up feature of Parse.com just as describe here. Here's my code:
user.signUpInBackgroundWithBlock {
(succeeded: Bool!, error: NSError!) -> Void in
if error == nil {
// Hooray! Let them use the app now.
} else {
let errorString = error.userInfo["error"] as NSString
// Show the errorString somewhere and let the user try again.
}
}
}
Unfortunately, I've updated my project from swift 1.1 to swift 1.2 and get the following compiler error:
Function signature '(Bool!, NSError!)->void is not compatible with
excepted type '#objc_block (Bool,NSError!)->Void'
it's on the following line:
user.signUpInBackgroundWithBlock {
(succeeded: Bool!, error: NSError!) -> Void in
Does anybody know how can I fox that ? Thanks !
Your succeeded variable is a 'Bool!' but what the block returns is a 'Bool' (without exclamation mark).
The solution would be:
user.signUpInBackgroundWithBlock {
(succeeded: Bool, error: NSError!) -> Void in
if error == nil {
// Hooray! Let them use the app now.
} else {
let errorString = error.userInfo["error"] as NSString
// Show the errorString somewhere and let the user try again.
}
}
}
Too see more about optionals go to the apple doc
I had the same problem with save in background with block. It looks like parse returns a "Bool not a Bool!"...however error is an NSError? unless you "!" it.
something.saveInBackgroundWithBlock {
(succeeded: Bool, error: NSError?) -> Void in
code
}