ghostrider
ghostrider

Reputation: 5259

Fetching CoreData in IOS

I am new to CoreData and I am going through some tutorials.

Here is my data model :

Data model

and I want to build something similar to live scores. So I have added some demo data that follow this format :

// -------------------------------------------------------------------------
// --   GW :    1                                           2
//              |                                           |
//          Premier League                               Primera
//         /            \                                   |
//  Chelsea vs M.City  Arsenal vs Liverpool      Real Mad vs Barcelona
// -------------------------------------------------------------------------

and I can verify that they are saved as you can see from the below screenshots :

Table 1

Table 2

So, now everything I need is to fetch these data into my app. I have added these debug functions :

# pragma -
# pragma  mark - different fetch functions

- (void) fetchGameweeksAndLeagues {
    /*
     Set up the fetched results controller.
     */
    NSLog(@"Fetch Gameweeks and Leagues");
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entityGW = [NSEntityDescription entityForName:@"GameWeek" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entityGW];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    NSError *fetchError = nil;
    NSArray *result = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];

    if (!fetchError) {
        for (NSManagedObject *managedObject in result) {
            NSLog(@"GwId:%@, League: %@", [managedObject valueForKey:@"gwId"], [[managedObject valueForKey:@"leagues"] valueForKey:@"leagueName"]/*,[[managedObject valueForKey:@"matches"] valueForKey:@"homeTeam"],[[managedObject valueForKey:@"matches"] valueForKey:@"awayTeam"]*/);
        }

    } else {
        NSLog(@"Error fetching data.");
        NSLog(@"%@, %@", fetchError, fetchError.localizedDescription);
    }
}

-(void) fetchMatchesForLeagueWithId/*:(NSNumber*)leagueId*/
{
    NSLog(@"Fetch Matches for specific League");
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entityLeague = [NSEntityDescription entityForName:@"League" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entityLeague];


    NSError *fetchError = nil;
    NSArray *result = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];

    if (!fetchError) {
        for (NSManagedObject *managedObject in result) {
            NSLog(@"League: %@, Teams : %@ vs %@", [managedObject valueForKey:@"leagueName"],[[managedObject valueForKey:@"matches"] valueForKey:@"homeTeam"],[[managedObject valueForKey:@"matches"] valueForKey:@"awayTeam"]);
        }
    } else {
        NSLog(@"Error fetching data.");
        NSLog(@"%@, %@", fetchError, fetchError.localizedDescription);
    }
}

So, my output is :

2015-03-24 17:38:42.236 SofaRef[73743:2215371] GwId:1, League: {(
    "Premier League"
)}
2015-03-24 17:38:42.236 SofaRef[73743:2215371] GwId:2, League: {(
    Primera
)}
2015-03-24 17:38:42.236 SofaRef[73743:2215371] Fetch Matches for specific League
2015-03-24 17:38:42.237 SofaRef[73743:2215371] League: Primera, Teams : {(
    "Real Madrid"
)} vs {(
    Barcelona
)}
2015-03-24 17:38:42.237 SofaRef[73743:2215371] League: Premier League, Teams : {(
    Chelsea,
    Arsenal
)} vs {(
    Liverpool,
    "Man.City"
)}

So, how I can print them in the correct order ?

I want to print them actually in the same way they are in the DB and in the same order. Meaning that print Chelsea vs Man.City and Arsenal vs Liverpool and not "grouped by" columns - I want to fetch them as "rows".

Upvotes: 0

Views: 67

Answers (2)

Denis Kotadiya
Denis Kotadiya

Reputation: 1

//Core Data Demo

import UIKit
import CoreData

class ViewController: UIViewController

{
@IBOutlet var txt_add: UITextField!
@IBOutlet var txt_name: UITextField!
let contex = ((UIApplication.shared.delegate) as! AppDelegate).persistentContainer.viewContext;
override func viewDidLoad()
{
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}
@IBAction func btn_insert(_ sender: UIButton)
{
    let entity = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: contex);
    entity.setValue(txt_name.text, forKey: "empname");
    entity.setValue(txt_add.text, forKey: "empadd");
    do
    {
        try contex.save();
    }
    catch
    {

    }
}
@IBAction func btn_select(_ sender: UIButton)
{
    let entitydic = NSEntityDescription.entity(forEntityName: "Employee", in: contex);
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Employee")
    request.entity = entitydic;
    let pred = NSPredicate(format: "(empname = @%)", txt_name.text!);
    request.predicate = pred;
    do
    {
        let arr = try contex.fetch(request);
        if arr.count > 0
        {
            let obj = arr[0] as! NSManagedObject;
            txt_name.text = obj.value(forKey: "empname") as? String;
            txt_add.text = obj.value(forKey: "empadd") as? String;
        }
    }
    catch
    {

    }
}
@IBAction func btn_update(_ sender: UIButton)
{
    let entitydic = NSEntityDescription.entity(forEntityName: "Employee", in: contex);
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Employee")
    request.entity = entitydic;
    let pred = NSPredicate(format: "(empname = %@)", txt_name.text!);
    request.predicate = pred;

    do
    {
        let arr = try contex.fetch(request);
        if arr.count > 0
        {
            let obj = arr[0] as! NSManagedObject;
            obj.setValue(txt_name.text, forKey: "empname");
            obj.setValue(txt_add.text, forKey: "empadd");

            do
            {
                try  contex.save();
            }
            catch
            {

            }
        }
    }
    catch
    {

    }

}

@IBAction func btn_delete(_ sender: UIButton)
{
    let entitydic = NSEntityDescription.entity(forEntityName: "Employee", in: contex);
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Employee");
    request.entity = entitydic;
    let pred = NSPredicate(format:"(empname = %@)", txt_name.text!);
    request.predicate = pred;
    do
    {
        let arr = try contex.fetch(request);
        if arr.count > 0
        {
            let obj = arr[0] as! NSManagedObject;
            contex.delete(obj)

            do
            {
                try contex.save();
            }
            catch
            {

            }
        }
    }
    catch
    {

    }
}
override func didReceiveMemoryWarning()
{
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
}

Upvotes: 0

pbasdf
pbasdf

Reputation: 21536

Because the relationship from League to Match is one-to-many, the matches property of League returns an NSSet, i.e. [managedObject valueForKey:@"matches"] is an NSSet. In your NSLog statement, you use:

[[managedObject valueForKey:@"matches"] valueForKey:@"homeTeam"]

This takes each element of the aforementioned NSSet, obtains the homeTeam property value, and returns the results as a new NSSet. When you log this NSSet, it lists all the values:

{(
    Chelsea,
    Arsenal
)}

But since NSSet is unordered, the results might be in any sequence. Indeed, as your results show, the value

[[managedObject valueForKey:@"matches"] valueForKey:@"awayTeam"]

is in the reverse order:

{(
    Liverpool,
    "Man.City"
)}

What you need to do is log each match separately, showing the homeTeam and awayTeam for each. You can do this by nesting another for loop:

    for (NSManagedObject *managedObject in result) {
        NSLog(@"League: %@", [managedObject valueForKey:@"leagueName"]);
        for (NSManagedObject *match in [managedObject valueForKey:@"matches"]) {
            NSLog(@"Teams : %@ vs %@", [match valueForKey:@"homeTeam"],[match valueForKey:@"awayTeam"]);
        }
    }

That will ensure that your output appears in "rows" rather than "columns". But it is still presenting the matches in a random sequence, which may or may not match up with the sequence in the SQL database. In general, you should not assume that the entries in the database are in any particular order. If the order is important, you should specify it when you fetch the values from the database (or sort them once they have been fetched). To achieve this, use an NSSortDescriptor. Suppose your preference is that the matches are sorted with the homeTeam in alphabetical order; use the following sortDescriptor:

NSSortDescriptor *homeTeamSort = [NSSortDescriptor sortDescriptorWithKey:@"homeTeam" ascending:YES];

The set that you wish to sort is the matches relationship, so amend the above code as below:

    for (NSManagedObject *managedObject in result) {
        NSLog(@"League: %@", [managedObject valueForKey:@"leagueName"]);
        NSSortDescriptor *homeTeamSort = [NSSortDescriptor sortDescriptorWithKey:@"homeTeam" ascending:YES];
        NSArray *sortedMatches = [[managedObject valueForKey:@"matches"] sortedArrayUsingDescriptors:@[homeTeamSort]];
        for (NSManagedObject *match in sortedMatches) {
            NSLog(@"Teams : %@ vs %@", [match valueForKey:@"homeTeam"],[match valueForKey:@"awayTeam"]);
        }
    }

Upvotes: 1

Related Questions