0

I am parsing some data from Json and saved into the coredata,after fetching core data showing into the tableview working fine, tableview is show all the value in repeatedly how can avoid the repeated values I tried many ways but not find way

Json format

{
    "contacts": [
        {
                "id": "c200",
                "name": "Ravi Tamada",
                "email": "ravi@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c201",
                "name": "Johnny Depp",
                "email": "johnny_depp@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c202",
                "name": "Leonardo Dicaprio",
                "email": "leonardo_dicaprio@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        }
  ]
}

enter image description here when I fetching "name" showing repeated values

enter image description here

these are save and fetch code

func getfetchdata()
{

    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Contacts")


    do{
        let fetchResults = try self.context.fetch(fetchRequest) as? [Contacts]
    if fetchResults!.count > 0 {

        for bEntity in fetchResults! {

            let employeeEntity =  bEntity

            print(employeeEntity.name as Any)

            TableviewData.append(ContactsDataVal.init(name: employeeEntity.name!,
                                                      id: employeeEntity.id!, email: employeeEntity.email!, gender: employeeEntity.gender!, address: employeeEntity.address!))

        }

      print("data values already")

        }}
    catch let error as NSError
    {
        print(error)
    }
}
func getdata()
{

    let url = URL(string: "https://api.androidhive.info/contacts/")

    URLSession.shared.dataTask(with: url!) { (Data, response, error) in
       do
        {
            let data = try JSONSerialization.jsonObject(with: Data!, options: JSONSerialization.ReadingOptions.allowFragments)as! [String:AnyObject]

            let arraydata = data["contacts"]as! [[String:Any]]


            for arravalues in arraydata
            {

                let entityDescription = NSEntityDescription.entity(forEntityName: "Contacts", in:self.context)

                let favouriteObj = Contacts(entity: entityDescription!, insertInto: self.context)

                favouriteObj.name = arravalues["name"] as? String

                favouriteObj.id = arravalues["id"] as? String

                favouriteObj.email = arravalues["email"] as? String

                favouriteObj.gender = arravalues["gender"] as? String

                favouriteObj.address = arravalues["address"] as? String

                do {
                    try self.context.save()
                }

            }

        }catch let error as NSError{

            print("error",error)
        }
    }
        .resume()
  }

how to avoid repeated values in core data and show proper data into the tableview

rmaddy
  • 314,917
  • 42
  • 532
  • 579
naga
  • 397
  • 2
  • 12
  • 26
  • Probably you should check the same json is stored in database multiple times, that's why you'll get duplicate entries. You should clear existing records prior to insert data into database. – rushisangani Mar 09 '18 at 17:12
  • Do you want to avoid inserting duplicates into your store or do you want to avoid duplicates when reading from the store? – Joakim Danielson Mar 09 '18 at 17:12
  • @JoakimDanielson I want avoid duplicate when read from store – naga Mar 09 '18 at 17:15

2 Answers2

2

First of all in getdata do not save the context in each iteration of the loop, save it once after the loop.

To avoid duplicates fetch all contacts from Core Data, map them to the names and check if the array contains the received name

func getdata()
{

    let url = URL(string: "https://api.androidhive.info/contacts/")
    let names : [String]
    do {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Contacts")
        let fetchResults = try self.context.fetch(fetchRequest)
        names = fetchResults.map{ $0.name }
    } catch {
        names = []
    }

    URLSession.shared.dataTask(with: url!) { (data, response, error) in
        if error != nil { print(error!); return }
        do {
            let data = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
            let arraydata = data["contacts"] as! [[String:Any]]
            for arravalues in arraydata
            {
                guard let name = arravalues["name"] as? String, !names.contains(name) else { continue }
                let entityDescription = NSEntityDescription.entity(forEntityName: "Contacts", in:self.context)
                let favouriteObj = Contacts(entity: entityDescription!, insertInto: self.context)
                favouriteObj.name = name
                favouriteObj.id = arravalues["id"] as? String
                favouriteObj.email = arravalues["email"] as? String
                favouriteObj.gender = arravalues["gender"] as? String
                favouriteObj.address = arravalues["address"] as? String
            }
            try self.context.save()
        } catch {
            print("error",error)
        }
    }
    .resume()
}

Notes:

  • A Core Data fetch with generic fetch request returns always a non-optional array of the NSManagedObject subclass which is specified as generic type on success.
  • Never check for empty array with foo.count > 0, use !foo.isEmpty
  • A JSON dictionary in Swift 3+ is always [String:Any] rather than [String:AnyObject]
  • Handle a potential error in the dataTask completion block.
  • Name the first parameter in the completion block lowercased (data) to avoid a confusion with the type Data.
  • Omit the options parameter in jsonObject(with as the result is clearly a collection type.
vadian
  • 274,689
  • 30
  • 353
  • 361
  • Your Notes piqued my curiosity: Apple docs do state that you should use .isEmpty because .count does extra work for collections that don't conform to RandomAccessCollection. However, Array does actually conform to RandomAccessCollection. So I do agree with you, but I suspect that for Array it is ok (for now) to check .count. – ghostatron Mar 10 '18 at 00:26
0

Maybe there is something that can be done to the fetch request similar to How to get distinct results from a single field in Core Data (Swift 4) but another option would be to remove the duplicates by simply creating a set from the fetch result:

let fetchSet = Set(fetchResults)

and iterate over the set instead

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52