NSFetchRequest आवृत्ति पर प्रकार कैसे लागू करें?


102

स्विफ्ट 2 में निम्नलिखित कोड काम कर रहा था:

let request = NSFetchRequest(entityName: String)

लेकिन स्विफ्ट 3 में यह त्रुटि देता है:

सामान्य पैरामीटर "ResultType" का अनुमान नहीं लगाया जा सकता है

क्योंकि NSFetchRequestअब एक सामान्य प्रकार है। अपने दस्तावेजों में उन्होंने लिखा है:

let request: NSFetchRequest<Animal> = Animal.fetchRequest

इसलिए यदि मेरा परिणाम वर्ग उदाहरण के लिए है तो Levelमुझे सही तरीके से कैसे अनुरोध करना चाहिए?

क्योंकि यह काम नहीं कर रहा है:

let request: NSFetchRequest<Level> = Level.fetchRequest

1
नई सुविधाओं के लिए लिंक, जहाँ मुझे कोड मिला: developer.apple.com/library/prerelease/content/releasenotes/…
डेनिस

1
यह एक तरीका है, इसलिए यह होना चाहिएlet request: NSFetchRequest<Level> = Level.fetchRequest()
सुल्तान

5
या बसlet request = Level.fetchRequest()
मार्टिन आर

2
@MartinR यह संकलन पास नहीं होगा क्योंकि यह अस्पष्ट है।
सुल्तान

6
@MartinR लगता है कि ढेर अतिप्रवाह सदस्य आपको बहुत प्यार करते हैं। वे तुम्हें आँख बंद करके अपवित्र करेंगे। : पी
बांगोपरेटर

जवाबों:


129
let request: NSFetchRequest<NSFetchRequestResult> = Level.fetchRequest()

या

let request: NSFetchRequest<Level> = Level.fetchRequest()

निर्भर करता है कि आपको कौन सा संस्करण चाहिए।

आपको जेनेरिक प्रकार निर्दिष्ट करना होगा क्योंकि अन्यथा विधि कॉल अस्पष्ट है।

पहले संस्करण के लिए परिभाषित किया गया है NSManagedObject, दूसरा संस्करण एक एक्सटेंशन का उपयोग करके प्रत्येक ऑब्जेक्ट के लिए स्वचालित रूप से उत्पन्न होता है, उदाहरण के लिए:

extension Level {
    @nonobjc class func fetchRequest() -> NSFetchRequest<Level> {
        return NSFetchRequest<Level>(entityName: "Level");
    }

    @NSManaged var timeStamp: NSDate?
}

पूरे बिंदु स्ट्रिंग स्थिरांक के उपयोग को हटाने के लिए है।


1
तो हर इकाई के लिए, क्या मुझे एक्सटेंशन कोड जोड़ने की आवश्यकता है? या कि स्वचालित रूप से होता है? इसलिए अगर मेरे पास "डॉग" इकाई और "कैट" इकाई है, तो क्या मुझे "डॉग {@nonobjc ...}" और "एक्सटेंशन कैट {@bonobjc ...}" की आवश्यकता है?
डेव जी

@DaveG यह एक्सटेंशन आपके लिए अपने आप जेनरेट हो जाता है।
सुल्तान

1
ठीक है, ty, लेकिन मैं थोड़ा उलझन में हूँ क्योंकि मैंने 'let fetchRequest = NSFetchRequest <myEntityName> (unitName: "myEntityName")' की कोशिश की 'और मुझे त्रुटि मिली कि अघोषित प्रकार का उपयोग "myEntityName"
डेव जी

4
नोट: विधि fetchRequest () केवल iOS 10 में उपलब्ध है
dzensik

@ सुल्तान हाय, जब मैंने आपके कोड के साथ प्रयास किया, तो निम्न त्रुटि होती है। Type 'Project Name' does not conform to protocol 'NSFetchRequestResult'
स्वेतोस्लाव अटानासोव

56

मुझे लगता है कि मुझे यह करके काम करना पड़ा:

let request:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Level")

कम से कम यह डेटाबेस से डेटा को बचाता और लोड करता है।

लेकिन ऐसा लगता है कि यह एक उचित समाधान नहीं है, लेकिन यह अभी के लिए काम करता है।


मुझे यह समाधान बेहतर लगता है, क्योंकि मेरे पास एक एकल विधि थी जो इकाई नाम को एक पैरामीटर के रूप में लेती थी और बस NSManagedObjects की एक सरणी को वापस कर देती थी।
n_b

इसे इसलिए भी पसंद किया क्योंकि इसके लिए कस्टम क्लास बनाने की आवश्यकता नहीं थी। बस इकाई नाम का उपयोग कर सकता है!
लियाम बोलिंग

अधूरा जवाब। धन्यवाद!
डेविड चेलिड्ज़

33

मैंने पाया कि सबसे सरल संरचना 3.0 में काम करती है:

let request = NSFetchRequest<Country>(entityName: "Country")

जहां डेटा इकाई प्रकार देश है।

हालांकि, कोर डेटा बैचडेलीट्रस्ट बनाने की कोशिश करते समय, मैंने पाया कि यह परिभाषा काम नहीं करती है और ऐसा लगता है कि आपको फॉर्म के साथ जाना होगा:

let request: NSFetchRequest<NSFetchRequestResult> = Country.fetchRequest()

भले ही ManagedObject और FetchRequestResult प्रारूप समान हों।


1
इस उत्तर में उल्लिखित पहला ढांचा एकमात्र तरीका है जो मैं वर्तमान में Swift3 / iOS 10 / Xcode 8. पर अपने प्राप्त परिणाम नियंत्रक के साथ संकलित करने के लिए प्राप्त कर सकता हूं
David L

विभिन्न रूपों को आजमाने के बाद यह मेरा अनुभव था। क्या उन्होंने CoreData प्रस्तुति में किसी अन्य रूप को शामिल किया है? कल इसकी जांच करने की योजना ...
रॉन डिल

पहला उदाहरण सबसे सरल तरीका है जो मैंने if #available(iOS 10.0) { ... }सशर्त का उपयोग किए बिना पाया है
djv

12

यहां कुछ सामान्य कोरडेटा विधियां दी गई हैं जो आपके प्रश्न का उत्तर दे सकती हैं:

import Foundation
import Cocoa

func addRecord<T: NSManagedObject>(_ type : T.Type) -> T
{
    let entityName = T.description()
    let context = app.managedObjectContext
    let entity = NSEntityDescription.entity(forEntityName: entityName, in: context)
    let record = T(entity: entity!, insertInto: context)
    return record
}

func recordsInTable<T: NSManagedObject>(_ type : T.Type) -> Int
{
    let recs = allRecords(T.self)
    return recs.count
}


func allRecords<T: NSManagedObject>(_ type : T.Type, sort: NSSortDescriptor? = nil) -> [T]
{
    let context = app.managedObjectContext
    let request = T.fetchRequest()
    do
    {
        let results = try context.fetch(request)
        return results as! [T]
    }
    catch
    {
        print("Error with request: \(error)")
        return []
    }
}

func query<T: NSManagedObject>(_ type : T.Type, search: NSPredicate?, sort: NSSortDescriptor? = nil, multiSort: [NSSortDescriptor]? = nil) -> [T]
{
    let context = app.managedObjectContext
    let request = T.fetchRequest()
    if let predicate = search
    {
        request.predicate = predicate
    }
    if let sortDescriptors = multiSort
    {
        request.sortDescriptors = sortDescriptors
    }
    else if let sortDescriptor = sort
    {
        request.sortDescriptors = [sortDescriptor]
    }

    do
    {
        let results = try context.fetch(request)
        return results as! [T]
    }
    catch
    {
        print("Error with request: \(error)")
        return []
    }
}


func deleteRecord(_ object: NSManagedObject)
{
    let context = app.managedObjectContext
    context.delete(object)
}

func deleteRecords<T: NSManagedObject>(_ type : T.Type, search: NSPredicate? = nil)
{
    let context = app.managedObjectContext

    let results = query(T.self, search: search)
    for record in results
    {
        context.delete(record)
    }
}

func saveDatabase()
{
    let context = app.managedObjectContext

    do
    {
        try context.save()
    }
    catch
    {
        print("Error saving database: \(error)")
    }
}

यह मानते हुए कि इस तरह के संपर्क के लिए एक NSManagedObject सेटअप है:

class Contact: NSManagedObject
{
    @NSManaged var contactNo: Int
    @NSManaged var contactName: String
}

इन तरीकों का इस्तेमाल निम्नलिखित तरीके से किया जा सकता है:

let name = "John Appleseed"

let newContact = addRecord(Contact.self)
newContact.contactNo = 1
newContact.contactName = name

let contacts = query(Contact.self, search: NSPredicate(format: "contactName == %@", name))
for contact in contacts
{
    print ("Contact name = \(contact.contactName), no = \(contact.contactNo)")
}

deleteRecords(Contact.self, search: NSPredicate(format: "contactName == %@", name))

recs = recordsInTable(Contact.self)
print ("Contacts table has \(recs) records")

saveDatabase()

साफ और सुंदर। काश मैं इसे 100 वोट कर सकता! एक टचअप, आपको क्या लगता है, यह सोचकर मैंने प्रत्येक विधि को संदर्भ के साथ लपेटा है? थ्रेड सुरक्षा के लिए ({})। यह Apple द्वारा अनुशंसित है।
Tinkerbell

बहुत ऊ नहीं है। जब तक आप इन्हें NSManagedObjectContect के विस्तार के रूप में लिखने में सक्षम नहीं होते, तब तक यह एक अच्छा समाधान होगा।
अक्ष

1
बस ध्यान दिया - उन सभी रिकॉर्डों को गिनने के लिए जिन्हें आप उन्हें पुनः प्राप्त कर रहे हैं और फिर सरणी प्रविष्टियों की संख्या की गिनती कर रहे हैं - यह वास्तव में अक्षम है। आप संदर्भ का उपयोग करने के लिए संभवत: रिकॉर्ड्स का विस्तार करना चाहते हैं। संदर्भ (अनुरोध) का उपयोग करें
मुज करें

ये अच्छे जोड़ हैं और इसमें अधिक वोट होने चाहिए, लेकिन शायद इसलिए नहीं कि यह मुख्य प्रश्न (भले ही यह उपयोगी हो) से दूर एक विषयांतर है। कुछ मैं डिलीट फ़ंक्शन के साथ बदलने के लिए कठिन सुझाव दूंगा, NSManagedObjectIDइसके बजाय डिलीट करना है । इसलिए context.delete(record)जोड़ने से पहले let record = context.object(with: record.objectID)और हटाने के लिए उस रिकॉर्ड ऑब्जेक्ट का उपयोग करें।
पोस्टकोडवाद

6

यह स्विफ्ट 3.0 में माइग्रेट करने का सबसे सरल तरीका है, बस जोड़ें <Country>

(परीक्षण और काम)

let request = NSFetchRequest<Country>(entityName: "Country")

0

मेरे पास "ResultType" था, यह भी गलत अनुमान नहीं था। एक बार जब मैंने प्रत्येक मॉडल के कोडेन को "क्लास डेफिनिशन" सेट करने वाले डेटा मॉडल को फिर से बनाया तो उन्होंने मंजूरी दे दी। मैंने यहां कदम से कदम निर्देश के साथ एक संक्षिप्त राइटअप किया:

स्विफ्ट 3 के साथ Xcode 8 में संशोधित NSPersistentContainer पर एक स्पष्ट ट्यूटोरियल की तलाश है

"पुनर्निर्माण" द्वारा मेरा मतलब है कि मैंने नई प्रविष्टियों और विशेषताओं के साथ एक नया मॉडल फ़ाइल बनाया। थोड़ा थकाऊ, लेकिन यह काम किया!


0

अब तक मेरे लिए सबसे अच्छा काम क्या था:

let request = Level.fetchRequest() as! NSFetchRequest<Level>

0

मेरे पास एक ही मुद्दा था और मैंने इसे निम्नलिखित चरणों के साथ हल किया:

  • अपनी xcdatamodeld फ़ाइल चुनें और डेटा मॉडल इंस्पेक्टर के पास जाएं
  • अपनी पहली एंटिटी चुनें और सेक्शन क्लास में जाएं
  • सुनिश्चित करें कि कोडजेन "क्लास डेफिनिशन" चुना गया है।
  • अपनी सभी जेनरेट की गई एंटिटी फाइल्स को हटा दें। अब आपको उनकी आवश्यकता नहीं है

ऐसा करने के बाद मुझे भ्रूण को हटाने की सभी घटनाओं को फिर से लिखना / हटाना पड़ा क्योंकि XCode को किसी तरह से कोडेनेरेटेड संस्करण के साथ मिलाना प्रतीत होता है।

HTH


0

स्विफ्ट 3.0 यह काम करना चाहिए।

let request: NSFetchRequest<NSFetchRequestResult> = NSManagedObject.fetchRequest()
request.entity = entityDescription(context)
request.predicate = predicate
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.