Доступ ко 2-му уровню массива в объекте Array NSDictionary - PullRequest
0 голосов
/ 18 сентября 2018

Я пробую 2-й уровень массива в объекте-массиве NSDictionary, но он возвращает nil

Сначала я определил NSDictionary, а затем получил доступ к 1-му уровню массива, и теперь все хорошо.

let dict = JSON(responseObject as! NSDictionary)
let arrayData = dict["data"].arrayObject! as NSArray
print("arrayData", arrayData)

При печати arrayData я получаю следующее возвращение

data =     (
{
categories = (
    {
    categories = "<null>";
    "category_id" = 333;
    image = "https://www.example.com/images/1.jpg";
    name = "Sub Category One";
    "parent_id" = 1000;
    },
    {
    categories = "<null>";
    "category_id" = 444;
    image = "https://www.example.com/images/2.jpg";
    name = "Sub Category Two";
    "parent_id" = 1000;
    },
    {
    categories = "<null>";
    "category_id" = 555;
    image = "https://www.example.com/images/3.jpg";
    name = "Sub Category Three";
    "parent_id" = 1000;
    }
);//end of categories array
"category_id" = 1000;
image = "https://www.examples.com/images/category.jpg";
name = "Parent Category";
"parent_id" = 0;
},
)

Теперь я пытаюсь получить доступ и напечатать categories из указанного выше возвращенного массива

Итак, я попробовал следующее:

if dict["categories"].arrayObject != nil{
  let arrayData2 = dict["categories"].arrayObject! as NSArray
  print("arrayData2", arrayData2)
}

Я также попробовал это как

if dict["data"]["categories"].arrayObject != nil{
  let arrayData2 = dict["data"]["categories"].arrayObject! as NSArray
  print("arrayData2", arrayData2)
}

В обоих случаях я получаю значение nil , в то время как оно должно получитьреальные значения.

РЕДАКТИРОВАНИЕ: добавлен вызов API в ViewController и структура dataModel

Функция CallHTTPAPI в View Controller

func callingHttppApi(){
  DispatchQueue.main.async{
    NetworkManager.sharedInstance.showLoader()
    let sessionId = self.defaults.object(forKey:"token");
    self.categoriesTableView.isUserInteractionEnabled = false

      var requstParams = [String:Any]();
      requstParams["token"] = sessionId
      NetworkManager.sharedInstance.callingHttpRequest(params:requstParams, apiname:"api/cat", cuurentView: self){success,responseObject in
        if success == 1{
          let dict = responseObject as! NSDictionary;
          if dict.object(forKey: "fault") != nil{
            let fault = dict.object(forKey: "fault") as! Bool;
            if fault == true{
              self.loginRequest()
            }
          }else{
            NetworkManager.sharedInstance.dismissLoader()
            self.view.isUserInteractionEnabled = true
            self.categoriesTableView.isUserInteractionEnabled = true
            let dict = JSON(responseObject as! NSDictionary)
            let arrayData = dict["data"].arrayObject! as NSArray
            if dict["categories"].arrayObject != nil{
              let arrayData2 = dict["categories"].arrayObject! as NSArray
              print("arrayData2", arrayData2)
            }
            print("arrayData", arrayData)
            if dict["error"].intValue == 1{
              NetworkManager.sharedInstance.showErrorMessageWithBack(view: self, message: NetworkManager.sharedInstance.language(key: "error"))
            }else{
              self.categoriesCollModel = CategoriesViewModel(data:JSON(responseObject as! NSDictionary))
              dump (self.categoriesCollModel)
            }
          }
        }else if success == 2{
          NetworkManager.sharedInstance.dismissLoader()
          self.callingHttppApi()
        }
      }
    }
  }

Модель данныхструктура для приведения значений

//
//  CategoriesViewModel.swift
//

import Foundation

class Categories: NSObject{
    var id:String = ""
    var name:String = ""
    var image:String = ""

    init(data:JSON){
        self.id = data["category_id"].stringValue
        self.name  = data["name"].stringValue
        self.image = data["image"].stringValue
    }

}

class SubCategories:NSObject{
    var pid:String = ""
    var id:String = ""
    var name:String = ""
    var image:String = ""

    init(data:JSON) {
        self.pid = data["parent_id"].stringValue
        self.id = data["category_id"].stringValue
        self.name  = data["name"].stringValue
        self.image = data["image"].stringValue
    }

}

struct Categories_Data{
    var id:String = ""
    var categoriesArray = [SubCategories]()

    init(data:JSON) {
        self.id = data["category_id"].stringValue
        if let arrayData = data["data"]["categories"].arrayObject {
            categoriesArray =  arrayData.map({(value) -> SubCategories in
                return  SubCategories(data:JSON(value))
            })
        }
    }

}

class CategoriesViewModel:NSObject{
    var categoryModel = [Categories]()
    var subCategories = [SubCategories]()
  var categories_Data = [Categories_Data]()

    init(data:JSON) {

        let arrayData = data["data"].arrayObject! as NSArray
        categoryModel =  arrayData.map({(value) -> Categories in
            return  Categories(data:JSON(value))
        })

        if data["data"]["categories"].arrayObject != nil{
            let arrayData2 = data["data"]["categories"].arrayObject! as NSArray
            categories_Data =  arrayData2.map({(value) -> Categories_Data in
                return  Categories_Data(data:JSON(value))
            })
        }

        //categoryModel = Categories(data:data)


    }

    var getCategories:Array<Categories>{
        return categoryModel
    }

  var getSubCategories:Array<SubCategories>{
        return subCategories
    }

}

Ответы [ 5 ]

0 голосов
/ 18 сентября 2018

Я настоятельно рекомендую сбросить SwiftyJSON и использовать Decodable.

. CategoriesViewModel можно уменьшить до

struct Root: Decodable {
    let data : [Category]
}

struct Category: Decodable {
    let categories : [Category]?
    let categoryId : Int
    let image : URL
    let name : String
    let parentId : Int
}

. Вам необходимо получить необработанные данные из сети.запрос (в следующем коде с именем data), тогда вы можете просто декодировать данные в структуры и получить значения с точечной нотацией.

Я добавил вспомогательную функцию, чтобы иметь возможность рекурсивно печатать вложенные категории

do {
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let result = try decoder.decode(Root.self, from: data)
    printCategories(result.data)
} catch { print(error) }

func printCategories(_ categories : [Category]) {
    for item in categories {
        if let subCategories = item.categories {
            printCategories(subCategories)
        }
        print(item.name, item.categoryId)
    }
}
0 голосов
/ 18 сентября 2018

Ну, сначала поймите ответ print("arrayData", arrayData).Это array из Dictionaries.

При добавлении:

let arrayData = dict["data"].arrayObject! as NSArray

вы сохраняете данные в массиве из dictionary.

Теперь, чтобы выбрать категории, которые вы должны использовать arrayData:

let firstDict = arrayData[0] as! [String:Any]
let arrayData2 = firstDict["categories"] as! [[String:Any]]
print("arrayData2", arrayData2)

Я добавил этот код, чтобы показать одну информацию.

Дополнительные данные вы можете использовать для цикла:

for dictData in arrayData {
    let arrayData2 = dictData["categories"] as! [[String:Any]]
    print("arrayData2", arrayData2)
}

, и с помощью этого цикла вы можетеуправляйте или сохраняйте соответствующие данные.

Еще одна вещь, не забудьте добавить ноль обрабатывающей части.

Еще одна вещь, работая при работе со swift, не используйте NSArray или NSDictionary.

Попробуйте использовать Codable.В интернете есть множество примеров, которые сделают ваш код немного чистым.

0 голосов
/ 18 сентября 2018

Это выглядит довольно сложно, но это очень просто, просто следуйте иерархии

скажем, например, что вы хотите достичь "данные -> категории -> имя", так как в своем ответе вы можете пойти так:

это ваш главный словарь, в котором есть все.

if let dict = responceObject as? NSDictionary {
// now lets say you want go to your categories which is array of dictionaries

  if let arrDict = dict["categories"] as? NSArray {
      print("arrDict")

      // Now you can go anywhere in that array of dictionaries
      // For example you want to get name you can do like this

      for obj in arrDict {
         if let name = obj["name"] as? String {
            print(name)
         }
      }
  }
}

Я добавляю редактировать часть здесь

// In your webcall lets say you receive a JSON(i am naming it as "json") object with type Any
if let jsonObj = json as? [String: Any], let mainDict = jsonObj["data"] as? [[String: Any]] {
    for arr in mainDict {
       if let arrDict = arr["categories"] as? [[String: Any]] {
           print(arrDict)
           // Now you can dig that dict which is array of dictionaries
           for obj in arrDict {
              if let name = obj["name"] as? String {
                 print(name)
              }

              if let id = obj["id"] as? Int { // Int or whatever it is
                 print(id)  
              } 
           }
       }
    }
}

Надеюсь, это сработает.

0 голосов
/ 18 сентября 2018

Вы также должны использовать guard для проверки значений при инициализации объектов модели:

init(data: JSON) {
    guard
        let id = data["category_id"] as? Int,
        let name = data["name"] as? String,
        let image = data["image"] as? String
        else {
             return
        }
    self.id = id
    self.name  = name
    self.image = image
}

Обратите внимание, что id - это целочисленное значение, а НЕ строка, поэтому вам следует сменить модель.

Также проверьте Кодируемый .

0 голосов
/ 18 сентября 2018

Вы получаете объекты в неправильном порядке. Всегда получать объект или значение с проверкой nil value ...
Проверьте ниже код, чтобы получить ваши категории.

let dict = JSON(responseObject as! NSDictionary)
    if let data = dict["data"] as? Array<Any>
    {
        if let categoryArray = data["categories"] as? Array<Dictionary<String,Any>>
        {
            if categoryArray.count > 0
            {
                print(categoryArray)
            }
        }
    }
...