UIPickerView with Core Data Swift4 - core-data

I am trying to re-use a code from swift 7.3. I feel I am very close.
When I try the code on the simulator, the picker view it is empty, but when I try to use it I have only one data show up.
I also try to adapt and other code to load data from core data to it, didn't work.
Any Idea?
Thank you
import CoreData
class ViewController: UIViewController, UIPickerViewDelegate, UIImagePickerControllerDelegate {
#IBOutlet weak var TextField: UITextField!
#IBOutlet weak var stylePicker: UIPickerView!
var styleData = [PilotBase]()
override func viewDidLoad() {
super.viewDidLoad()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "PilotBase")
do {
styleData = try context.fetch(fetchRequest) as! [PilotBase]
} catch let err as NSError {
print(err.debugDescription)
}
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "PilotBase")
request.returnsObjectsAsFaults = false
do{
let result = try context.fetch(request)
for data in result as! [NSManagedObject]{
print(data.value(forKey: "name") as! String)
}
}catch{
print("Failed")
}
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return styleData.count
} else {
return 0
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return styleData[row].name
} else {
return nil
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
print(styleData[row])
stylePicker.selectRow(row, inComponent: 0, animated: true)
TextField.text = styleData[row].name
}
}
Below the code to add data to Core Data.
#IBAction func Save(_ sender: Any) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "PilotBase", in: context)
let newUser = NSManagedObject(entity: entity!, insertInto: context)
newUser.setValue(TextField.text!, forKey: "name")
do{
try context.save()
}catch{
print("failed saving")
}
}

Related

SwifUI: How to get manual list to refresh when updating CoreData records?

I have a CoreData table that has several repeated records that don't need to be stored but do need to be displayed in my user interface. I have manually created my arrays based on the CoreData table. I have made them Observable Objects so they should automatically update and I have made them Hashable and Equatable.
My problem is that the list does not update when the database records are updated. This works fine when records are being added.
Here is my much simplified code in full that demonstrates the problem:
import SwiftUI
let persistentContainerQueue = OperationQueue()
let firstNames = ["Michael", "Damon", "Jacques", "Mika", "Fernando", "Kimi", "Lewis", "Jenson", "Sebastion", "Nico"]
let lastNames = ["Schumacher", "Hill", "Villeneuve", "Hakkinen", "Alonso", "Raikkonen", "Hamilton", "Button", "Vettel", "Rosberg"]
class RepeatedPerson: ObservableObject, Hashable
{
#Published var person: Person
#Published var index: Int
#Published var tested: Bool
init (person: Person, index: Int, tested: Bool)
{
self.person = person
self.index = index
self.tested = tested
}
func hash(into hasher: inout Hasher)
{
hasher.combine(person.firstName)
hasher.combine(person.lastName)
hasher.combine(index)
}
static func == (lhs: RepeatedPerson, rhs: RepeatedPerson) -> Bool
{
return lhs.person.firstName == rhs.person.firstName &&
lhs.person.lastName == rhs.person.lastName &&
lhs.index == rhs.index
}
}
class RepeatedPeople: ObservableObject
{
#Published var people: [RepeatedPerson] = []
}
func getRepeatedPeople() -> [RepeatedPerson]
{
var repeatedPeople:[RepeatedPerson] = []
let records = allRecords(Person.self)
for person in records
{
for index in 1...3
{
repeatedPeople.append(RepeatedPerson(person: person, index: index, tested: true))
}
}
return repeatedPeople
}
struct ContentView: View
{
#Environment(\.managedObjectContext) private var viewContext
#ObservedObject var repeatedPeople = RepeatedPeople()
init()
{
repeatedPeople.people = getRepeatedPeople()
}
var body: some View
{
VStack
{
List()
{
ForEach(repeatedPeople.people, id: \.self)
{ repeatedPerson in
Text("\(repeatedPerson.index)) \(repeatedPerson.person.firstName!) \(repeatedPerson.person.lastName!)")
}
}
HStack
{
Button("Add Record", action:
{
addItem()
repeatedPeople.people = getRepeatedPeople()
})
Button("Change Record", action:
{
let q = allRecords(Person.self)
let oldLastName = q[0].lastName
q[0].lastName = lastNames.randomElement()!
print ("changed \(q[0].firstName!) \(oldLastName!) -> \(q[0].firstName!) \(q[0].lastName!)")
saveDatabase()
})
Button("Reset Database", action:
{
deleteAllRecords(Person.self)
})
}
}
}
private func addItem()
{
withAnimation
{
let newItem = Person(context: viewContext)
newItem.timestamp = Date()
newItem.firstName = firstNames.randomElement()!
newItem.lastName = lastNames.randomElement()!
print ("added \(newItem.firstName!) \(newItem.lastName!)")
saveDatabase()
}
}
}
func allRecords<T: NSManagedObject>(_ type : T.Type, sort: NSSortDescriptor? = nil) -> [T]
{
let context = PersistenceController.shared.container.viewContext
let request = T.fetchRequest()
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 deleteAllRecords<T: NSManagedObject>(_ type : T.Type)
{
let context = PersistenceController.shared.container.viewContext
let results = allRecords(T.self)
for record in results
{
context.delete(record as NSManagedObject)
}
saveDatabase()
}
func saveDatabase()
{
persistentContainerQueue.addOperation()
{
let context = PersistenceController.shared.container.viewContext
context.performAndWait
{
try? context.save()
}
}
}
To reproduce the problem, add a few records. These will be shown in the list. Then click the 'Update Record' button. The CoreData record will be updated (you can see this the next time you run the app) but the changes will not be shown.
How do I get the new changes to show?
If you add another record the changes will then be shown. A side effect is that the list introduces wild spaces between the records. I have seen this is in other places. Is this a SwiftUI bug?
OK it turned out to be really quite simple. All I actually had to do was remove some of the #Published and provide a UUID for the repeatedPerson record (and for == and hash).
import SwiftUI
import CoreData
let persistentContainerQueue = OperationQueue()
let firstNames = ["Michael", "Damon", "Jacques", "Mika", "Fernando", "Kimi", "Lewis", "Jenson", "Sebastion", "Nico"]
let lastNames = ["Schumacher", "Hill", "Villeneuve", "Hakkinen", "Alonso", "Raikkonen", "Hamilton", "Button", "Vettel", "Rosberg"]
class RepeatedPerson: ObservableObject, Hashable
{
var id: UUID = UUID()
var index: Int
var person: Person?
init (person: Person, index: Int)
{
self.person = person
self.index = index
}
func hash(into hasher: inout Hasher)
{
hasher.combine(id)
}
static func == (lhs: RepeatedPerson, rhs: RepeatedPerson) -> Bool
{
return lhs.id == rhs.id
}
}
class RepeatedPeople: ObservableObject
{
#Published var people: [RepeatedPerson] = []
}
func getRepeatedPeople() -> [RepeatedPerson]
{
var repeatedPeople:[RepeatedPerson] = []
let records = allRecords(Person.self)
for person in records
{
for index in 1...3
{
repeatedPeople.append(RepeatedPerson(person: person, index: index))
}
}
return repeatedPeople
}
struct ContentView: View
{
#Environment(\.managedObjectContext) private var viewContext
#ObservedObject var repeatedPeople = RepeatedPeople()
init()
{
repeatedPeople.people = getRepeatedPeople()
}
var body: some View
{
VStack
{
List()
{
ForEach(repeatedPeople.people, id: \.self)
{ repeatedPerson in
Text("\(repeatedPerson.index)) \(repeatedPerson.person!.firstName!) \(repeatedPerson.person!.lastName!)")
}
}
HStack
{
Button("Add Record", action:
{
addItem()
repeatedPeople.people = getRepeatedPeople()
})
Button("Change Record", action:
{
let q = allRecords(Person.self)
let r = q.randomElement()!
let oldLastName = r.lastName
r.lastName = lastNames.randomElement()!
print ("changed \(r.firstName!) \(oldLastName!) -> \(r.firstName!) \(r.lastName!)")
saveDatabase()
repeatedPeople.people = getRepeatedPeople()
})
Button("Reset Database", action:
{
print ("Reset database")
deleteAllRecords(Person.self)
repeatedPeople.people = getRepeatedPeople()
})
}
}
}
private func addItem()
{
withAnimation
{
let newItem = Person(context: viewContext)
newItem.timestamp = Date()
newItem.firstName = firstNames.randomElement()!
newItem.lastName = lastNames.randomElement()!
print ("added \(newItem.firstName!) \(newItem.lastName!)")
saveDatabase()
}
}
}
func query<T: NSManagedObject>(_ type : T.Type, predicate: NSPredicate? = nil, sort: NSSortDescriptor? = nil) -> [T]
{
let context = PersistenceController.shared.container.viewContext
let request = T.fetchRequest()
if let sortDescriptor = sort
{
request.sortDescriptors = [sortDescriptor]
}
if let predicate = predicate
{
request.predicate = predicate
}
do
{
let results = try context.fetch(request)
return results as! [T]
}
catch
{
print("Error with request: \(error)")
return []
}
}
func allRecords<T: NSManagedObject>(_ type : T.Type, sort: NSSortDescriptor? = nil) -> [T]
{
return query(T.self, sort: sort)
}
func deleteAllRecords<T: NSManagedObject>(_ type : T.Type)
{
let context = PersistenceController.shared.container.viewContext
let results = allRecords(T.self)
for record in results
{
context.delete(record as NSManagedObject)
}
saveDatabase()
}
func saveDatabase()
{
persistentContainerQueue.addOperation()
{
let context = PersistenceController.shared.container.viewContext
context.performAndWait
{
try? context.save()
}
}
}

fetch core data string and place in a label (Swift4)

I am trying to call 2 different core data strings and place them each on separate labels. Right now I am getting the error Cannot invoke initializer for type 'init(_:)' with an argument list of type '([NSManagedObject])'. This error is coming from j1.text = String(itemsName). I added both view controllers for saving and displaying.
import UIKit
import CoreData
class ViewController: UIViewController {
#IBOutlet var j1 : UITextField!
#IBOutlet var j2 : UITextField!
#IBAction func save(){
let appD = UIApplication.shared.delegate as! AppDelegate
let context = appD.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Team", in : context)!
let theTitle = NSManagedObject(entity: entity, insertInto: context)
theTitle.setValue(j1.text, forKey: "score")
theTitle.setValue(j2.text, forKey: "alba")
do {
try context.save()
}
catch {
print("Tom Corley")
}
}}
class twoVC: UIViewController {
#IBOutlet var j1 : UILabel!
#IBOutlet var j2 : UILabel!
var itemsName : [NSManagedObject] = []
var itemsName2 : [NSManagedObject] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let appD = UIApplication.shared.delegate as! AppDelegate
let context = appD.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Team")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "score", ascending: true)]
let fetchRequest2 = NSFetchRequest<NSManagedObject>(entityName: "Team")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "alba", ascending: true)]
do {
itemsName = try context.fetch(fetchRequest)
itemsName2 = try context.fetch(fetchRequest2)
if let score = itemsName[0].value(forKey: "score") {
j1.text = (score as! String)
}
if let alba = itemsName2[0].value(forKey: "alba") {
j2.text = (alba as? String)
}
}catch {
print("Ashley Tisdale")
}
}}
Loop over the result from the fetch and append to a string that is then used as value for the label, this goes inside the do{...} where you do the fetch today. Note that I am only using one fetch request here.
itemsName = try context.fetch(fetchRequest)
var mergedScore: String = ""
var mergedAlba: String = ""
for item in itemsName {
if let score = item.value(forKey: "score") as? String {
mergedScore.append(score)
mergedScore.append(" ") //separator
}
if let alba = item.value(forKey: "alba") as? String {
mergedScore.append(alba)
mergedScore.append(" ") //separator
}
}
j1.text = mergedScore
j2.text = mergedAlba
Try this one it's Working for me Swift 4 I think You need to store the value as int which are used as sortDescriptor.
func FetchManagedObjectFromDatabaseForStoreData(Entity :NSEntityDescription) ->
[NSManagedObject]
{
let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
// Add Sort Descriptor
let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
let sortDescriptor1 = NSSortDescriptor(key: "is_favourite", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor,sortDescriptor1]
// Create Entity Description
fetchRequest.entity = Entity
let result : [NSManagedObject] = []
// Execute Fetch Request
do{
let result = try appDelegate.managedObjectContext.fetch(fetchRequest) as! [NSManagedObject]
if result.count > 0
{
return result
}
else
{
// return result
}
}
catch{
let fetchError = error as NSError
print(fetchError)
}
return result
}
For Fetch Data
// Create Entity Description
let entityDescription = NSEntityDescription.entity(forEntityName: "Your Entity Name Here", in: appDel.managedObjectContext)
let DataObject = FetchManagedObjectFromDatabaseForStoreData(Entity: entityDescription!)
//Convert Array of NSManagedObject into array of [String:AnyObject]
for item in DataObject{
let keys = Array(item.entity.attributesByName.keys)
// Here is your result
print((item.dictionaryWithValues(forKeys: keys) as NSDictionary).value(forKey: "id") as Any) // And so On Whatewer you Fetch
}

Issues with UserDefaults.standard.value(forKey: "barcodeId") as! String

Can anyone tell me why the copied data from user defaults is not passing the correct value? Below is my code, the weird part about all of this is outside of the app, when pasting on to notes or safari on the device. It does indeed past the correct data. NOTE: I've removed the test url
let testURL = ""
// let barcodeData = UserDefaults.standard.value(forKey: "barcodeId") as! String
var barcodeData = UserDefaults.standard.value(forKey: "barcodeId") as! String
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet weak var webView: WKWebView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
webView.navigationDelegate = self
load(urlString: testURL)
}
// MARK: Private function
func load(urlString string: String) {
let url = URL(string: string)
let request = URLRequest(url: url!)
webView.load(request)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.getElementById('RCPT_BARCODE').value = \(barcodeData)") {(result, error) in
guard error == nil else {
print(error!)
return
}
print(String(describing: result))
}
}
}

logically false fetch request

I am doing a fetch request with a predicate mentioned in the block quote below, but I seem to get "logically false fetch request". What does this message mean and what step should I take to find the problem and resolve it?
annotation: logically false fetch request (entity: Country; predicate: ("alpha3Code" == "KOR"); sortDescriptors: ((null)); type: NSManagedObjectResultType; ) short circuits.
Here is the code that I get the error from
let record = Currency.fetch(id: currency)[0] as! Currency
where Currency class is as follows. "fetch" is implemented in NSManagedObjectProtocol trait
public class Currency: NSManagedObject, NSManagedObjectProtocol, XMLImporterDelegate {
private static let attributes = ["name", "currency", "decimalUnit", "isUsed"]
private static let xmlRecordTag = "CcyNtry"
private static let xmlAttributeTags = ["CcyNm": attributes[0],
"Ccy": attributes[1],
"CcyMnrUnts": attributes[2]]
static func setValue(managedObject: NSManagedObjectProtocol, object: Dictionary<String, Any>) {
let currency = managedObject as! Currency
currency.name = getString(from: object, withKeyValue: attributes[0])
currency.currency = getString(from: object, withKeyValue: attributes[1])
currency.decimalUnit = getInt16(from: object, withKeyValue: attributes[2])
currency.isUsed = getBool(from: object, withKeyValue: attributes[3])
return
}
static func getPredicates(forID id: Dictionary<String, Any>) -> [NSPredicate] {
var predicates: [NSPredicate] = []
predicates.append(NSPredicate.init(format: "%# = %#", attributes[1], getString(from: id, withKeyValue: attributes[1])))
return predicates
}
func isEqual(object: NSManagedObjectProtocol) -> Bool {
if let object = object as? Currency {
if object.currency == self.currency { return false }
return true
} else {
return false
}
}
static func recordTag() -> String {
return xmlRecordTag
}
static func attribute(byTag tag: String) -> String? {
return xmlAttributeTags[tag]
}
static func getUsed() -> [Any]?{
var predicates: [NSPredicate] = []
predicates.append(NSPredicate.init(format: "%# = %#", attributes[3], NSNumber(booleanLiteral: false)))
return fetch(predicates: predicates)
}
}
NSManagedObjectProtocol has following trait
extension NSManagedObjectProtocol {
public static func add(from objectValue: Dictionary<String, Any>) -> NSManagedObjectProtocol? {
let exists = fetch(id: objectValue)
if exists.count > 0 {
NSLog("Object already exists in CoreData : %#", objectValue.description)
return nil
} else {
return newObject(object: objectValue)
}
}
public static func addOrChange(from object: Dictionary<String, Any>) -> NSManagedObjectProtocol {
let exists = fetch(id: object)
if exists.count > 0 {
// TODO: confirm if data needs to be changed rather than delete and insert
}
delete(id: object)
return add(from: object)!
}
public static func getString(from object: Dictionary<String, Any>, withKeyValue key: String) -> String {
return object[key] as! String
}
public static func getInt16(from object: Dictionary<String, Any>, withKeyValue key: String) -> Int16 {
if let stringValue = object[key] as? String {
if let intValue = Int(stringValue) {
return Int16(intValue)
} else {
return 0
}
} else if let intValue = object[key] as? Int {
return Int16(intValue)
} else {
return 0
}
}
public static func getBool(from object: Dictionary<String, Any>, withKeyValue key: String) -> Bool {
if let boolValue = object[key] as? Bool {
return boolValue
} else {
return false
}
}
public static func fetch(predicates: [NSPredicate] = [], sortDescriptors: [NSSortDescriptor] = []) -> [Any] {
let request = Self.request(predicates: predicates)
do {
return try CoreDataHelper.getCoreDataHelper().context.fetch(request)
} catch {
return []
}
}
public static func fetch(id: Dictionary<String, Any>) -> [Any] {
return Self.fetch(predicates: Self.getPredicates(forID: id))
}
public static func delete(predicates: [NSPredicate] = []) {
let context = CoreDataHelper.getContext()
let fetchRequest = request(predicates: predicates)
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try context.execute(deleteRequest)
CoreDataHelper.getCoreDataHelper().saveContext()
} catch {
NSLog("Delete request failed")
return
}
}
public static func delete(id: Dictionary<String, Any>) {
delete(predicates: getPredicates(forID: id))
}
// MARK: - Private API
private static func newObject(object: Dictionary<String, Any>) -> NSManagedObjectProtocol {
let entityName = String(describing: self)
let context = CoreDataHelper.getContext()
let managedObject = NSEntityDescription.insertNewObject(forEntityName: entityName, into: context) as! NSManagedObjectProtocol
setValue(managedObject: managedObject, object: object)
CoreDataHelper.getCoreDataHelper().saveContext()
return managedObject
}
private static func request(predicates: [NSPredicate] = [], sortDescriptors: [NSSortDescriptor] = []) -> NSFetchRequest<NSFetchRequestResult> {
// Prepare a request
let entityName = String(describing: self)
let classObject: AnyClass! = NSClassFromString(entityName)
let objectType: NSManagedObject.Type = classObject as! NSManagedObject.Type!
let request: NSFetchRequest<NSFetchRequestResult> = objectType.fetchRequest()
// Add predicates
if predicates.count > 0 {
request.predicate = NSCompoundPredicate.init(andPredicateWithSubpredicates: predicates)
}
// Add sortDescriptors
if sortDescriptors.count > 0 {
request.sortDescriptors = sortDescriptors
}
return request
}
}
Finally this is how the CoreDataHelper looks like.
class CoreDataHelper: NSObject {
var context: NSManagedObjectContext!
var model: NSManagedObjectModel!
var coordinator: NSPersistentStoreCoordinator!
var store: NSPersistentStore!
let storeFilename = "Accounting.sqlite"
func setupCoreData() {
self.loadStore()
}
func saveContext() {
if (self.context.hasChanges) {
do {
try context.save()
} catch {
}
}
}
func applicationDocumentDictionary() -> String {
let directory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last!
NSLog("SQLite Directory : %#", directory)
return directory
}
func applicationStoresDirectory() -> URL {
let storesDirectory = URL.init(fileURLWithPath: self.applicationDocumentDictionary()).appendingPathComponent("Stores")
let fileManager = FileManager.default
if (!fileManager.fileExists(atPath: storesDirectory.path)) {
do {
try fileManager.createDirectory(at: storesDirectory,
withIntermediateDirectories: true,
attributes: nil)
} catch {
}
}
return storesDirectory
}
func storesURL() -> URL {
return self.applicationStoresDirectory().appendingPathComponent(storeFilename)
}
override init() {
super.init()
model = NSManagedObjectModel.mergedModel(from: nil)
coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
context.persistentStoreCoordinator = coordinator
}
func loadStore() {
if (store != nil) {
return
} else {
do {
try store = coordinator.addPersistentStore(ofType: NSSQLiteStoreType,
configurationName: nil,
at: self.storesURL(),
options: nil)
} catch {
}
}
}
static func getCoreDataHelper() -> CoreDataHelper {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.coreDataHelper
}
static func getContext() -> NSManagedObjectContext {
return getCoreDataHelper().context
}
}
Just to let you know that Country class has alpha3Code.
extension Country {
#nonobjc public class func fetchRequest() -> NSFetchRequest<Country> {
return NSFetchRequest<Country>(entityName: "Country");
}
#NSManaged public var englishName: String?
#NSManaged public var frenchName: String?
#NSManaged public var alpha2Code: String?
#NSManaged public var alpha3Code: String?
#NSManaged public var countryNumber: Int16
}
Use the recommended format specifier %K for a key(path) rather than %# as described in the Predicate Documentation
predicates.append(NSPredicate.init(format: "%K = %#", attributes[1], getString(from: id, withKeyValue: attributes[1])))

How to write into the CoreData entity at the same index in different view controller (also swift files)

I have created core data using 'NSFetchedResultController' and 'managedObjectContext' in a table view. But in the later view controller, after gathering accelerometer data and conduct calculation, I will get some results that I also want to store in the same row index with the core data I created before.
How can I achieve this? If I create managedObjectContext again, it will create another 'row' of core data in this table.
The code in tableViewController:
'
let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext
var fetchedResultController: NSFetchedResultsController = NSFetchedResultsController()
override func viewDidLoad() {
super.viewDidLoad()
fetchedResultController = getFetchedResultController()
fetchedResultController.delegate = self
fetchedResultController.performFetch(nil)
}
func getFetchedResultController() -> NSFetchedResultsController {
fetchedResultController = NSFetchedResultsController(fetchRequest: trialFetchRequest(), managedObjectContext: managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil)
return fetchedResultController
}
func trialFetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Trials")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: true)]
return fetchRequest
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
let numberOfSections = fetchedResultController.sections?.count
return numberOfSections!
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let numberOfRowsInSection = fetchedResultController.sections?[section].numberOfObjects
return numberOfRowsInSection!
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let trial = fetchedResultController.objectAtIndexPath(indexPath) as Trials
cell.textLabel?.text = trial.trialName
cell.detailTextLabel?.text = trial.date?.description
return cell
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
let managedObject:NSManagedObject = fetchedResultController.objectAtIndexPath(indexPath) as NSManagedObject
managedObjectContext?.deleteObject(managedObject)
managedObjectContext?.save(nil)
}
func controllerDidChangeContent(controller: NSFetchedResultsController!) {
tableView.reloadData()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "showTrial" {
let indexPath = tableView.indexPathForSelectedRow()
let trial:Trials = fetchedResultController.objectAtIndexPath(indexPath!) as Trials
let trialController:TrialDetailViewController = segue.destinationViewController as TrialDetailViewController
trialController.trial = trial
}
}
'
The code in the createTrial Controller:
' let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "createTrial" {
if theTrialName.text != "" {
createTrial()
} else {
let alertView = UIAlertController(title: "", message: "Trial name couldn't be empty", preferredStyle: .Alert)
alertView.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
presentViewController(alertView, animated: true, completion: nil)
}
}
}
func createTrial() {
let entityDescripition = NSEntityDescription.entityForName("Trials", inManagedObjectContext: managedObjectContext!)
let trial = Trials(entity: entityDescripition!, insertIntoManagedObjectContext: managedObjectContext)
trial.trialName = theTrialName.text
trial.location = theLocation.text
trial.notes = theNotes.text
if theArm.on {
trial.arm = 1
} else {
trial.arm = 0
}
managedObjectContext?.save(nil)
}
'
ps. the view controller I want to get data from is not this following segue, it is around 3 view afterwards. And I have created a string to store the data I need in that view.
I solved the problem by creating the object in the tableViewControllerand use segue twice to transmit it to secondViewControllerand thirdViewController. So it will be at the same index for the whole time. And I can change the content of the core data at both the following view controllers.

Resources