iPhone Development – core data relationships tutorial part 1

I’m going to start a short series on Core Data relationships and maybe throw in some general Core Data stuff too. Here in part one we’re just going to set our app up with core data and add two entities with a simple one to one relationship between them. A one to one relationship means that for every Fruit there will be one source and in our case here the reverse it true too, for every source there is one fruit.

1.) Create a new Tab Bar Application named CoreDataRelationshipsTutorial.

2.) Change FirstView.xib so it looks similar to this.

3.) Add the core data framework to the app.

4.) Right click on Supporting Files and select New File, then choose Core Data select Data Model and hit Next. I just accepted the default name of Model and clicked save.

5.) Select Model.xcdatamodeld and the visual editor will open. Click Add Entity and name it Fruit. Add an Attribute named fruitName of type String. Add another Entity named Source with an Attribute sourceName, which will also be of type String.

6.) Select Fruit and then click the plus symbol under Relationships. Name the relationship fruitSource. Set the destination to Source, there will be no inverse yet. In the relationship data model inspector uncheck the Optional checkbox. In the delete rule select Cascade.

7.) Now select Source and add a relationship named sourceFruit. Destination should be Fruit and set the inverse to artistCareer. Uncheck the Optional checkbox again.

8.) Select Fruit under ENTITIES and then go under the file menu up top and select New File. Choose Core Data and NSManagedObject subclass,, click Next. Keep the default location and click Create.

Repeat this same process after selecting Source under ENTITIES.

You should now see your new objects listed under Supporting Files.

9.) Open up CoreDataRelationshipsTutorial-Prefix.pch and add an import for CoreDate. This saves us from having to import it into every file that will use it.


1

2

3

4

5

6

7

8

9

10

11

12

#import <availability.h>

 

#ifndef __IPHONE_3_0

#warning "This project uses features only available in iPhone SDK 3.0 and later."

#endif

 

#ifdef __OBJC__

    #import <uikit uikit.h="">

    #import <foundation foundation.h="">

    #import <coredata coredata.h="">

#endif

</coredata></foundation></uikit></availability.h>

10.) Now let’s add all the necessary Core Data code to the app delegate files.

First the header file. Import our FirstViewController, then declare private instance variables for our NSManagedObjectContext, NSManagedObjectModel and NSPersistentStoreCoordinator. Create an IBOutlet with out FirstViewController, and declare two methods that we’ll implement.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

#import <uikit uikit.h="">

#import "FirstViewController.h"

 

@interface CoreDataRelationshipsTutorialAppDelegate : NSObject <uiapplicationdelegate, uitabbarcontrollerdelegate="">

{

 

@private

    NSManagedObjectContext *managedObjectContext;

    NSManagedObjectModel *managedObjectModel;

    NSPersistentStoreCoordinator *persistentStoreCoordinator;

 

}

 

@property (nonatomic, retain) IBOutlet UIWindow *window;

@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;

 

@property (nonatomic, retain) IBOutlet FirstViewController *firstViewController;

 

@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;

@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;

@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;

 

- (NSURL *)applicationDocumentsDirectory;

- (void)saveContext;

 

@end

</uiapplicationdelegate,></uikit>

11.) Now open the app delegate implementation file. Synthesize our firstViewController, then set it’s managedObjectContext to the one created in the app delegate. You may see an error on the line that sets the managedObjectContext because we haven’t set that up in FirstViewController yet.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

#import "CoreDataRelationshipsTutorialAppDelegate.h"

 

@implementation CoreDataRelationshipsTutorialAppDelegate

 

@synthesize window=_window;

@synthesize tabBarController=_tabBarController;

@synthesize firstViewController;

 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

    firstViewController.managedObjectContext = self.managedObjectContext;

 

    self.window.rootViewController = self.tabBarController;

    [self.window makeKeyAndVisible];

    return YES;

}

Implement all these methods.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

/**

 Returns the URL to the application's Documents directory.

 */

- (NSURL *)applicationDocumentsDirectory

{

    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];

}

 

- (void)saveContext

{

     

    NSError *error = nil;

    NSManagedObjectContext *objectContext = self.managedObjectContext;

    if (objectContext != nil)

    {

        if ([objectContext hasChanges] && ![objectContext save:&error])

        {

            // add error handling here

            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

            abort();

        }

    }

}

 

#pragma mark -

#pragma mark Core Data stack

 

/**

 Returns the managed object context for the application.

 If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.

 */

- (NSManagedObjectContext *)managedObjectContext

{

     

    if (managedObjectContext != nil)

    {

        return managedObjectContext;

    }

     

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil)

    {

        managedObjectContext = [[NSManagedObjectContext alloc] init];

        [managedObjectContext setPersistentStoreCoordinator:coordinator];

    }

    return managedObjectContext;

}

 

/**

 Returns the managed object model for the application.

 If the model doesn't already exist, it is created from the application's model.

 */

- (NSManagedObjectModel *)managedObjectModel

{

    if (managedObjectModel != nil)

    {

        return managedObjectModel;

    }

    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];

     

    return managedObjectModel;

}

 

/**

 Returns the persistent store coordinator for the application.

 If the coordinator doesn't already exist, it is created and the application's store added to it.

 */

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator

{

     

    if (persistentStoreCoordinator != nil)

    {

        return persistentStoreCoordinator;

    }

     

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataTabBarTutorial.sqlite"];

     

    NSError *error = nil;

    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])

    {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

        abort();

    }

     

    return persistentStoreCoordinator;

}

12.) Open up FirstViewController.h and let’s set it up with the necessary code and instance variables.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

#import <uikit uikit.h="">

 

@interface FirstViewController : UIViewController

{

     

    NSFetchedResultsController  *fetchedResultsController;

    NSManagedObjectContext      *managedObjectContext;

 

}

 

@property (nonatomic, retain) NSString *fruitNameString;

@property (nonatomic, retain) NSString *fruitSourceString;

 

 

@property (nonatomic, retain) NSFetchedResultsController    *fetchedResultsController;

@property (nonatomic, retain) NSManagedObjectContext        *managedObjectContext;

 

- (IBAction) saveData;

 

@end

</uikit>

13.) Now for the implementation file. Let’s import our managed objects.


1

2

3

#import "FirstViewController.h"

#import "Fruit.h"

#import "Source.h"

Then synthesize the instance variables.


1

2

@synthesize fetchedResultsController, managedObjectContext;

@synthesize fruitNameString, fruitSourceString;

Let’s go ahead and set the values of those two strings in ViewDidLoad.


1

2

3

4

5

6

- (void)viewDidLoad

{

    [super viewDidLoad];

    fruitNameString = [[NSString alloc] initWithString:@"Apple"];

    fruitSourceString = [[NSString alloc] initWithString:@"Apple Tree"];

}

14.) Implement the saveData method.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

- (IBAction) saveData

{

    NSLog(@"saveData");

    Fruit *fruit = (Fruit *)[NSEntityDescription insertNewObjectForEntityForName:@"Fruit" inManagedObjectContext:managedObjectContext];

    fruit.fruitName = fruitNameString;

    Source *source = (Source *)[NSEntityDescription insertNewObjectForEntityForName:@"Source" inManagedObjectContext:managedObjectContext];

    source.sourceName = fruitSourceString;

     

    // Because we set the relationship fruitSource as not optional we must set the source here

    fruit.fruitSource = source;

     

    NSError *error;

     

    // here's where the actual save happens, and if it doesn't we print something out to the console

    if (![managedObjectContext save:&error])

    {

        NSLog(@"Problem saving: %@", [error localizedDescription]);

    }

 

 

    // **** log objects currently in database ****

    // create fetch object, this object fetch's the objects out of the database

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Fruit" inManagedObjectContext:managedObjectContext];

    [fetchRequest setEntity:entity];

    NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

     

    for (NSManagedObject *info in fetchedObjects)

    {

        NSLog(@"Fruit name: %@", [info valueForKey:@"fruitName"]);

        Source *tempSource = [info valueForKey:@"fruitSource"];

        NSLog(@"Source name: %@", tempSource.sourceName);

 

    }

    [fetchRequest release];

}

15.) Release our objects in the dealloc method and set them to nil in viewDidUnload.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

- (void)viewDidUnload

{

    [super viewDidUnload];

    fetchedResultsController = nil;

    managedObjectContext = nil;

    fruitNameString = nil;

    fruitSourceString = nil;

}

 

- (void)dealloc

{

    [fetchedResultsController release];

    [managedObjectContext release];

    [fruitNameString release];

    [fruitSourceString release];

 

    [super dealloc];

}

16.) Open up FirstView.xib and connect the UIButton to our saveData IBAction.

17.) Open up MainWindow.xib, select the app delegate and connect firstViewController outlet to FirstViewController under the Tab Bar Controller.

18.) Now you can run the app and hit the Save Data button. Look in the console to see the results of the fetch.

The important things to note from this tutorial are these.

When we created the relationship from Fruit to Source we made it so that it was not optional. Therefore during our saveData method we had to set the fruitSource to something.


1

2

3

4

Fruit *fruit = (Fruit *)[NSEntityDescription insertNewObjectForEntityForName:@"Fruit" inManagedObjectContext:managedObjectContext];

fruit.fruitName = fruitNameString;

Source *source = (Source *)[NSEntityDescription insertNewObjectForEntityForName:@"Source" inManagedObjectContext:managedObjectContext];

source.sourceName = fruitSourceString;

Try commenting out that last line


1

//    source.sourceName = fruitSourceString;

And then running it again. What happens? Crash and burn. Because the relationship is not optional you must set the sourceName.

You can also see from the block of code above that we use reuse the same managedObjectContext to create both of the managed objects. Then we set the values and just saved the context. Doing this saved both objects (entities in Core Data).

Another thing to take note of happens in the fetch process. You notice that we only fetch the Fruit entity. But because of the relationship between Fruit and Source we can access the Source entity. We don’t need to do a separate fetch on Source.


1

2

3

4

5

6

7

8

9

10

11

12

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Fruit" inManagedObjectContext:managedObjectContext];

[fetchRequest setEntity:entity];

NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

 

for (NSManagedObject *info in fetchedObjects)

{

    NSLog(@"Fruit name: %@", [info valueForKey:@"fruitName"]);

    Source *tempSource = [info valueForKey:@"fruitSource"];

    NSLog(@"Source name: %@", tempSource.sourceName);

    [tempSource release];

}

Okay that does it for this tutorial. Next time we will look at a one to many relationship.

As always here’s the code.

 

欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 330987132 | Go:217696290 | Python:336880185 | 做人要厚道,转载请注明出处!http://www.cnblogs.com/sunshine-anycall/p/3446905.html

时间: 2024-10-31 06:42:41

iPhone Development – core data relationships tutorial part 1的相关文章

iOS App开发中Core Data框架基本的数据管理功能小结_IOS

一.何为CoreDataCoreData是一个专门用来管理数据的框架,其在性能与书写方便上都有很大的优势,在数据库管理方面,apple强烈推荐开发者使用CoreData框架,在apple的官方文档中称,使用CoreData框架可以减少开发者50%--70%的代码量,这虽然有些夸张,但由此可见,CoreData的确十分强大. 二.设计数据模型在iOS开发中,时常使用SQL数据库对大量的表结构数据进行处理,但是SQL有一个十分明显的缺陷,对于常规数据模型的表,其处理起来是没问题的,例如一个班级表,其

Core Data浅谈系列之一 : 基础结构

Core Data是苹果官方提供的一套框架,用来解决与对象生命周期管理.对象关系图管理和持久化等方面相关的问题.大多数情况下,我们引入Core Data作为持久化数据的解决方案,并利用它将持久化数据映射为内存对象. 为什么要使用Core Data呢?以下几点可供参考: 有丰富且良好的文档,方便新手入门.老手埋坑.这些文档多半来源于Apple官方,以及Stackoverflow. 有着经过很多开发者检验的代码,除了省去我们编码的精力,还有着比我们自己编码更好的代码质量. 苹果出品使得它与OS X或

《Core Data应用开发实践指南》一2.12 后端SQL的可见性

2.12 后端SQL的可见性 如果只在控制台的日志中查看Core Data所输出的结果,那么意义并不算太大.你知不知道这些事情背后究竟发生了什么?Core Data对持久化存储区中的数据到底进行了哪些操作?这些操作是否恰当?为了提供无缝的Core Data体验,系统都生成了哪些SQL查询语句?每次在模拟器中运行程序的时候,是不是会插入重复的对象? 有个极其详尽的调试选项可以提供足够的信息,告诉你这些操作背后所发生的事情,从而令你知道上述那些问题的答案.这个调试选项会把系统自动生成的SQL查询语句

iOS 开发中使用 Core Data 应避免的十个错误

Core Data是苹果针对Mac和iOS平台开发的一个框架主要用来储存数据.对很多开发者来说Core Data比较容易入手但很难精通如果没有正确的学习方法你将很难真正理解它更不用说精通了.很多开发者常常在这方面犯一些错误而这篇文章列出了 开发者在iOS开发过程中使用Core Data常见的一些错误并对如何避免这些错误进行了分析. 1.不了解关键术语 对于iOS开发者来说会使用Core Data是一项必备技能. 没有它很多app都不会存在.当在互联网上四处搜索Core Data学习教程你很容易被

Core Data 版本迁移经验总结

大家在学习和使用Core Data过程中,第一次进行版本迁移的经历一定是记忆犹新,至少我是这样的,XD.弄的不好,就会搞出一些由于迁移过程中数据模型出错导致的Crash.这里总结了一下Core Data版本迁移过程中的经验,希望对大家有用. 写在前面 关于Core Data版本迁移,这两篇文章都进行了分析,大家可以参考. Core Data Model Versioning and Data Migration Programming Guide 自定义 Core Data 迁移 迁移准备 1)

《Core Data应用开发实践指南》一1.2 Core Data的适用场合

1.2 Core Data的适用场合 如果应用程序要保存的设置数据太多,以致NSUserDefaults及"特性列表"(property list)这种简单的存储方案无法应付,那么就会出现内存占用量方面的问题.解决办法是直接使用数据库或通过Core Data来间接操作数据库.选用Core Data的好处是,不用再花时间编写数据库接口的代码了.此外,你还将享受性能方面的优势,而且可以使用诸如撤销及验证等强大的功能.假如选择直接使用数据库,那就要花时间去做开发与测试工作,也就是通常所说的&

《Core Data应用开发实践指南》一2.6 单精度浮点数与双精度浮点数

2.6 单精度浮点数与双精度浮点数 对于属性来说,单精度浮点数(float)和双精度浮点数(double)这两种数据类型可以看作带小数点的非整数.它们都可以用来表示实数,但也都有一定的限制.单精度浮点数与双精度浮点数都使用以2为底的数制(也叫二进制),对CPU来说,这是一种原生的数制,它容易引起舍入误差.以1/5这个分数为例,如果采用十进制,那我们可以精确地将其写为0.2,但如果改用二进制,则只能表示出它的近似值.小数点后面的数位越多,精度就越高,表示出来的近似值也就越准确.高精度的数会占用更多

《Core Data应用开发实践指南》一1.3 创建Grocery Dude项目

1.3 创建Grocery Dude项目 Grocery Dude是个运行在iPhone上的范例程序,在学习本书的过程中,你将了解到它的制作流程.学会了Core Data中的某个特性或某项开发技巧之后,你可以将其运用在Grocery Dude程序上面.到了本书收尾的时候,你将会制作好一款功能完备而且运行速度很快的Code Data程序,它能够同iCloud紧密地集成在一起.假如你现在就想直接看看成品,那可以去App Store下载Grocery Dude.请注意,Grocery Dude是专门为

iOS7应用开发12:Core Data

Core Data:一种数据库机制,可以用于保存应用中需要永久保存的数据,是一种面向对象的数据库,在ios中应用极为广泛. 应用方法: (1)在xcode中建立一个visual mapping,即在新建文件中选择Core Data->Data Model.在Data Model文件中添加Entity,在Entity中添加attribute并设置类型.各个entity可以通过ctrl+拖动建立relation,并在右侧栏中设置relation的属性. (2)另一种方式:通过NSManagedObj