2014-08-15 7 views
7

Podczas gdy łańcuch wydaje się być w porządku, mam problem z przechowywanie liczb całkowitych w danych podstawowych. Podążanie za tutorialami i czytanie dostępnych informacji nie pomaga mi, kto nie ma tła w Objective-C. (Swift wydawał mi się językiem prostym, takim jak języki, w których płynnie posługuję się PHP/OOPHP/JavaScript/VBScript/... w ten sposób zacząłem grać z nim i do tej pory byłem w stanie zrobić wszystko, co chciałem, prawie)Przechowuj liczby całkowite w danych podstawowych za pomocą Swift i XCode

Co chcę zrobić to teraz, aby otrzymać dane JSON i przechowywać go w danych Core

Oto moje podstawowe dane

Entity name: Category 

jego atrybutów:

id Int16 
title String 
description String 

My Model Swift? file: Category.swift

import CoreData 

class Category: NSManagedObject { 
    @NSManaged var id: Int //should I declare this as Int16? 
    @NSManaged var title: String 
    @NSManaged var description: String 
} 

Używam rozszerzenia SwiftyJASON? i protokół NSURLSession? aby uzyskać dane i analizować je następująco:

import UIKit 
import CoreData 

class ViewController: UIViewController { 

    let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     fetchData() 
    } 
     func fetchData() { 
      var url = NSURL.URLWithString("http://domain.com/index.php?r=appsync/read&id=category") 
      var session = NSURLSession.sharedSession() 
      session.dataTaskWithURL(url, completionHandler: {(data, response, error) in 
       // parse data into json 
       let json = JSONValue(data) 
       let entityDescription = NSEntityDescription.entityForName("Category", inManagedObjectContext: self.managedObjectContext) 
       let category = Category(entity: entityDescription, insertIntoManagedObjectContext: self.managedObjectContext) 
       for item in json.array! { 
        category.id = item["id"].string!.toInt()! //goes KABOOM! 
        category.title = item["title"].string! 
        category.description = item["description"].string! 
        managedObjectContext?.save(nil) 
       } 
       dispatch_async(dispatch_get_main_queue()) { 
        // do something 
       } 
      }).resume() 
     } 
} 

Załóżmy dane Jason:

[{"id":"1","title":"cat1","description":"blabala one"},{"id":"2","title":"cat2","description":"blabala two"}] 

W wierszu, w którym jest napisane category.id = item["id"].string!.toInt()! Xcode idzie Kaboom, co robię źle tutaj?

Uwagi/Inne pytania:

  • Próbuję zmienić typ id ciągu danych Core do Int32, a następnie deklarując je jako tylko Int w modelu (i nie Int16 lub Int32) co zmniejszyło masę błędów, ale Xcode ciągle wywala

  • Prawdopodobnie sposób mam pętli rzeczy nie jest najlepszym sposobem, aby to zrobić, co jest lepszym sposobem przechowywania tablicę danych do danych podstawowych w raz?

  • Większość tutoriali, które widziałem, nie ma identyfikatorów dla Entities (tabele), czy brakuje mi tutaj czegoś?

Referencje:

EDIT> Praca kod:

Category.s wift plik model, który może być automatycznie generowane przy użyciu Plik> Nowy> Plik> iOS> Rdzeń danych> NSManagedObject podklasa [swift, nie ma potrzeby pomostowych nagłówek, ale trzeba ręcznie dodać linię @objc jak poniżej]

import CoreData 

@objc(Category) //Wouldn't work without this 
class Category: NSManagedObject { 
    @NSManaged var id: NSNumber //has to be NSNumber 
    @NSManaged var title: String 
    @NSManaged var mydescription: String //"description" is reserved so is "class" 
} 

ViewController .Swift

import UIKit 
import CoreData 

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     fetchData() 
    } 
    func fetchData() { 
     var url = NSURL.URLWithString("http://domain.com/index.php?r=appsync/read&id=category") 
     var session = NSURLSession.sharedSession() 
     session.dataTaskWithURL(url, completionHandler: {(data, response, error) in 
      let json = JSONValue(data) 
      let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext //this line had to be moved here 
      let entityDescription = NSEntityDescription.entityForName("Category", inManagedObjectContext: managedObjectContext) 
      for item in json.array! { 
       let category = Category(entity: entityDescription, insertIntoManagedObjectContext: managedObjectContext) //this line has to be in inside for loop 
       category.id = item["id"].string!.toInt()! 
       category.title = item["title"].string! 
       category.mydescription = item["description"].string! 
       managedObjectContext?.save(nil) 
      } 
      dispatch_async(dispatch_get_main_queue()) { 
       // do something 
      } 
     }).resume() 
    } 
} 

Przykładowy kod pobierania danych:

func requestData() { 
    let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate 
    let context:NSManagedObjectContext = appDel.managedObjectContext! 
    var request = NSFetchRequest(entityName: "Category") 
    request.returnsObjectsAsFaults = false 
    var results:NSArray = context.executeFetchRequest(request, error: nil) 
    //println(results) 
    for category in results { 
     var cat = category as Category 
     println("\(cat.id),\(cat.title),\(cat.mydescription)") 
    } 
} 

PS: Upewnij się, aby oczyścić swój projekt i usunąć aplikację z symulatora po zmianie modelu

+1

Powinien być numer NSNumber? Lub może zostawić to jako identyfikator zmiennej? AS SWIFT wywnioskuje go z wartości, którą umieścisz? – CW0007007

+0

Otrzymuję błąd "EXC_BAD_ACCESS", gdy robię to w tej samej linii, próbowałem zmienić 'Int' w modelu na' NSNumber', a także 'category.id = element [" id "]. String! .toInt() ! jako NSNumber! 'i inne kombinacje, ten sam wynik. I nie całkiem rozumiem, co masz na myśli przez _leave it as var id_ –

+0

Nie jawnie zadeklarować typu? Nie zrobiłem wiele w szybkim tempie. Tak więc nie wiem, czy EntityModel będzie działał bez wyraźnego typu. Więc zmień na: @NSManaged var id – CW0007007

Odpowiedz

6

Typy skalarne (liczby całkowite, zmienne, booleany) w danych podstawowych są rozbijane w bieżącej wersji beta Swift (5). Użyj NSNumber dla właściwości i zgłoś radar.

object.intProperty = NSNumber(int:Int(item["id"] as String)) 

(Wpisane przez telefon, więc przepraszam, jeśli to się stało, a ja wiem, że to kod obrzydliwe - stąd złożyć radar)

lub w swoim konkretnym przypadku, patrząc na JSON, korzystanie Strunowy. Te identyfikatory przychodzą i tak jako ciągi.

+0

Zaktualizowałem moje pytanie z działającym kodem, Wierzę, że xCode był odtwarzany i od czasu gdy zmieniałem swój plik modelu (który stworzyłem ręcznie) bez czyszczenia mojego projektu otrzymywałem Błędy BAD_ACCESS –

+1

@ (objc) nie jest zalecanym rozwiązaniem, zobacz http://stackoverflow.com/questions/24926418/swift-array-cannot-be-downcast-to-array-of-derived/24926845#24926845 – jrturton

1

Aktualizacja dla Swift 2

Jeśli dane JSON jest naprawdę typu [[String:String]], można użyć następującego kodu w celu ustalenia category.id :

if let unwrappedString = item["id"], unwrappedInt = Int(unwrappedString) { 
    category.id = unwrappedInt 
} 
+0

Twoja odpowiedź jest również poprawna Musiałem użyć NSNumber w pliku modelu –