Restkit, Coredata and Swift - I Can't Seem to Fetch Results Back Out

RestKit, CoreData and Swift - I can't seem to fetch results back out

The answer is that apparently Swift does not like casting the fetch result as an optional. I have to put the result into a local variable and then set the optional:

var currentUser: User? {
if !_currentUser {
var error: NSError? = nil
let request = NSFetchRequest(entityName: "User")
let recordCount = self.managedObjectContext.countForFetchRequest(request, error:&error)
NSLog("user records found: \(recordCount)")
var result = self.managedObjectContext.executeFetchRequest(request, error:&error)
for resultItem : AnyObject in result {
var currentUserItem = resultItem as User
NSLog("Fetched User for \(currentUserItem.firstname) \(currentUserItem.lastname)")
_currentUser = currentUserItem
}
}
return _currentUser;
}

Here is my setup and teardown of RestKit in Swift in case anyone (like niiamon) finds it helpful:

From my RestApi.swift:

var objectStore: RKManagedObjectStore = RKManagedObjectStore()

init() {
configureRestKit()
}

func configureRestKit() {
let objectManager = RKObjectManager(baseURL: NSURL.URLWithString(baseUrl))
//objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
RKObjectManager.setSharedManager(objectManager)

objectStore = RKManagedObjectStore(managedObjectModel: managedObjectModel())
let dataPath = "\(RKApplicationDataDirectory())/MyApp.sqlite"
NSLog("Setting up store at \(dataPath)")
objectStore.addSQLitePersistentStoreAtPath(dataPath, fromSeedDatabaseAtPath: nil, withConfiguration: nil, options: optionsForSqliteStore(), error: nil)
objectStore.createManagedObjectContexts()
objectStore.managedObjectCache = RKInMemoryManagedObjectCache(managedObjectContext: objectStore.persistentStoreManagedObjectContext)
objectManager.managedObjectStore = objectStore

// -- Declare routes -- //

// Login Route
objectManager.addResponseDescriptor(userLoginResponseDescriptor())
objectManager.addResponseDescriptor(eventLoginResponseDescriptor())
objectManager.router.routeSet.addRoute(RKRoute(name:kUserLoginRouteName, pathPattern: "/login", method: RKRequestMethod.POST))
}

func tearDownRestKit() {
// Cancel any network operations and clear the cache
RKObjectManager.sharedManager().operationQueue.cancelAllOperations()
NSURLCache.sharedURLCache().removeAllCachedResponses()

// Cancel any object mapping in the response mapping queue
RKObjectRequestOperation.responseMappingQueue().cancelAllOperations()

// Ensure the existing defaultStore is shut down
NSNotificationCenter.defaultCenter().removeObserver(RKManagedObjectStore.defaultStore())

RKObjectManager.setSharedManager(nil)
RKManagedObjectStore.setDefaultStore(nil)
}

func userMapping() -> RKEntityMapping {
let userMapping = RKEntityMapping(forEntityForName: "User", inManagedObjectStore: objectStore)

var userDictionary = ["id": "id", "created_at": "createdAt", "updated_at": "updatedAt", "username": "username", "email": "email", "firstname": "firstname", "lastname": "lastname", "organization": "organization"]

userMapping.addAttributeMappingsFromDictionary(userDictionary)
let tokenMapping = RKEntityMapping(forEntityForName: "ApiToken", inManagedObjectStore: objectStore)
tokenMapping.addAttributeMappingsFromArray(["token", "expiration"])
userMapping.addRelationshipMappingWithSourceKeyPath("tokens", mapping:tokenMapping)
return userMapping
}

func userLoginResponseDescriptor() -> RKResponseDescriptor {
let userResponseDescriptor = RKResponseDescriptor(mapping: userMapping(), method: RKRequestMethod.POST, pathPattern: "/login", keyPath: "user", statusCodes: NSIndexSet(index: 200))
return userResponseDescriptor
}

func managedObjectModel() -> NSManagedObjectModel {
return NSManagedObjectModel.mergedModelFromBundles(nil)
}

func optionsForSqliteStore() -> NSDictionary {
return [
NSInferMappingModelAutomaticallyOption: true,
NSMigratePersistentStoresAutomaticallyOption: true
];
}

Return Results from CoreData directly into Class

The compiler complains because you did not specify a return type for your function,
it should be

class func getAllLocations() -> [Locations] { ... }

There are also some unnecessary type annotations, and all the objects can be
declared as constants:

class func getAllLocations() -> [Locations] {
let appDel = (UIApplication.sharedApplication().delegate as AppDelegate)
let context = appDel.managedObjectContext!

let request = NSFetchRequest(entityName: "Locations")
request.returnsObjectsAsFaults = false

let results = context.executeFetchRequest(request, error: nil)!
return results as [Locations]
}

Note also that

let results = context.executeFetchRequest(request, error: nil)!

will throw a runtime exception if the executing the fetch request failed.
You should use an optional binding and some error handling or fallback,
for example

if let results = context.executeFetchRequest(request, error: nil) as? [Locations] {
return results
} else {
// Failed, return empty list. (Alternatively, report error.)
return []
}

Fetching From CoreData returns AnyObject

context.executeFetchRequest() returns [AnyObject], not AnyObject.

You need to do:

if let results = context.executeFetchRequest(fetchRequest2) as? [MyObjectType] {
for object in results {
//do thing
}
}

Issue with Core Data fetch request

I got the viewContext from the container because I needed the UI thread. I guess that was my problem. I solved it passing the context I used to fetch and create the data and dispatching the request to the main queue:

func loadData(with context: NSManagedObjectContext) {

context.perform {

DispatchQueue.main.async {
let request: NSFetchRequest<EntityName> = EntityName.fetchRequest()
let data = try? context.fetch(request)
self.data = data!

self.setUI()
}
}
}

I hope it helps.

How to Fetch Coredata?

You are very close, type of users is [User] so an array of User objects, so you can get to token of each User with:

let managedContext = coreDataStack.managedContext
let request = NSFetchRequest<User>(entityName: "User")
do {
let users = try managedContext.fetch(request)
for user in users {
print(user.token)
}
} catch {
print(error.localizedDescription)
}

or if you want to get last (.last) or first (.first) User you can just do:

do {
let users = try managedContext.fetch(request)
if let user = users.first {
print(user.token)
}
} catch {
print(error.localizedDescription)
}

Fetch Local Data from CoreData using RestKit 0.2

Using addInMemoryPersistentStore: does not save to disk so when the app closes all data is gone. Look at using addSQLitePersistentStoreAtPath: instead.

Sync coredata with restkit

RestKit will work with your existing core data model. You aren't forced to use the active record additions at all - feel free to ignore it.

As to your question. Before you try and fix everything by using RestKit. I recommend understanding exactly what you are trying to achieve with this "sync process". In fact RestKit does not magically sync anything (although there was that branch somewhere...). If you do not understand synchronization first, you will not be able to develop this system well.

IOS CoreData fetch duplicates on each view load

It because you create new data in your loop with this code

let order = FailedOrderEntity(context: context)

to fetch data with entity class model use this code

var fetched: [FailedOrderEntity] = []
let fetchRequest: NSFetchRequest<FailedOrderEntity> = FailedOrderEntity.fetchRequest()
do{
try fetched = context.fetch(fetchRequest)
} catch {}

How to retrieve CoreData that satisfies a condition swift 2

You need to add a NSPredicate to your fetchRequest.

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/

fetchRequest.predicate = NSPredicate(format: "flag == %@", "3")


Related Topics



Leave a reply



Submit