2016-01-05 9 views
8

Ich habe ein Projekt, in dem ich eine Abrufanforderung ausführen muss, die das letzte "aktualisierte" Datum einer Core Data-Entität erhält. Wenn ich tatsächlich die von meiner Abfrage zurückgegebenen Ergebnisse untersuche, sehe ich ein ziemlich merkwürdiges Verhalten. Zusätzlich zu dem "korrekten" Ergebnis, das das Datum enthält, enthalten die Ergebnisse auch ein leeres Wörterbuchelement. Dies geschieht jedes Mal unabhängig davon, wie die zugrunde liegenden Daten aussehen. Noch seltsamer, wenn ich sql bei der Anmeldung von xcode einschalte und die protokollierte Abfrage gegen die sqllite db ausführe, erzeugt es das korrekte Ergebnis ohne zusätzliche Einträge. Ich bin mir nicht ganz sicher, was ich hier falsch mache, jede Hilfe wäre willkommen.Swift-Fetch-Anforderung, die leeres Element in Ergebnissen zurückgibt

Die Funktion, die baut und führt die Abfrage aus:

func queryForContactDate(context:NSManagedObjectContext) -> AnyObject? 
{ 

    var expressionDescriptions = [AnyObject](); 

    let expressionDescription = NSExpressionDescription() 

    // Name the column 
    expressionDescription.name = "maxUpdated" 
    // Use an expression to specify what aggregate action we want to take and 
    // on which column. In this case max on the update_at column 
    expressionDescription.expression = NSExpression(format: "@max.updated_at") 
    // Specify the return type we expect 
    expressionDescription.expressionResultType = .DateAttributeType 
    // Append the description to our array 
    expressionDescriptions.append(expressionDescription) 

    // Build out our fetch request the usual way 
    let request = NSFetchRequest(entityName: Contact.entityName()) 

    // Specify we want dictionaries to be returned 
    request.resultType = .DictionaryResultType 

    // Hand off our expression descriptions to the propertiesToFetch field. 
    request.propertiesToFetch = expressionDescriptions 

    // Our result is going to be an array of dictionaries. 
    var results:[[String:AnyObject]]? 

    // Perform the fetch. This is using Swfit 2, so we need a do/try/catch 
    do { 
     results = try context.executeFetchRequest(request) as? [[String:AnyObject]] 
    } catch _ { 
     // If it fails, ensure the array is nil 
     results = nil 
    } 

    return results![0]; 
} 

Wenn ich einen Haltepunkt am Ende gesetzt und erzeugt aus den Ergebnissen drucken:

Printing description of results: 
▿ Optional([[:], ["maxUpdated": 2015-12-30 20:05:31 +0000]]) 
    ▿ Some : 2 elements 
    - [0] : 0 elements 
    ▿ [1] : 1 elements 
     ▿ [0] : 2 elements 
     - .0 : "maxUpdated" 
     - .1 : 2015-12-30 20:05:31 +0000 
+0

Können Sie mit context.executeFetchRequest drucken (Anfrage) ist ohne eine Besetzung? Es ist möglich, dass du etwas umlegst, das nicht wirklich [[String: AnyObject]] ist. Besonders in den Ecken der API, die Objc portiert werden, um Swift gibt es einige seltsame Dinge, die mit Wörterbüchern/Arrays gehen – tbondwilkinson

+0

Ich vermute, Sie sind auf dem richtigen Weg, aber der Druck war nicht besonders aufschlussreich. Hier ist, was ich habe: [{ }, { maxUpdated = "2015-12-30 20:05:31 +0000"; }] – pbuchheit

+0

Dann würde ich einen Haltepunkt in die Fetch-Methode setzen und zurückverfolgen und sehen, wo die Anfrage stammt/wenn das leere Wörterbuch dort – tbondwilkinson

Antwort

1

Die traditionelle Core Data Art und Weise zu erhalten Bei einem Max- oder Min-Objekt wird mit einem Abruflimit von 1 abgefragt und nach diesem Schlüssel sortiert. Wie in diesem Objective-C-Code:

+ (NSFetchRequest *) requestForStatusWithMaxID { 

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName: kAMStatusEntity]; 

    NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey: kAMTwID ascending:NO]; 

    request.sortDescriptors = @[sd]; 
    request.fetchLimit = 1; 

    return request; 

} // +requestForStatusWithMaxID 

wäre es ganz einfach sein, die oben für Ihre updated_at Eigenschaft zu ändern.

+0

Ja, es ist möglich, den Abruf auf diese Weise durchzuführen, aber die Leistung wird leiden, wenn die Größe der zugrunde liegenden Tabelle größer wird. Außerdem sehe ich das gleiche Verhalten, wenn ich andere Aggregatfunktionen wie SUM versuche. Einfach zu sortieren und das erste Ergebnis zu nehmen, wird bei diesen nicht helfen. – pbuchheit

+0

Jede Abfrage ohne einen Index, einschließlich Ihrer oben aufgeführten, weist Skalierungsprobleme auf, wenn die Tabelle wächst. Wie groß wird dein Tisch? 100, 1.000, 10.000, 1M Reihen? Wenn es groß ist, benötigen Sie einen Index - für beide Abfrageformate. – adonoho