diff --git a/Cocoa Programming Guidelines.pdf b/Cocoa Programming Guidelines.pdf index d4bba63..2351787 100644 Binary files a/Cocoa Programming Guidelines.pdf and b/Cocoa Programming Guidelines.pdf differ diff --git a/Cocoa Programming Guidelines.tex b/Cocoa Programming Guidelines.tex index 299f196..cbb200f 100644 --- a/Cocoa Programming Guidelines.tex +++ b/Cocoa Programming Guidelines.tex @@ -949,4 +949,133 @@ The following getter implementation traverses view controller hierarchy, and ret \end{codelisting} +\section{Core Data} + + +\begin{importantlisting} +NSManagedObject's properties must not be prefixed with "new". Due to @dynamic compiler directive, the following compiler error is suppressed: "property's synthesized getter follows Cocoa naming convention for returning 'owned' objects". +\end{importantlisting} + + +\subsection{Category provides helper methods to managed object} + +NSManagedObject subclasses can be generated by Xcode schema editor automatically. + +\begin{codelisting} +@interface Person : NSManagedObject + +@property (nonatomic, retain) NSString * name; +@property (nonatomic, retain) NSString * surname; + +@end +\end{codelisting} + +Therefore, all helper methods are kept in a category in a separate file, otherwise they would be overridden by the editor. + +\begin{codelisting} +@interface Person (Additions) + +- (NSString *)fullName; + +@end +\end{codelisting} + +\subsection{Custom objects are stored as transformable attributes} + +A custom object can be stored by Core Data as a transformable attribute, if it conforms to NSCoding protocol. Xcode schema editor uses id for this attributes, which deprives developer of good type checking. + +\begin{codelisting} +@interface Person : NSManagedObject + +@property (nonatomic, retain) id eyeColorTransformableType; + +@end +\end{codelisting} + +To ameliorate the situation, a property with the proper class type is provided by a category. + +\begin{codelisting} +@interface Person (Additions) + +@property (strong, nonatomic) UIColor * eyeColor; + +@end +\end{codelisting} + +Consequently the original property is never used except by the shadowing property's accessors. + +\begin{codelisting} +@implementation Person (Additions) + +- (void)setEyeColor:(UIColor *)eyeColor +{ + self.eyeColorTransformableType = eyeColor; +} + +- (UIColor *)eyeColor +{ + return self.eyeColorTransformableType; +} + +@end +\end{codelisting} + + +\subsection{Objective-C types are stored through NSValue} + +NSValue is a simple container for Objective-C data types. It conforms to NSCoding protocol, thus can be stored by Core Data as transformable attribute. + +\begin{codelisting} +@interface Figure : NSManagedObject + +@property (nonatomic, retain) id imaginaryPositionTransformableType; // stores NSValue object + +@end +\end{codelisting} + +A category provides a shadowing property for the convenience. + +\begin{codelisting} +struct ComplexNumber { + float real; + float imaginary; +}; +typedef struct ComplexNumber ComplexNumber; + +extern ComplexNumber const ComplexNumberZero; + + +@interface Figure (Additions) + +@property (assign, nonatomic) ComplexNumber imaginaryPosition; + +@end +\end{codelisting} + +The getter initializes the local variable so it does not return uninitialized value, if the shadowed property is nil. + +\begin{codelisting} +@implementation Figure (Additions) + +- (ComplexNumber)imaginaryPosition +{ + ComplexNumber imaginaryPosition = ComplexNumberZero; + [self.imaginaryPositionTransformableType getValue:&imaginaryPosition]; + return imaginaryPosition; +} +\end{codelisting} + +The setter creates NSValue object with the passed value, and stores it. + +\begin{codelisting} +- (void)setImaginaryPosition:(ComplexNumber)imaginaryPosition +{ + NSValue * value = [NSValue valueWithBytes:&imaginaryPosition objCType:@encode(ComplexNumber)]; + self.imaginaryPositionTransformableType = value; +} + +@end +\end{codelisting} + + \end{document}