Alamofire: unexpectedly found nil while unwrapping an Optional value - ios

Good Day.
I have a iOS Swift Application that communicates with a companies already created API and its communicated with using Alamofire. The problem I have is the API can possibly return nulls some time and this causes the following problem:
"fatal error: unexpectedly found nil while unwrapping an Optional value"
My code snippet that reads from the dictionary is as follows:
if let LowRate = HotelList[i]["LowRate"] as? Decimal!{
HList._LowRate = LowRate
}
I have reviewed multiple questions and google sites however I need a way to check the object in the dictionary for null before its processed or I need to set some type of default value.
The Json null example is as follows
HotelData = "<null>";
HotelList =(
{
Address1 = "124 Oceanview Road";
Address2 = Oneroa;
BookingUrl = "<null>";
City = " Auckland";
Country = "New Zealand";
CurrencyCode = "<null>";
DateViewed = "<null>";
Description = "<null>";
Directions = "<null>";
Distance = "<null>";
GeoPoint = "<null>";
HighRate = "<null>";
ImageUrl = "<null>";
LowRate = "<null>";
MinChildAge = "<null>";
Name = "The Oyster Inn";
NavUrl = "<null>";
PostalCode = "<null>";
State = "<null>";
WebsiteUrl = "<null>";
distance = "<null>";
hotelID = 130;
isActive = 1;
isBlocked = 0;
isChildrenAllowed = "<null>";
isFavorite = 0;
isPromoNotified = 0;
showDouble = "<null>";
}
);
RowCount = 11;
hasError = 0;
};
I am using Alamofire for my json and it works unless there is a null returned in one of the 20 fields that could possibly return a null.
Can anyone assist me in doing some validation checks for the result of a null as shown above while unwrapping an optional.
Regards

This is how you can do this.(Updated)
if let lowRate = json["LowRate"], !(lowRate is NSNull){
print(lowRate)
}else{
print("null")
}

Good Day
Thanks to all the contributions to helping me find my answer. What worked in the end was something very similar to above I had to use a NSNumber object and then cast it to a decimal later along the lines please see code below.
if let lowRate = HotelList[i]["LowRate"] as? NSNumber{
HList._LowRate = LowRate
}else{
print("Null")
}
Regards

Your json has array of only one object. What is the value of i? If it's greater than 0 it will crash.

Related

Traverse nsdictionary in swift

I am new to swift.
I have my dictionary as
monthData =
{
"2018-08-10" = {
accuracy = 71;
attempted = 7;
correct = 5;
reward = Bronze;
};
"2018-08-12" = {
accuracy = 13;
attempted = 15;
correct = 2;
reward = "";
};
"2018-08-13" = {
accuracy = 33;
attempted = 15;
correct = 5;
reward = "";
};
"2018-08-14" = {
accuracy = 100;
attempted = 15;
correct = 15;
reward = Gold;
};
"2018-08-16" = {
accuracy = 73;
attempted = 15;
correct = 11;
reward = Silver;
};
"2018-08-21" = {
accuracy = 26;
attempted = 15;
correct = 4;
reward = "";
};
"2018-08-23" = {
accuracy = 46;
attempted = 15;
correct = 7;
reward = "";
};
}
I want to get all the dates for which reward is Gold
Can anyone please help me do that?
What I have tried 'till now is:
for (key,value) in monthData{
let temp = monthData.value(forKey: key as! String) as! NSDictionary
for (key1,value1) in temp{
if((value1 as! String) == "Gold"){
print("keyFINAL \(key)")
}
}
but it outputs the error Could not cast value of type '__NSCFNumber' to 'NSString'
The error occurs because when you are iterating the dictionary you force cast the Int values to String which is not possible
The (highly) recommended Swift way is to use the filter function. This is much more efficient than a loop.
In the closure $0.1 represents the value of the current dictionary ($0.0 would be the key). The result is an array of the date strings.
let data : [String:Any] = ["monthData" : ["2018-08-10": ["accuracy" : 71, "attempted" ... ]]]
if let monthData = data["monthData"] as? [String:[String:Any]] {
let goldData = monthData.filter { $0.1["reward"] as? String == "Gold" }
let allDates = Array(goldData.keys)
print(allDates)
}
The code safely unwraps all optionals.
However if there is only one Gold entry the first function is still more efficient than filter
if let monthData = data["monthData"] as? [String:[String : Any]] {
if let goldData = monthData.first( where: {$0.1["reward"] as? String == "Gold" }) {
let goldDate = goldData.key
print(goldDate)
}
}
In Swift avoid the ObjC runtime (value(forKey:)) and Foundation collection types (NSDictionary) as much as possible.
From the first for in loop, you are getting the NSDictionary in temp variable
"2018-08-16" = {
accuracy = 73;
attempted = 15;
correct = 11;
reward = Silver;
};
So, you should directly check .value(forKey:) on temp and get the value for reward.
You should try it like this
for (key,value) in monthData {
let temp = monthData.value(forKey: key as! String) as! NSDictionary
if(((temp.value(forKey: "reward")) as! String) == "Gold"){
print("keyFINAL \(key)")
}
}
Try and share results
EDIT
Please checkout the answer from vadian for in-depth explanation and pure swift approach to achieve the same.
Thanks

PayUBiz hash integration failed-iOS?

I am calculating hash from server and passed it to payUbiz hash object. When hash value passed to hash object of payUbiz it binds as optional value i.e. Optional(*hashValue*). I have tried to convert optional string to string, but it won't worked. It gives Invalid Parameter error.
Below is my hash value response from server:
{
errorMessage = "Success.";
lastSyncDateTime = "<null>";
result = {
furl = "http://192.168.3.2:93/PayU/AppointmentResponse";
hash = 4875a6096814ee1fbe19110582ea0a1564f81880ae66539b94384d3d332106855a00132332919724f085d02d64cffb6d47ff98f3ac4eb7d5e2bb31b4022e3f06;
merchantKey = gtKFFx;
mobileSDKHASH = 110f85b862578214e5c38637762a6fce9c34bd5e2d78bc34a486f0ee2e3e5d0fada221795de4b67952ec2cff6b4d0fe8877506e7a5480bbdbfdf9045521d8523;
payURequestArea = 1;
profileID = 7;
surl = "http://192.168.3.2:93/PayU/AppointmentResponse";
txnID = 62604613a06163c02ddd;
userID = 18;
vasMobileSDKHASH = 7da0f4fef5bab0e5034f37f9503bdcbede00cc2cd0cf6cbb4e43baa9d57f05680305885199e2b0d38e8cf12895fd06f4d3dd3fb422535feeb555adc58e2cf3cc;
};
statusCode = 200;
}
This is hashvalue printed from payUbiz
paymentHash: Optional("4875a6096814ee1fbe19110582ea0a1564f81880ae66539b94384d3d332106855a00132332919724f085d02d64cffb6d47ff98f3ac4eb7d5e2bb31b4022e3f06")
vasForMobileSDKHash: Optional("7da0f4fef5bab0e5034f37f9503bdcbede00cc2cd0cf6cbb4e43baa9d57f05680305885199e2b0d38e8cf12895fd06f4d3dd3fb422535feeb555adc58e2cf3cc")
paymentRelatedDetailsHash: Optional("110f85b862578214e5c38637762a6fce9c34bd5e2d78bc34a486f0ee2e3e5d0fada221795de4b67952ec2cff6b4d0fe8877506e7a5480bbdbfdf9045521d8523")
Please give solution on this
I have faced same issue a month ago. I think Optional value is not cause of issue. The response itself say's that "Invalid Parameters" means there are some invalid parameters passed to Payment gateway.
Please check following parameters are provided or not:
paymentParam.key = *Your key*;
paymentParam.transactionID = *Transaction ID*
paymentParam.amount = *Amount*
paymentParam.productInfo = *Product Info*;
paymentParam.surl = *Success URL*;
paymentParam.furl = *Failure URL*;
paymentParam.firstName = "";
paymentParam.email = "";
paymentParam.udf1 = "";
paymentParam.udf2 = "";
paymentParam.udf3 = "";
paymentParam.udf4 = "";
paymentParam.udf5 = "";
paymentParam.hashes = hashes; //**Important**
paymentParam.userCredentials = "default"; **//This was the issue in my case, i have accidentally deleted this parameter**
// ENVIRONMENT_TEST for test environment:
paymentParam.environment = ENVIRONMENT_TEST;
// Set this property if you want to give offer:
paymentParam.offerKey = "";
Please check for paymentParam.userCredentials = "default" parameter,
because after adding this parameter i have solved my issue.
Hope this will help you.

How Parse JSON from API [duplicate]

This question already has answers here:
type 'Any' has no subscript members
(2 answers)
Closed 5 years ago.
i know to much ask like this. i already searching but not match with my problems.
oke i will try explain with my code
i have data API Like this
["profile": {
accountId = 58e470a0c50472851060d083;
androidDeviceId = "[\"3453247ddcf3f809\"]";
androidVersion = 21;
appId = (
"c46b4c10-62ce-11e6-bdd4-59e4df4b8410",
"fac915f0-fe2b-11e6-9dfb-55339bd7be35"
);
appVersion = "v5.1.0";
avatar = "https://account.8villages.com/uploads/images/5/1491366164_bnx1t0rudi.jpg";
birthDate = "12/03/1994";
"channel-group" = android;
communityId = 553e09b251906884443eff85;
coordinates = {
coordinates = (
"106.9602383333333",
"-6.249333333333334"
);
type = Point;
};
crop = "";
crops = "<null>";
customerId = 5369bd85cae84d0e03246a7c;
dateSubmitted = {
iso = "2017-04-05T04:20:48.483Z";
timestamp = 1491366048;
};
fullName = "Megi Fernanda";
gender = "Laki-laki";
homeAddress = Payakumbuah;
location = "Kota Payakumbuh";
moderation = {
at = {
iso = "2017-04-05T04:20:48.483Z";
timestamp = 1491366048;
};
by = auto;
status = moderated;
};
skill = "Budidaya pertanian";
state = "Sumatera Barat";
storeType = "";
subdistrict = "Payakumbuh Barat";
totalConversations = {
articles = 0;
forums = 0;
questions = 2;
responses = 0;
storeItems = 1;
};
type = users;
university = "Politeknik Negeri Pertanian Payakumbuh";
}, "accessToken": {
key = "lH5aYvnp2JAZ6zoKQK4mpfsxCI0.";
secret = "yfZfTZbsaVIhKCbksGHQnPcPg9mKtoRAKyvjg_cgMeo.";
}]
i already can got fullName, Addres, Skill State etc
if let profile = json["profile"] as? NSDictionary {
let name = profile["fullName"]
let alamat = profile["Skill"]
}
but i don't know how to get atribut in totalConversation like question, storeItems, points
skill = "Budidaya pertanian";
state = "Sumatera Barat";
storeType = "";
subdistrict = "Payakumbuh Barat";
totalConversations = {
articles = 0;
forums = 0;
questions = 2;
responses = 0;
storeItems = 1;
};
i tried like
let profile = json["profile"]["totalConversation"] as? NSDictionary
error sign : Type 'any?' has no subscript members
You got that error because json["profile"] is Any type and it doesn't have any subscript. So you need to cast json["profile"] to a dictionary, [String: Any] is dictionary type in Swift.
if let profile = json["profile"] as? [String: Any] {
if let totalConversations = profile["totalConversations"] as? [String: Any] {
let questions = totalConversations["questions"] as? Int
}
}

Indexing into NSArray with JSON object

I receive an object that is sent as a pointer to a collection.
I can access the fields directly as an NSDictionary.
The emails field is sent as an array, and I receive it in parentheses. Currently I get the emailaddress by what I feel is a roundabout method.
How can I most efficiently get to the email address?
let allDoc = users.allDocuments[0]
print("allDoc: \(allDoc)")
let emailsArray = users.allDocuments[0].valueForKey("emails") as! NSArray
print("emailsArray: \(emailsArray)")
let emailAddress = emailsArray[0]["address"] as! String
print("emailAddress: \(emailAddress)")
Console output:
allDoc: <METDocument key: <collection: users, ID: kzzw3vcqukD62xEyz>, fields: {
emails = (
{
address = "xxxx#gmail.com";
verified = 1;
}
);
profile = {
address = {
city = "";
country = nor;
lineOne = "";
lineTwo = "";
zip = "";
};
card = {
last4 = 4242;
verified = 1;
};
filledOut = 1;
name = {
first = XXXX;
last = XXXX;
};
phone = 9999999999;
validated = 1;
};
}>
emailsArray: (
{
address = "xxxx#gmail.com";
verified = 1;
}
)
emailAddress: xxxx#gmail.com
If you just want the email address you could simply do:
let emailsAddress = users.allDocuments[0]["emails"][0][#"address"] as! String
print("emailAddress: \(emailAddress)")
But it really is better to use multiple lines. It makes the code much easier to read and debug. Also, putting all that onto one line doesn't allow any error checking. What if the #"emails" key has an empty array, for example? The code will crash.

Parse Json using SwiftyJson

I am able to get the entire JSon array parsed. It outputs to console with no issue. I can't seem to get the individual params from the array... my json looks like:
[{
City = NYC;
Device = "<null>";
DisplayAs = "Steve Hutson";
FirstName = Steve;
LastName = Hutson;
MobilePhone = "000-000-0000";
Org = "<null>";
Region = "";
Role = INSPECTOR;
SupervisorID = "73990";
email = "email#email.com";
fLast = shutson;
"gz_modtimestamp" = "2015-07-28 14:42:41";
id = 96;
isActive = YES;
lastupdated = "<null>";
sendemail = 1;
token = "<null>";
userpassword = "xxx";
},{
City = DET;
Device = "<null>";
DisplayAs = "Filipe Washington";
FirstName = Filipe;
LastName = Washington;
MobilePhone = "000-000-0000";
Org = "<null>";
Region = "";
Role = INSPECTOR;
SupervisorID = "6567";
email = "email#email.com";
fLast = shutson;
"gz_modtimestamp" = "2015-07-28 13:02:09";
id = 93;
isActive = YES;
lastupdated = "<null>";
sendemail = 1;
token = "<null>";
userpassword = "xxx";
}]
In my main ViewController.swift file my json request looks like:
var myData:NSData = getJSON("http://xxxx/getusersData.php")
var myDict:NSArray = parseJSON(myData)
println(myDict)
This prints my entire json object which is perfect. However my issue is, how do I get only the FirstName's in an array? By index this works:
println(myDict[0]["FirstName"]) how ever, it only brings back one item.
I am trying to insert specific json items into sqlite which i am using SQLite.swift but i need to know how to retrieve specific item parameters as I would if i was using AJAX.
I am trying to retrieve FirstName, Email and UserPassword info.
Any help would be appreciated.
You can iterate over the JSON object and retrieve that info:
for (index: String, subJson: JSON) in json {
//Do something you want
var firstName = subJson["FirstName"].stringValue
var email = subJson["email"].stringValue
var userPassword = subJson["userpassword"].stringValue
// Build the sqlite query with the variables here
}
As a clarification, you don't access the values directly as in json["FirstName"], you must also use the type functions from SwiftyJSON. In your case they're both strings, so stringValue is used. If you needed and int, it'd be intValue.
There's also the option of just json["FirstName"].string in case the field is optional. Take a look at the readme

Resources