Swift 2では、次のコードが機能していました。
let request = NSFetchRequest(entityName: String)
しかし、Swift 3ではエラーになります:
汎用パラメーター「ResultType」を推測できませんでした
NSFetchRequest
は現在ジェネリック型であるためです。彼らの文書で彼らはこれを書いた:
let request: NSFetchRequest<Animal> = Animal.fetchRequest
結果クラスが例えばLevel
の場合、どうすれば正しくリクエストできますか?
これが機能しないため:
let request: NSFetchRequest<Level> = Level.fetchRequest
let request: NSFetchRequest<NSFetchRequestResult> = Level.fetchRequest()
または
let request: NSFetchRequest<Level> = Level.fetchRequest()
必要なバージョンに応じて。
それ以外の場合、メソッド呼び出しがあいまいであるため、ジェネリック型を指定する必要があります。
最初のバージョンはNSManagedObject
に対して定義され、2番目のバージョンは拡張機能を使用してすべてのオブジェクトに対して自動的に生成されます、例:
extension Level {
@nonobjc class func fetchRequest() -> NSFetchRequest<Level> {
return NSFetchRequest<Level>(entityName: "Level");
}
@NSManaged var timeStamp: NSDate?
}
全体のポイントは、文字列定数の使用を削除することです。
私はこれを行うことでうまくいったと思います:
let request:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Level")
少なくとも、データベースからデータを保存およびロードします。
しかし、それは適切な解決策ではないように感じますが、今のところは機能します。
3.0で動作することがわかった最も単純な構造は次のとおりです。
let request = NSFetchRequest<Country>(entityName: "Country")
ここで、データエンティティタイプは国です。
ただし、Core Data BatchDeleteRequestを作成しようとすると、この定義が機能せず、フォームを使用する必要があるようです。
let request: NSFetchRequest<NSFetchRequestResult> = Country.fetchRequest()
managedObjectとFetchRequestResultの形式は同等であると想定されていますが。
質問に答える可能性のある一般的なCoreDataメソッドを次に示します。
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)")
}
}
次のようなContactの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()
これはSwift 3.0に移行する最も簡単な方法で、<Country>
を追加するだけです
(テスト済みおよび動作中)
let request = NSFetchRequest<Country>(entityName: "Country")
また、「ResultType」エラーを推測できませんでした。各エンティティのCodegenを「クラス定義」に設定してデータモデルを再構築すると、それらはクリアされました。私はここでステップバイステップの手順で簡単な記事を書きました:
Swift 3を使用したXcode 8のNSPersistentContainerの改訂版に関する明確なチュートリアルを探しています
「再構築」とは、新しいエントリと属性を持つ新しいモデルファイルを作成したことを意味します。少し面倒ですが、うまくいきました!
私は同じ問題を抱えていて、次の手順で解決しました。
XCodeが何らかの方法でコード生成バージョンと混同するように見えるので、それを行った後、fetchRequestのすべての出現を削除/書き換える必要がありました。
HTH
これまでのところ私にとって最もうまくいったのは:
let request = Level.fetchRequest() as! NSFetchRequest<Level>
Swift 3.0これは動作するはずです。
let request: NSFetchRequest<NSFetchRequestResult> = NSManagedObject.fetchRequest()
request.entity = entityDescription(context)
request.predicate = predicate