I want to run the same line of code but incrementing the number "prodottiNome_prodotto0" and forKey: ("nome_prodotto0") always.
let prodotti = jsonData.value(forKey: "prodotti") as! NSDictionary
let prodottiNome_prodotto0 = prodotti.value(forKey: "nome_prodotto0") as! String
self.defaultValues.set(prodottiNome_prodotto0, forKey: "nome_prodotto0")
nome_prodotto0 refers to the result of a return in php ------------>
"prodotti":{"nome_prodotto0":"farina","nome_prodotto1":"dfd"}
If I understand what you're asking, your code might look like this:
let max = 50 //Or whatever limit you want to use
for i in 0...max {
let key = "nome_prodotto" + String(i)
//Use `if let` so you don't crash if a value is not a string
//Don't use `value(forKey:)` on a dictionary. That's a KVO method
if let value = prodotti[key] as? String {
self.defaultValues.set(value, forKey: key)
{
}
Related
I'm working on a database connection between Swift 3 and a php file.
Sending information to the php will be correctly transfered into the database.
But I'm having an issue when I want to print information from the database into my xcode.
I'm sending this json to my app:
[{"latitude":"51.430536341034","longitude":"5.45947450542819"},
{"latitude":"51.4305299243587","longitude":"5.45964865535365"},
{"latitude":"51.4305299243587","longitude":"5.45964865535365"},
{"latitude":"51.4305299243587","longitude":"5.45964865535365"},
{"latitude":"51.4305299243587","longitude":"5.45964865535365"}]
I printed this JSON in xcode with:
print(NSString(data: data!, encoding: String.Encoding.utf8.rawValue)!)
I tried 2 options that were described in other topics at this site, which both were about swift 3 and json problems.
Option 1:
let parsedData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:AnyObject]
When I ran the app, there come's an error:
Signal SGBRT Could not cast value of type '__NSArrayI' (0x1b2a89cc8) to 'NSDictionary' (0x1b2a8a128).
Option 2:
let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! Dictionary<String, AnyObject>
What happens is the same Signal SGBRT with error:
Could not cast value of type '__NSArrayI' (0x1b2a89cc8) to 'NSDictionary' (0x1b2a8a128).
I need to say that I'm not a professional, but I'm a hard learning student with no connections that also program swift. Therefore I hope to get some help here, to finish this function of the app.
If you answer the topic, I would be glad to here some other codes I should try.
Thank you.
From your JSON response that you have added in question, if that was the only response that you need to use [[String: String]] instead of [[String: AnyObject]] because using AnyObject you need to first convert it to String then double, so it is batter if you use [[String: String]]. Now you have array of dictionary so get all coordinates like this way.
let parsedData = try? JSONSerialization.jsonObject(with: data!, options: []) as! [[String:String]]
for dic in parsedData {
if let lat = Double(dic["latitude"]), let long = Double(dic["longitude"]) {
print(lat)
print(long)
}
}
Your JSON clearly says that it is an array of dictionaries, so you should cast it to an array of dictionaries [[String: AnyObject]]. Already mentioned in comments. Try below, it might help you:
//First you should check for data whether it has value
if let data = data {
//This gives you an array of dictionaries as per your JSON data. So safer side try to 'guard let' it so that it should not crash if your JSON data is nil
guard let parsedDataArray = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: AnyObject]] else { return }
//Here you can enumerate through your array to get each dictionary
for parsedDict in parsedDataArray {
//This gives the value of latitude
if let latitude = parsedDict["latitude"] {
print(latitude)
}
//And this is for "longitude"
if let longitude = parsedDict["longitude"] {
print(longitude)
}
}
}
Using a PHP file, I echoed data from a MySQL database in the following format: [{"longitude":"-122.031","latitude":"37.3323”}]
In my Swift file, I use NSJSONSerialization.JSONObjectWithData() to create a JSON dictionary that looks like the following
(
{
latitude = "37.3323";
longitude = "-122.031";
}
)
If I wanted to store the individual dictionary values inside variables, I believe the following snippet of Swift code would work
class Location: NSObject {
var latitude: String?
var longitude: String?
}
var locations = [Location]()
if let locationDictionary = jsonDictionary["coordinates"] as? [String: AnyObject] {
let location = Location()
location.setValuesForKeysWithDictionary(locationDictionary)
print(location.latitude, location.longitude)
}
The only problem I’m having is that I need my JSON dictionary to look like
(
coordinates = {
latitude = "37.3323";
longitude = "-122.031";
}
)
but I don’t know what steps to take to achieve this.
You would have to make your JSON like this:
[{"coordinates":{"longitude":"-122.031","latitude":"37.3323"}}]
which is an array of dictionaries, where each dictionary contains another one.
And here is your code adapted for the new format:
if let json = try? NSJSONSerialization.JSONObjectWithData(data, options: []), // your source may differ, I'm just using this line for my example
content = json as? [[String:AnyObject]] { // the array of dictionaries
for item in content {
if let locationDictionary = item["coordinates"] as? [String: AnyObject] { // the dictionary inside the dictionary
let location = Location()
location.setValuesForKeysWithDictionary(locationDictionary)
print(location.latitude, location.longitude)
}
}
}
I want to crypt privateKey & publicKey to sha1 in base64 with Swift, but the output is not the one I see in PHP urlencode base64_encode which I tried in Codecademy:"https://www.codecademy.com/courses/web-beginner-en-StaFQ/0/3?curriculum_id=5124ef4c78d510dd89003eb8".
Pls see the following codes in Swift and Codecademy:
Swift:
//pls see func dataFromHexadecimalString() details here "http://stackoverflow.com/questions/26501276/convert-string-to-hex-string-in-swift/26502285#26502285"
extension String {
func dataFromHexadecimalString() -> NSData? {
let trimmedString = self.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "<> ")).stringByReplacingOccurrencesOfString(" ", withString: "")
var error: NSError?
let regex = NSRegularExpression(pattern: "^[0-9a-f]*$", options: .CaseInsensitive, error: &error)
let found = regex?.firstMatchInString(trimmedString, options: nil, range: NSMakeRange(0, count(trimmedString)))
if found == nil || found?.range.location == NSNotFound || count(trimmedString) % 2 != 0 {
return nil
}
let data = NSMutableData(capacity: count(trimmedString) / 2)
for var index = trimmedString.startIndex; index < trimmedString.endIndex; index = index.successor().successor() {
let byteString = trimmedString.substringWithRange(Range<String.Index>(start: index, end: index.successor().successor()))
let num = UInt8(byteString.withCString { strtoul($0, nil, 16) })
data?.appendBytes([num] as [UInt8], length: 1)
}
return data
}
}
func URLEcodekey() -> String {
let appid="a1b2c34d5e"
let privateKey="ef7d6s0d"
let areaid="101020900"
let time="201507191254"
let publicKey="http://open.weather.com.cn/data/?areaid=\(areaid)&type=forecast_v&date=\(time)&appid=\(appid)"
let cPrivateKey=privateKey.dataUsingEncoding(NSUTF8StringEncoding)!
let cPublicKey=publicKey.dataUsingEncoding(NSUTF8StringEncoding)!
var cHMAC = [CUnsignedChar](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1), cPublicKey.bytes, Int(cPublicKey.length), cPrivateKey.bytes, Int(cPrivateKey.length), &cHMAC)
let hexKeyString=NSMutableString(capacity: Int(CC_SHA1_DIGEST_LENGTH))
for byte in cHMAC{
hexKeyString.appendFormat("%02hhx", byte)
}
println("hexKeyString:\(encryptedKey)")
let binaryData = hexKeyString.dataFromHexadecimalString()
let base64String = binaryData?.base64EncodedStringWithOptions(nil)
println("base64String:\(base64String)")
var urlEncodeKey=base64String!.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())!
println("urlEncodeKey:\(urlEncodeKey)")
return urlEncodeMessage
}
the outputs are:
hexKeyString:d4433d42b1505c00a4aa80205171d0d04754d254
base64String:1EM9QrFQXACkqoAgUXHQ0EdU0lQ=
urlEncodeKey:1EM9QrFQXACkqoAgUXHQ0EdU0lQ=
PHP in Codecademy:
echo urlencode(base64_encode(hash_hmac('sha1', " http://open.weather.com.cn/data/?areaid=101020900&type=forecast_v&date=201507191254&appid=a1b2c34d5e", "ef7d6s0d", TRUE)));
the output is:
A5O59Y%2BFbGjhVwaI9JNB7DkcX%2F4%3D // the output is much like the
example in API, which I think maybe the right one.
So, how can I receive the right urlEncodeKey for my privateKey & publicKey like in PHP?
Thank you very much in advance!
You should read more about cryptography and hashing. In your case, there's no public key, private key, ... SHA stands for Secure hash algorithm and what you're trying to get is Hash based authentication code. Check Wikipedia articles about HMAC, SHA-1, Public key, ... I strongly recommend to read more about it otherwise you can create more damage if you misunderstand it.
Back to your problem. It's in one character:
Swift code - let publicKey="http://open.weather.com.cn...
PHP code - hash_hmac('sha1', " http://open.weather.com.cn...
Do you see where the problem is? In your PHP code, there's one space character just before http. This character is not in your Swift code.
Honestly, I didn't check your whole code, because I don't know why you're trying to convert it from hexadecimal string, etc. Used some parts only and rewrote it from scratch for you. Here's working example:
func URLEncodedKey() -> String? {
let appid = "a1b2c34d5e"
let time = "201507191254"
let areaid = "101020900"
let key = "ef7d6s0d"
let string = " http://open.weather.com.cn/data/?areaid=\(areaid)&type=forecast_v&date=\(time)&appid=\(appid)"
// ^ <- in your PHP example, there's space
guard let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
stringData = string.dataUsingEncoding(NSUTF8StringEncoding),
outputData = NSMutableData(length: Int(CC_SHA1_DIGEST_LENGTH)) else {
return nil
}
outputData.length = Int(CC_SHA1_DIGEST_LENGTH)
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1),
keyData.bytes, keyData.length,
stringData.bytes, stringData.length,
outputData.mutableBytes)
return outputData
.base64EncodedStringWithOptions([])
.stringByAddingPercentEncodingWithAllowedCharacters(.URLQueryAllowedCharacterSet())
}
Return value is:
`Optional("A5O59Y+FbGjhVwaI9JNB7DkcX/4=")`
Which is what you get when you decode your PHP output.
Just replace URLQueryAllowedCharacterSet with any of the following character sets:
class func URLUserAllowedCharacterSet() -> NSCharacterSet
class func URLPasswordAllowedCharacterSet() -> NSCharacterSet
class func URLHostAllowedCharacterSet() -> NSCharacterSet
class func URLPathAllowedCharacterSet() -> NSCharacterSet
class func URLQueryAllowedCharacterSet() -> NSCharacterSet
class func URLFragmentAllowedCharacterSet() -> NSCharacterSet
Depends on your use case. IOW in which part of the URL your would like to use it.
I'm passing a large set of strings to my server from iOS (Swift) to a PHP file via POST. Unfortunately, if a user places an ampersand (&) in a field, the rest of the field is lost. I understand why (& signifies the next field in the message) but I'm not sure how to fix.
func UploadToSql(plan: LessonPlan, isNew: Bool, callBack: ((data: NSData!, response: NSURLResponse!, error: NSError!) -> Void)?) {
let url = NSURL(string: "https://myserver.com/receive.php")!
var request:NSMutableURLRequest = NSMutableURLRequest(URL:url)
var bodyData = "Author=\(plan.author)&title=\(plan.title)&grade=\(plan.grade)&date=\"\(plan.date)\"&element1=\(plan.element1)&objective1=\(convertedFields[0])&element2=\(plan.element2)&objective2=\(convertedFields[1])&element3=\(plan.element3)&objective3=\(convertedFields[2])&coreProcess1=\(plan.coreProcess1)&coreStrand1=\(plan.coreStrand1)&coreStandard1=\(plan.coreStandard1)&coreProcess2=\(plan.coreProcess2)&coreStrand2=\(plan.coreStrand2)&coreStandard2=\(plan.coreStandard2)&coreProcess3=\(plan.coreProcess3)&coreStrand3=\(plan.coreStrand3)&coreStandard3=\(plan.coreStandard3)&media1=\(plan.media1)&media2=\(plan.media2)&media3=\(plan.media3)&media4=\(plan.media4)&media5=\(plan.media5)&media6=\(plan.media6)&repertoire1=\(convertedFields[3])&repertoire2=\(convertedFields[4])&repertoire3=\(convertedFields[5])&process=\(convertedFields[6])&assessment=\(convertedFields[7])&stateCat1=\(plan.stateCat1)&stateCat2=\(plan.stateCat2)&stateCat3=\(plan.stateCat3)&stateStand1=\(plan.stateStand1)&stateStand2=\(plan.stateStand2)&stateStand3=\(plan.stateStand3)&comment=\(plan.comment)&shared=\(sharedInt!)&authorName=\(plan.authorName)" + planID
request.HTTPMethod = "POST"
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
println("error=\(error)")
return
}
println("response = \(response)")
callBack?(data: data, response: response, error: error)
return
}
task.resume()
}
Typically for a webrequest like that it uses % followed by the ascii hex value. The hex value for & is 26, so it would be %26
google.com/#q=red%26white is example of a google search for red&white, which uses that replacement
Its called URL encoding or percent encoding and here is another question with an answer on how to do more broad URL encoding: stackoverflow.com/questions/24551816/swift-encode-url
Note that you would have to URL encode each element you were interpolating into the string, not the whole result string, as you want to keep your &'s that separate parameters.
This one is working for me. I am also using PHP/MySQL with NSURLSession.
func stringByAddingPercentEncodingForFormData(plusForSpace: Bool=false) -> String? {
let unreserved = "*-._"
let allowed = NSMutableCharacterSet.alphanumericCharacterSet()
allowed.addCharactersInString(unreserved)
if plusForSpace {
allowed.addCharactersInString(" ")
}
var encoded = stringByAddingPercentEncodingWithAllowedCharacters(allowed)
if plusForSpace {
encoded = encoded?.stringByReplacingOccurrencesOfString(" ",
withString: "+")
}
return encoded
}
Found above function from this link: http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/.
How do I get/extract datas from bracket/object in iOS swift???
I used println(datas) to display in Xcode6 console log:
Optional({"status":"fail","message":"Invalid Username or Password"})
note:
server code: php language.
I want to get this datas from that object or array. I don't know what that is.
I want to specifically display status in a specific label.
I want swift code if possible. Thank you very much!!! :D hehe
You PhP code returns a JSON, its like this:
{
"status":"fail",
"message":"Invalid Username or Password"
}
Its an NSDictionary type data, So receive it in an NSDictionary, lets call it responseData.
Then If you want to get status then write this:
let status = responseData ["status"]! as String
For message :
let message = responseData ["message"]! as String
From your provided code:
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
let status = jsonResult ["status"]! as String
println(status)
let message = jsonResult ["message"]! as String
println(message)
})
Hope this helps.. :)
Try it
var jsonText = //your json text
var data : Dictionary<NSObject, NSObject> =
NSJSONSerialization.JSONObjectWithData(text.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!, options: nil, error: nil)