Segmentation Fault while reading JSON parse to NSArray in swift - ios

There is a method used to fill realm database from json:
func parseJSON(data: NSData) -> NSArray? {
do {
let array: NSArray = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as! NSArray
return array
} catch _ {
return nil
}
}
//parameter came from previous method
func updateDatabaseFromParsedJson(parsedJson: NSArray) {
let realm = try! Realm()
try! realm.write {
realm.deleteAll()
}
for i in 0..<parsedJson.count {
let deviceObject = parsedJson[i]
let name = deviceObject["name"] as! String
let id = deviceObject["id"] as! Int
var device = Device()
device.name = name
device.id = id
try! realm.write {
realm.add(device)
}
var deviceMeasuresArray = deviceObject["measures"] as! NSArray
for i in 0..<deviceMeasuresArray.count {
var measureObject = deviceMeasuresArray[i]
var measure = Measure()
measure.slug = measureObject["name"]
measure.device = device
measure.localize()
try! realm.write {
realm.add(measure)
}
var measureEntriesArray = measureObject["averages"] as! NSArray
for i in 0..<measureEntriesArray.count {
var entryObject = measureEntriesArray[i]
var entry = PeriodAverage()
entry.measure = measure
entry.value = entryObject["value"]
entry.start = NSDate.parse(entryObject["start"])
entry.end = NSDate.parse(entryObject["end"])
entry.length = entryObject["length"]
try! realm.write {
realm.add(entry)
}
}
}
}
}
extension NSDate {
class func parse(dateString: String) -> NSDate {
let format = "yyyy-MM-dd'T'HH:mm:ss'Z'"
let formatter = NSDateFormatter()
formatter.dateFormat = format
return formatter.dateFromString(dateString)!
}
}
JSON itself http://188.166.51.200/api/v1/actual_data/
While compiling I get error Error:unable to execute command: Segmentation fault: 11
Where I am wrong and how to properly parse my json? I think problem is in lines where json fields forcely parsed to objects but I am new in swift and can't exactly determine the error.

You've apparently run across a compiler issue (which you should report to Apple), although it's easy enough to work around. If you're using Swift you should really be using Swift collection types instead Foundation collection types if possible (i.e., Array instead of NSArray) which allow for more type information. Also, while you're casting some of the values you're getting out of your JSON, you're not casting them all. Adding this additional type information will make the compiler behave and work around the issue. I would suggest the following edit:
func updateDatabaseFromParsedJson(parsedJson: Array<AnyObject>) {
let realm = try! Realm()
try! realm.write {
realm.deleteAll()
}
for i in 0..<parsedJson.count {
let deviceObject = parsedJson[i] as! Dictionary<String, AnyObject>
let name = deviceObject["name"] as! String
let id = deviceObject["id"] as! Int
var device = Device()
device.name = name
device.id = id
try! realm.write {
realm.add(device)
}
var deviceMeasuresArray = deviceObject["measures"] as! Array<AnyObject>
for i in 0..<deviceMeasuresArray.count {
var measureObject = deviceMeasuresArray[i] as! Dictionary<String, AnyObject>
var measure = Measure()
measure.slug = measureObject["name"] as! String // I'm guessing on the type here
measure.device = device
measure.localize()
try! realm.write {
realm.add(measure)
}
var measureEntriesArray = measureObject["averages"] as! Array<AnyObject>
for i in 0..<measureEntriesArray.count {
var entryObject = measureEntriesArray[i] as! Dictionary<String, AnyObject>
var entry = PeriodAverage()
entry.measure = measure
entry.value = entryObject["value"] as! String // Guessing on the type here also
entry.start = NSDate.parse(entryObject["start"] as! String)
entry.end = NSDate.parse(entryObject["end"] as! String)
entry.length = entryObject["length"] as! String // Again, guessing on the type here
try! realm.write {
realm.add(entry)
}
}
}
}
}
Unrelated to the compiler issue, you could also use for-in loops to make your code more Swift like. You can read more about them in the For-In Loops section of the Control Flow chapter of The Swift Programming Language.

Related

Get JSON value to Array

I need to get the JSON value from MYSQL and display it in the table view. I have done PHP part to receive data but I have error with my XCODE. My data will store temperature, humidity and digital status (on off) of sensor. I have questions below:
How to get ON/OFF JSON value and store in Bool array?
How to get JSON value and store in Float array?
if JSON value is , how can I store value as 0 in XCODE?
class DataManager {
var nodenameArray: [String] = []
var nodeidArray: [String] = []
var tempArray: [Float] = []
var humArray: [Float] = []
var pirArray: [Bool] = []
var lightArray: [Bool] = []
var relayArray: [Bool] = []
var hallArray: [Bool] = []
var smokeArray: [Bool] = []
#objc func taskdo() {
self.nodenameArray = []
self.nodeidArray = []
self.tempArray = []
self.humArray = []
self.pirArray = []
self.lightArray = []
self.relayArray = []
self.hallArray = []
self.smokeArray = []
if userlogin == true {
let request = NSMutableURLRequest(url: NSURL(string: http://talectric.com/wp-admin/a_p/iot/read_all.php")! as URL)
request.httpMethod = "POST"
let postString = "username=\(username)&password=\(password)&authen=wdwfesf9329140dsvfxkciospdkm"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error!)")
return
} else {
do {
if let respondString = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
print(respondString)
if let nodedata = respondString.value(forKey: "nodedata") as? NSArray {
for node in nodedata{
if let nodeDict = node as? NSDictionary {
if let nodeid = nodeDict.value(forKey: "node_id") {
self.nodeidArray.insert(nodeid as! String, at: 0)
}
if let nodeid = nodeDict.value(forKey: "node_name") {
self.nodenameArray.insert(nodeid as! String, at: 0)
}
if let nodeid = nodeDict.value(forKey: "temp") {
self.tempArray.insert(Float(nodeid as! String)!, at: 0)
}
if let nodeid = nodeDict.value(forKey: "hum") {
print(nodeid)
self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)
}
}
}
}
}
print(self.nodenameArray)
print(self.nodeidArray)
print(self.tempArray)
print(self.humArray)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
}
catch let error as NSError {
print(error.debugDescription)
}
}
}
task.resume()
}
}
}
below is the respond:
{
nodedata = (
{
"hall_status" = "<null>";
hum = 111;
"light_status" = "<null>";
"node_id" = y2cfwecrw3hqznuxmfvf;
"node_name" = SVIN03;
"pir_status" = OFF;
"relay_status" = "<null>";
"smoke_status" = "<null>";
temp = 2132;
},
{
"node_name" = SVIN04;
nodeid = aj2w1aljw8nd65ax79dm;
},
{
"hall_status" = "<null>";
hum = 100;
"light_status" = "<null>";
"node_id" = mwmfl2og2l8888fjpj2d;
"node_name" = SVIN05;
"pir_status" = ON;
"relay_status" = "<null>";
"smoke_status" = "<null>";
temp = 45;
}
);
numberofnodeid = 3;
}
111
100
Could not cast value of type '__NSCFNumber' (0x10db6f878) to 'NSString' (0x10ca71568).
2018-10-11 08:11:05.352491+0700 IOT 2[1506:101847] Could not cast value of type '__NSCFNumber' (0x10db6f878) to 'NSString' (0x10ca71568).
error is in this line :
self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)
First of all, you have to look at json_decode to read data from json in php
Example:
`$json = '{"foo-bar": 12345}';
$obj = json_decode($json);
print $obj->{'foo-bar'}; // this will print 12345`
How to get ON/OFF JSON value and store in Bool array ?
basically you have to add a new value to your onOff variable, something like
$onOff=array();
$val;
$obj = json_decode($json);
if (is_null($obj->{'name_of_the_alert'})) {
$val = 0
} else {
$val = $obj->{'name_of_the_alert'};
}
array_push($onOff,$obj->{'name_of_the_alert'});
How to get JSON value and store in Float array ?
Basically same thing, I haven't use PHP in a while, but just declare the array of the value type you need.
if JSON value is , how can i store value as 0 in XCODE ?
I guess you mean if it is null, in this case you have to do this
$onOff=array();
$val;
$obj = json_decode($json);
if (is_null($obj->{'name_of_the_alert'})) {
$val = 0
} else {
$val = $obj->{'name_of_the_alert'};
}
array_push($onOff,$obj->{'name_of_the_alert'});
Take into consideration that I may have some mistakes here because I am not familiar with newer PHP versions.
Good luck
From your question, it is clear that temp and hum are Number type(Int of Double). So use NSNumber rather than NSString as:
self.humArray.insert(Float(Int(nodeid as! NSNumber)!), at: 0)
As more swifty approach, you can update your code as:
if let nodeDict = node as? [String: Any] {
if let nodeid = nodeDict["node_id"] as? String {
self.nodeidArray.insert(nodeid, at: 0)
}
if let nodename = nodeDict["node_name"] as? String {
self.nodenameArray.insert(nodename, at: 0)
}
if let temp = nodeDict["temp"] as? Int {
self.tempArray.insert(Float(temp), at: 0)
}
if let hum = nodeDict["hum"] as? Int {
self.humArray.insert(Float(hum), at: 0)
}
}
There is plenty of issues with your code:
First, avoid using NSStuff in Swift3+ when there is the equivalent.
let request = NSMutableURLRequest(url: NSURL(string: http://talectric.com/wp-admin/a_p/iot/read_all.php")! as URL)
...
let task = URLSession.shared.dataTask(with: request as URLRequest) {
=>
let request = URLRequest(url: URL(string: http://talectric.com/wp-admin/a_p/iot/read_all.php")!)
...
let task = URLSession.shared.dataTask(with: request) {
See, you avoid already all the as URL, as URLRequest.
Avoid force unwrapping: Avoid using !.
Because if it's nil or with as! the cast fails (and then it's nil), you'll get a crash.
Use if let, guard let. Read this about Optional
As a sample, I would have wrote:
guard let url = URL(string:http...) else {
print("invalid URL")
return
}
let request = URLRequest(url: url)
Parsing part:
if let respondString = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
Get rid of NSDictionary, use [String: Any] instead, then get rid of .allowFragments, it's rarely useful (it makes sense on certains cases only) don't use the force unwrap on data!, and don't name your variable respondString
because that's clearly not a String and that's clearly misleading.
=>
guard let data = data else { return }
if let responseDict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
Now:
if let nodedata = respondString.value(forKey: "nodedata") as? NSArray {
for node in nodedata{
if let nodeDict = node as? NSDictionary {
if let nodeid = nodeDict.value(forKey: "node_id") {
self.nodeidArray.insert(nodeid as! String, at: 0)
}
if let nodeid = nodeDict.value(forKey: "node_name") {
self.nodenameArray.insert(nodeid as! String, at: 0)
}
if let nodeid = nodeDict.value(forKey: "temp") {
self.tempArray.insert(Float(nodeid as! String)!, at: 0)
}
if let nodeid = nodeDict.value(forKey: "hum") {
print(nodeid)
self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)
}
}
}
}
No, no NSArray, no NSDictionary, avoid using value(forKey:) because it does what you think it does on a NSDictionary doing a object(forKey:), or simply subscript (using ["someKey"]) but on an Array you'll get an issue with an unexpected result I think.
Don't name all your var nodeid, it's harder to debug after ward, don't do a soft unwrap (if let) if just afterward you do a force unwrap on that value.
if let nodedata = responseDict["nodedata"] as? [[String: Any]] {
for aNode in nodedata {
if let id = aNode["node_id"] as? String {
self.nodeidArray.insert(nodeId, at: 0)
}
if let name = aNode["node_name"] as? String {
self.nodenameArray.insert(name, at: 0)
}
if let temp = aNode["temp"] as? String, let tempFloat = Float(temp) {
self.tempArray.insert(tempFloat, at: 0)
}
if let hum = aNode["hum"] as? String, let humFloat = Float(hum) {
self.humArray.insert(humFloat, at: 0)
}
}
}
That's much more readable.
Now instead of using insert(_:at:), it might be easier to use nodedata.inverted().
Now, let's talk about architecture:
What happens in your case, if you don't pass the if let hum = aNode["hum"] as? String, let humFloat = Float(hum) { on one iteration (let's say the second one which is exactly your case in the sample you gave there is no temp) but success on all the others?
Here what's going to happen:
self.nodeidArray[3] and self.humArray[3] won't be correct, they'll be desynchronized, right?
Because self.nodeidArray[2] should be with self.humArray[1].
Theses values are meant to be synce'd, so use a custom Struct/Class for it:
After all, Swift is a OOP (Object Oriented Programming) language, so use objects.
struct Node {
let id: String?
let name: String?
let humidity: Float?
let temperature: Float?
}
So instead of having:
var nodenameArray: [String] = []
var nodeidArray: [String] = []
var tempArray: [Float] = []
var humArray: [Float] = []
Just have:
var nodes: [Node] = []
And during the parsing, do
let node = Node.init(withDict: aNode)
nodes.append(node) //or insert it at 0
You can construct your own method init in Node, let's say:
func init(withDict dict: [String: Any]) {
if let id = dict["node_id"] as? String {
self.id = id
}
etc.
}
Having this Node class simplify. But using the JSONSerialization and init all the values manually could be avoided using Codable (available in Swift 4).
Side Note:
This code is not tested, there might be some glitch, typo etc. Let's focus on the explanation instead.
Lastly concerning the error:
Could not cast value of type '__NSCFNumber' (0x10db6f878) to
'NSString' (0x10ca71568). 2018-10-11 08:11:05.352491+0700 IOT
2[1506:101847] Could not cast value of type '__NSCFNumber'
(0x10db6f878) to 'NSString' (0x10ca71568).
error is in this line :
self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)
The error means that at some point you tried to cas (using as) on a a (NS)String, but is was in fact NSNumber (in Swift, it's easily converted into an Int/Float, etc.), so it failed.
So the part that failed: nodeid as! String, because nodeid is not a (NS)String

Working with Realm and result JSON

I am new to realm and I am trying to use Realm in my project. Here I am trying to parse JSON and save it using realm. When I am trying to loop through the result array error occurs
'Attempting to modify object outside of a write transaction - call beginwritetransaction on an RLMRealm instance first'
This is the JSON result:
{"data":[{"id":1,"parent_id":0,"name":"JenniferMaenle","title":"Ms","phone":"","address":"Toled, ohio","email":"jlmaenle#aol.com","image":"44381525_2017.jpg","relation_id":5,"created_at":null,"updated_at":"2017-08-10 02:30:05"},{"id":2, "parent_id":1,"name":"Khadeeja","title":"","phone":"","address":"","email":"","image":"Khadeeja_2017-07-17.jpg","relation_id":2,"created_at":null,"updated_at":"2017-07-17 08:3:12"}]}
I am trying to parse JSON and save it in the Realm database. Here is my try:
class Person: Object {
dynamic var name = ""
dynamic var title = ""
dynamic var address = ""
}
override func viewDidLoad() {
super.viewDidLoad()
self.add()
}
func add(){
guard let data = dataFromFile("ServerData") else { return }
let persons = Person()
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: AnyObject] {
if let data = json["data"] as? [[String:AnyObject]]{
for eachItem in data{
persons.name = eachItem["name"] as! String
persons.title = eachItem["title"] as! String
persons.address = eachItem["address"] as! String
try! realm.write {
realm.add(persons)
}
}
}
}
} catch {
print("Error deserializing JSON: \(error)")
}
}
Do not modify the persons object and add it to the realm again. The error you see is because you add persons to the realm and then edit it on the second iteration in the for eachItem in data again. Persons is already added to the realm in this iteration and you try to give it a new name outside a realm write transaction. That's why you see the error. It's better to create a new object for every person.
func add(){
guard let data = dataFromFile("ServerData") else { return }
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: AnyObject] {
if let data = json["data"] as? [[String:AnyObject]]{
for eachItem in data{
let persons = Person()
persons.name = eachItem["name"] as! String
persons.title = eachItem["title"] as! String
persons.address = eachItem["address"] as! String
try! realm.write {
realm.add(persons)
}
}
}
}
} catch {
print("Error deserializing JSON: \(error)")
}
}
As the error indicates, you need to preform the transaction inside a write,
One option is to write each person individually:
for eachItem in data{
let person = Person()
person.name = eachItem["name"] as! String
person.title = eachItem["title"] as! String
person.address = eachItem["address"] as! String
try! realm.write {
realm.add(person)
}
}
Second option is to build an object and then write:
for eachItem in data{
let person = Person();
person.name = eachItem["name"] as! String
person.title = eachItem["title"] as! String
person.address = eachItem["address"] as! String
persons.add(person)
}
try! realm.write {
realm. append(persons)
}
You might need to make few changes to this, but this is the idea.

Cannot instantiate function Could not cast value of type '__NSArrayI'

I have made the following function in Swift 3:
func parseJSON() {
var JsonResult: NSMutableArray = NSMutableArray()
do {
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
} catch let error as NSError {
print(error)
}
var jsonElement:NSDictionary=NSDictionary()
let locations: NSMutableArray = NSMutableArray()
for i in 0 ..< JsonResult.count
{
jsonElement = JsonResult[i] as! NSDictionary
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.add(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
When i call this function from another method, i get the following error:
Could not cast value of type '__NSArrayI' (0x105d4fc08) to 'NSMutableArray' (0x105d4fcd0).
It points me towards the element here:
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
Where it exits with a SIGBRT..
What have i missed here?
You are trying to convert an NSArray into an NSMutable array which is what the warning is complaining about.
Take the array it provides you, and then convert it into a mutable one.
let jsonArray = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
jsonResult = jsonArray.mutableCopy() as! NSMutableArray
Unrelated, but you may also want to user a lower case value for the JsonResult to fit with normal iOS style guidelines. It should instead be jsonResult.
Another way to improve your code:
You are not mutating your JsonResult, so you have no need to declare it as NSMutableArray:
var JsonResult = NSArray()
do {
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
}
And some steps to improve your code...
enum MyError: Error {
case NotArrayOfDict
}
func parseJSON() {
do {
guard let jsonResult = try JSONSerialization.jsonObject(with: self.data as Data) as? [[String: Any]] else {
throw MyError.NotArrayOfDict
}
let locations: NSMutableArray = NSMutableArray()
for jsonElement in jsonResult {
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.add(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
} catch let error {
print(error)
}
}
as! casting sometimes crashes your app, use it only when you are 100%-sure that the result is safely converted to the type. If you are not, using guard-let with as? is safer.
Use Swift types rather than NSSomething as far as you can.
Specifying .allowFragments is not needed, as you expect the result as an Array.
And if you can modify some other parts of your code, you can write your code as:
func parseJSON() {
do {
//If `self.data` was declared as `Data`, you would have no need to use `as Data`.
guard let jsonResult = try JSONSerialization.jsonObject(with: self.data) as? [[String: Any]] else {
throw MyError.NotArrayOfDict
}
var locations: [Parsexml] = [] //<-Use Swift Array
for jsonElement in jsonResult {
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.append(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
} catch let error {
print(error)
}
}

Ambiguous use of subscript. Array Swift IOS

I try to compile on device but i get this error. Any help?. In the simulator works perfectly.
I get an ambiguous use of subscript error in the following code and was hoping somebody else has encountered this and know the fix.
case .Success:
if response.response?.statusCode == 200 {
print ("Respuesta 200")
if let value = response.result.value {
let respuestaJSON = JSON(value)
let objsonUSUARIOS = respuestaJSON["d"].object
let arrayUsuarios = objsonUSUARIOS["results"]!
//print ("Usuarios: ",String(arrayUsuarios))
for i in 0 ..< arrayUsuarios!.count{
let boletines = boletinJSON()
if let item = arrayUsuarios![i] as? [String: AnyObject]{
)
if let person = item["Title"] as? String
{
boletines.name = person
}
if let person = item["Portada"] as? String
{
boletines.imagen = person
}
if let person = item["Created"] as? String
{
boletines.fecha = person
}
if let person = item["AttachmentFiles"] as? [String: AnyObject] {
if let itemAttach = person["__deferred"] as? [String: AnyObject]{
if let itemdeferred = itemAttach["uri"] as? String {
boletines.urldescarga = itemdeferred
}
}
}
self.boletin.append(boletines)
self.view.hideToastActivity()
}
}
}
self.tableView.reloadData()
// self.view.hideToastActivity()
}
Inform the compiler what the intermediary object objsonUSUARIOS is of type
let objsonUSUARIOS = respuestaJSON["d"].object
After the above statement, the compiler does not know what kind of object he is dealing with. So make sure that you can actually do all the casting as below
let objsonUSUARIOS = respuestaJSON["d"].object as! Dictionary
let arrayUsuarios = objsonUSUARIOS["results"]! as! Array
The problem is that you have not specified the type of object arrayUsuarios is Array, so try to explicit type cast the arrayUsuarios Array
let arrayUsuarios = objsonUSUARIOS["results"] as! [[String: AnyObject]]

Json parsing in iOS playground do method is not parsing

I am trying to parse some json data into three different arrays based off the label in the json. I seem to be stuck and don't know why my for loop is never being entered. I am new to iOS and am using this to learn swift. Any help will be appreciated.
Here is the code that I am using:
var myPicture = [String]()
var myPath = [String]()
var mylabel = [String]()
let jsonString = "[{\"picture\" : \"Picture 1 \", \"path\": \"Path 1\" , \"label\" : \"Label 1\"}]"
//Convert jsonString to NSData
let myData = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
do{
let promoJson = try NSJSONSerialization.JSONObjectWithData(myData, options:.AllowFragments)
if let promtions = promoJson[""] as? [[String: AnyObject]] {
for promtions in promtions {
if let picture = promtions["picture"] as? String
{
myPicture.append(picture)
if let path = promtions["path"] as? String
{
myPath.append(path)
if let label = promtions["label"] as? String
{
mylabel.append(label)
}
}
}
}
}
}catch {
print("Error with Json: \(error)")
}
print(myPicture.first)
print(myPath.first)
print(mylabel.first)
The results for the print are all nil. So nothing is being appended to the arrays
The if let promtions = promoJson[""] part won't work and would be useless anyway. This is only promoJson that you have to cast to an array of dictionaries.
You weren't that far from the solution, look at my working version of your code:
do {
let promoJson = try NSJSONSerialization.JSONObjectWithData(myData, options: [])
if let promtions = promoJson as? [[String: AnyObject]] {
for promtion in promtions {
if let picture = promtion["picture"] as? String {
myPicture.append(picture)
}
if let path = promtion["path"] as? String {
myPath.append(path)
}
if let label = promtion["label"] as? String {
mylabel.append(label)
}
}
}
} catch let error as NSError {
print(error.debugDescription)
}
Alternative
Now that the issue is resolved, let me suggest you another way: instead of separate arrays for your data, use one array of objects holding your data.
For example, make a struct like this:
struct Promotion {
let picture: String
let path: String
let label: String
}
And an array for instances of this struct:
var myPromotions = [Promotion]()
Now we can decode the JSON, create objects from it then store them in the array:
do {
let promoJson = try NSJSONSerialization.JSONObjectWithData(myData, options: [])
if let promtions = promoJson as? [[String: AnyObject]] {
for promtion in promtions {
if let picture = promtion["picture"] as? String,
path = promtion["path"] as? String,
label = promtion["label"] as? String {
let promo = Promotion(picture: picture, path: path, label: label)
myPromotions.append(promo)
}
}
}
} catch let error as NSError {
print(error.debugDescription)
}
Now look at the content of the array, very convenient:
for promo in myPromotions {
print(promo.label)
print(promo.path)
print(promo.picture)
}
When you are converting it is already an array.
import Foundation
import UIKit
var myPicture = [String]()
var myPath = [String]()
var mylabel = [String]()
let jsonString = "[{\"picture\" : \"Picture 1 \", \"path\": \"Path 1\" , \"label\" : \"Label 1\"}]"
//Convert jsonString to NSData
let myData = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
do{
let promoJson = try NSJSONSerialization.JSONObjectWithData(myData, options:.AllowFragments) as! NSArray
for promtions in promoJson {
if let picture = promtions["picture"] as? String
{
myPicture.append(picture)
if let path = promtions["path"] as? String
{
myPath.append(path)
if let label = promtions["label"] as? String
{
mylabel.append(label)
}
}
}
}
}catch
{
print("Error with Json: \(error)")
}
print(myPicture.first) // "Optional("Picture 1 ")\n"
print(myPath.first) // "Optional("Path 1")\n"
print(mylabel.first) // "Optional("Label 1")\n"
This does the job.

Resources