How do I avoid the import loop if I need imported protocols?

In objective-C, I made 11 classes, subclassing RLMObject, to represent my database model. And at the moment I have a problem building my app with this because, as the title suggests, they don't seem to see each other. Also: they are in the same folder, #import does not pose any problem.

As an example, I want to provide two classes Below is the class for books:

#import <Realm/Realm.h>
#import "Chapter.h"

@interface Book : RLMObject

@property NSInteger id;
@property NSString *name;
@property RLMArray<Chapter> *chapters;

@end

// This protocol enables typed collections. i.e.:
// RLMArray<Book>
RLM_ARRAY_TYPE(Book)

      

The next would be my class for chapters:

#import <Realm/Realm.h>

@class Book;

@interface Chapter : RLMObject

@property NSInteger id;
@property NSString *name;
@property Book *book;

@end

// This protocol enables typed collections. i.e.:
// RLMArray<Chapter>
RLM_ARRAY_TYPE(Chapter)

      

In Book.h I get:

Unable to find protocol declaration for 'Chapter'

Does anyone have any ideas? It's definitely some kind of import circle. But how can I solve this? If not necessary, I would like to avoid putting all the model classes in the prefix header.

EDIT: importing @class helped in the chapter file, but it's not in the Book file

+3


source to share


2 answers


You can also make a protocol declaration for the objects you want to use on the list property as shown below:

#import <Realm/Realm.h>

@protocol Chapter;

@interface Book : RLMObject

@property NSInteger id;
@property NSString *name;
@property RLMArray<Chapter> *chapters;

@end

// This protocol enables typed collections. i.e.:
// RLMArray<Book>
RLM_ARRAY_TYPE(Book)

      

Note. For the relationship "one to one" you need to use @class

, and @protocol

for the relationship "one to many".


In addition, I would recommend for your script to use a back link from a chapter in a book instead of properties. There are two independent properties in your question that don't automatically sync .



If you don't support it correctly, it could lead to something like this:

Books:

  • id: 0, name: "Moby Dick", chapters: [Chapter # 0, Chapter # 1]
  • id: 1, name: "Fast programming language", chapters: [Chapter # 2, Chapter # 3]

Chapters:

  • id: 0, name: "Loomings.", book: Book # 0
  • id: 1, name: "The Carpet-Bag.", book: Book # 0
  • id: 2, name: "About Swift", book: Book number 1
  • id: 3, name: "Swift Tour", book: Book number 0

See how "Swift Tour" refers to "Moby Dick", although this is clearly the second chapter of the Swift book. Your model currently allows this, but you can define it in such a way as to prevent such scenarios from ever existing.

A backlink solution would look like this:

@interface Chapter : RLMObject

@property NSInteger id;
@property NSString *name;
@property (readonly) Book *book;

@end

@implementation Chapter
// Define "book" as the inverse relationship to Book.chapters
- (Book *)book {
    return [self linkingObjectsOfClass:@"Book" forProperty:@"chapters"].firstObject;
}
@end

      

+4


source


Ok I figured out the way:

I created a header file ModelProtocols.h and added all the protocols for typed collections to this file:

#ifndef Your_Project_ModelProtocols_h
#define Your_Project_ModelProtocols_h

@class Book;
@class Chapter;

// This protocol enables typed collections. i.e.:
// RLMArray<Book>
RLM_ARRAY_TYPE(Book)

// This protocol enables typed collections. i.e.:
// RLMArray<Chapter>
RLM_ARRAY_TYPE(Chapter)

#endif

      



Once I installed this file, I needed to import it into my model classes:

#import "ModelProtocols.h"

      

and can be used @class

for the rest of my model classes. This is just fine, I have to test it anyway, but it should work.

+1


source







All Articles