waitForExpectations not working as expected in Swift - swift

Trying to write a unit test in Swift 4 for an already working method and having trouble getting the correct result. My current approach is:
let expected = expectation(description: "Obtain access keys")
let keys = sut.retrieveAccessKeys()
//sleep(5)
if keys != nil {
expected.fulfill()
} else {
XCTFail("ERROR: Failed obtaining access keys")
}
waitForExpectations(timeout: 5) { error in
let myError = error as? Error
print("ERROR: \(String(describing: myError?.localizedDescription))")
}
}
The sut makes a network call via a completion handler if the values don't exist within the keychain. The outputted error I get is:
Error: The operation couldn’t be completed. (com.apple.XCTestErrorDomain error 0.)
I've tried various ways including adding in sleep(5). sut. retrieveAccessKeys() does work and the resulting keys contains an optional tuple.

Related

FirebaseMLNLTranslation model files not found

I am adding a translate text feature to my app. I have the text and run the initial setup, but this error keeps coming up.
error: Error Domain=com.firebase.ml Code=13 "Translation model files not found. Make sure to call downloadModelIfNeeded and if that fails, delete the models and retry." UserInfo={NSLocalizedDescription=Translation model files not found. Make sure to call downloadModelIfNeeded and if that fails, delete the models and retry.}
This is the function that translates the text...
translator.translate(textView.text) { [self] translatedText, error in
print("Translator Translated")
guard error == nil, let translatedText = translatedText else {
print(error!); return // prints the error below...
}
print(translatedText) // nil (when I comment out the guard statement)
}
This is the setup code run before the translation.
let options = TranslatorOptions(sourceLanguage: .en, targetLanguage: .es) //
print("Options: \(options)") // Options: sourceLanguage: en, targetLanguage: es
let translator = NaturalLanguage.naturalLanguage().translator(options: options)
print("Translator: \(translator)") // Translator: <FIRTranslator: 0x280173ac0>
let conditions = ModelDownloadConditions (
allowsCellularAccess: true,
allowsBackgroundDownloading: false
); print("Conditions: \(conditions)") // Conditions: allowsCellularAccess: 1, allowsBackgroundDownloading: 0
translator.downloadModelIfNeeded(with: conditions) { error in
guard error == nil else {
print("Model Failed To Download because: \(error!)"); return
}
}
textView.text is not nil. I have no idea how to solve this problem and there are no solutions that I have found online. It actually used to work and I revisited my project after some time off and it all of a sudden started presenting this error. Any help is appreciated.

Cannot assign values from functions to dictionary array Swift 4

I've encountered the following error in two different scenarios that may be related. The error is:
lldb Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
This is the code for the first scenario:
db.collection("properties").getDocuments()
{
(querySnapshot, err) in
if let err = err
{
print("Error getting documents: \(err)");
}
else
{
for document in querySnapshot!.documents {
var propertyData = [String:[String]]()
let listingType = (document.get("listingType") as! [String])
propertyData["listingType"]![0] = listingType[0]
}
}
}
I am trying to get a list of properties that I have already set in Firestore. I can print the listingType variable to the console and it successfully prints "Sale". However when I assign the variable it then gives that error.
I have experienced the same issue when using the location manager functions. If I get the user's current location coordinates, when I try to add those coordinates to a global dictionary it throws the same error. I am writing the code in Swift 4.
You can't just assign something to [0] since the array is initially nil
if propertyData["listingType"] == nil {
propertyData["listingType"] = [listingType[0]] //Create a new array with the string
} else {
propertyData["listingType"]![0] = listingType[0]
}

Confused on Error Handling in Swift 3

I got confused error handling in swift3. I try to do like "if XX function got error then try YY function"
Let me show you what I try:
class MyClass {
enum error: Error
{
case nilString
}
func findURL() {
do {
let opt = try HTTP.GET(url_adr!)
opt.start { response in
if let err = response.error {
print("error: \(err.localizedDescription)")
return //also notify app of failure as needed
}
do
{
/* This is func1. and got error. I want to if this function has error then go next function. */
try self.stringOperation(data: response.description)
}
catch{
print("doesn't work on func1. trying 2nd func")
self.stringOperation2(data:response.descritption)
}
}
} catch let error {
print("got an error creating the request: \(error)")
}
}
func stringOperation(data:String)throws -> Bool{
do{
/** 1 **/
if let _:String = try! data.substring(from: data.index(of: "var sources2")!){
print("its done")
}else{
throw error.nilString
}
IN 1: I got this fatal error on this line:
"fatal error: unexpectedly found nil while unwrapping an Optional value" and program crashed.
I googled error handling try to understand and apply to in my code. However not succeed yet. Can someone explain where did I wrong?
Additional info: I got String extension for .substring(from:...) , and .index(of:"str"). So these lines doesn't got you confused.
As a general rule, try avoiding using force unwrapping (!), where you have
if let _: String= try! data.substring...
Instead use
if let index = data.index(of: "var sources2"),
let _: String = try? data.substring(from: index) { ... } else { ... }
That way you remove the two force unwraps that may be causing your crash. You already have the if let protection for catching the nil value, so you can make the most of it by using the conditional unwrapping.

Swift 3 change to NSErrorPointer?

I have code I've been using for SwiftyJSON and I'm trying to update to Swift 3 using XCode 8.0 Beta 3. I'm running into an issue where the compiler doesn't like the argument 'error: &err' as it did before. I've been searching for how to correctly pass an NSErrorPointer but everything I've found says to re-write, leave out the error and throw an error back. Since this isn't my code I'd rather leave it as it is. So what's the correct new way to use an NSErrorPointer?
var err : NSError?
// code to get jsonData from file
let json = JSON(data: jsonData, options: JSONSerialization.ReadingOptions.allowFragments, error: &err)
if err != nil {
// do something with the error
} else {
return json
}
The code above results in compiler error: '&' can only appear immediately in a call argument list. I've tried creating an NSErrorPointer so I can use that instead but I can't find anything on how to initialize one (the type alias declaration is not enough). I've already been to Using Swift with Cocoa and Obj-C, it does not contain the word NSErrorPointer, instead goes over the new way of throwing errors. I've also looked over a couple dozen posts all using the &err so apparently this is new to Swift 3.
Is there anyone out there that's solved this one? What's the answer to using NSErrorPointer?
Thanks,
Mike
That seems to be an error in the Swift 3 branch of SwiftyJSON at
https://github.com/SwiftyJSON/SwiftyJSON/blob/swift3/Source/SwiftyJSON.swift
which defines the init method as
public init(data:Data, options opt: JSONSerialization.ReadingOptions = .allowFragments, error: NSErrorPointer? = nil) {
do {
let object: AnyObject = try JSONSerialization.jsonObject(with: data, options: opt)
self.init(object)
} catch let aError as NSError {
if error != nil {
error??.pointee = aError
}
self.init(NSNull())
}
}
In the Swift 3 that comes with Xcode 8 beta 3, NSErrorPointer is an optional:
public typealias NSErrorPointer = AutoreleasingUnsafeMutablePointer<NSError?>?
as a consequence of
SE-0055: Make unsafe pointer nullability explicit using Optional
Therefore the error parameter should have the type NSErrorPointer,
not NSErrorPointer? (and consequently error??.pointee
changed to error?.pointee).
With these changes the init method becomes
public init(data:Data, options opt: JSONSerialization.ReadingOptions = .allowFragments, error: NSErrorPointer = nil) {
do {
let object: AnyObject = try JSONSerialization.jsonObject(with: data, options: opt)
self.init(object)
} catch let aError as NSError {
if error != nil {
error?.pointee = aError
}
self.init(NSNull())
}
}
and then your code compiles and runs as expected.

Swift: passing params - unexpectedly found nil while unwrapping an Optional value

I'm trying to use Alamofire and passing my parameters to a function I made.
Here's my code:
let msisdn : AnyObject = textFields[0].text!
//let msisdn = textFields[0].text!
let userId = "MyID"
let params = [
"msisidn":msisdn /*as AnyObject*/,
"denom_id":self.selectedGameDetail.Id /*as AnyObject*/,
"game_id":self.selectedGameDetail.GameId /*as AnyObject*/
]
print(params)
showEZLoading(true)
su.postEpins(userId, params: params, completion:{ (result, error) -> Void in
self.hideEZLoading()
if (error != nil){
print("DEBUG: API Response Error")
Utility.displayAlert(self, msg: "There's an errror fetching data from server.")
}
else {
print("DEBUG: API Response Success")
}
})
Everything in selectedGameDetail is a String.
And here's the postEpins function:
func postEpins(msisdn: String, params: [String: AnyObject]?, completion:(result: JSON, error: NSError?) -> Void) {
print("POST EPINS")
}
Doesn't do anything yet. But, whenever the app gets to the function call, I get this:
fatal error: unexpectedly found nil while unwrapping an Optional value
I'm positive it has something to do with the params, but I'm 100% sure. Yes, params has stuff in it. Check below.
What I've tried:
Well, if you see a comment in my code, I've pretty much tried those. And I have no idea what else to do.
For reference, that exact same code works on another part of the app, minus the userID - and I also tried removing that, but it still gave me the above error.
I found this regarding the params:
I noticed that one of the values is an NSTaggedPointerString, whereas everything else is an AnyObject. Is this an issue?