Fatal error: Binding error to behavior relay: objectDeleted: file #2025 - rx-swift

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

"An Unknown error occurred" When trying to launch my Siri Shortcut

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
}
}

How to get reason from custom error enum on Swift failure Result

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
}

Xcode Swift macOS, Terminal App not doing NSURLSession

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.

logInWithReadPermissions(_:handler:)' is deprecated: use logInWithReadPermissions:fromViewController:handler: instead

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.

Signing Up Parse User with Swift 1.2

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
}

Resources