I want to extend my generated NSManagedObject classes (data mapping, init, utility functions). I was doing this with categories, but doing two imports got old real fast. I saw that MagicalRecord subclassed the generated files (https://github.com/magicalpanda/MagicalRecord/tree/develop/Samples/iOS/Application/Models). I tried this approach, but ran into the following problem.
[foo.bar myExtensionMethod];
Where foo is of class _foo and bar is of class _bar. The method myExtensionMethod is in the subclass of _bar named bar. I get a syntax error along the lines of _bar does not have function myExtensionMethod.
question
Is there a way to extend generated NSManagedObject classes that doesn't require two imports or something like modgenerator? As I regenerate the files, manually editing the generated files isn't an option.
The classes with underscore (_Foo, _Bar) are overwritten by mogenerator with the
current properties of your Core Data entities, and you should not modify these.
Your extension methods should go into the classes without underscore (Foo, Bar),
and you need only include "Foo.h" or "Bar.h".
Related
I have a rather large Dart application that uses part and part of so that I don't have to use relative imports. However, the application may have something like this at the entry point file:
part 'file1.dart';
part 'file2.dart';
part 'file3.dart';
part 'some_sub_dir/file1.dart';
part 'some_sub_dir/file2.dart';
part 'some_sub_dir/file3.dart';
part 'some_sub_dir/file4.dart';
part 'some_sub_dir/file5.dart';
part 'some_sub_dir/file6.dart';
...
As far as I know, my IDE (WebStorm) doesn't automatically add a part statement when I create a new class. Is there any way I can avoid having to use so many parts? If not, can the process of adding new parts each time be automated?
I understand your problem as I can and I'll try to answer from my experience in Dart.
As I got it you are trying to keep all (or a lot) project files as parts of one library. It's wrong conception. In Dart library is not big thing. Here is few advices how to organize your files.
Don't try to keep a lot of files as parts of one library. Rather keep each file as separated library.
You can keep few classes in one file. But be sure classes works together for one idea.
You can split one library in few part files only if it has a lot of classes or one class is too big. But be sure all this files should be together in one library.
If you don't know how to combine classes in libraries keep each class in separated library. After days you will get understanding which classes plays together.
If one class from one library has usages in not only library but in other libraries - make it separated library.
Place parts in same folder with main library file.
If library has parts put all library files into separated folder.
Use relative links to parts.
Always use absolute links to other libraries. It will help you to make refactoring in future.
For example, this is a project like TODO list application. So, we have view class:
// This is a view html component class. //
library todolist.list_viewer;
import 'package:todolist/task.dart'; // model class
class ListViewer extends HtmlElement {
// it showes list of tasks
}
class TodoRenderer extends HtmlElement {
// this is a renderer for one todo item
}
And this is a model class:
// This is a todo model task //
library todolist.task;
class TodoProvider {
List<TodoItem> todos;
String addItem(TodoItem new Todo) {
//...
}
}
class TodoItem {
String Author;
DateTime date;
}
It looks simple now, divided into separated libraries. But if we want to add RecId class to keep todo database id it becomes too complex. We should split it in two libraries: todo_provider and todo_model and put RecId class into last one. Now it's good again.
If we wanna add one more model: a User, so each todo item may have executor or author. We can't just put it todo_model. Now we should to combine TodoItem and User classes into model library. So we just rename todo_model class to model and add User class into it.
Or instead last action we can make user_model library to keep User class. And as User model has recId property too we should extract RecId class into separated library.
It's all depends on how our classes big and complex.
I understand that:
part/part of is used to break a library into several parts (scripts). You have visibility to public and private members.
import is to "call/use" another library from your library. You have only visibility to public members of the imported library.
WebStorm can't infer you want a script to be part of your library.
While a class usually has the same name as it's contained class - how about the filename of a struct? The below example actually works.
File names and files themselves are completely arbitrary. You can put multiple object type declarations in one file, and they need have nothing to do with the name of the file. (You can also spread out an object type declaration over multiple files, thanks to extensions.) And the names of those types are unrelated to the name of the file.
The reason for giving a file a name that has something to do with its contents is so that you can find those contents; it does not affect the behavior or compilation of the program in any way.
Okay, exceptions:
In Swift, only main.swift has special behavior based on its name - and you don't have a main.swift.
Privacy in Swift is file-based, so you want to separate object type declarations that need to keep things private from each other into separate files.
They usually do but in Swift you honestly can call any file anything you want. I have many different files with not directly related names, some with one class, some with multiple, some with just structs, some with class(es) and structs. The new class function in Xcode will give it a specific name but that was never necessary.
I'm trying to add a new file to my Xcode project using Xcode 6.1.1 and Xcode now has a "File type" option where you select between "Empty File, Category, Protocol, Extension"
Can someone explain the differences between these and what the default to select would be? My file is a subclass of NSObject.
Thanks
Category
Categories are used to help modularize and organize class definitions. They allow you to take a (complex) class definition and spread it over several organized classes. It is not the same as subclassing. Although categories do allow you to override methods, Objective-C has no way of determining which method definition should be used, so you should never use a category to override methods. Instead, create a subclass that overrides the method as per usual.
Categories can contain protected methods, which "allow arbitrary files to 'opt-in' to a portion of an API by simply importing the category." (Check out the articles linked below.)
Extension
Extensions provide similar functionality to categories, except that you must implement the extension's API in the main implementation file.
Extensions can also be used to create a formal private API. Ordinarily, if you wanted to create private methods, you would write them in the implementation block, but would exclude them from the interface block. However, if you have an extensive group of methods that you would like to remain private, this becomes cumbersome and difficult to read/maintain. Using extensions, you can define the private methods in both the interface and implementation blocks of the .m file. As long as you do not include it in the respective .h file, these methods will be treated as private methods.
Extensions can also be used to make previously declared properties that are read-only outside the class read-write within the class (using the "self." syntax).
Protocol
Protocols allow for abstracted horizontal relationships across various (sometimes unrelated) classes and class hierarchies. A protocol consists of an API that can be used by a variety of classes, regardless of whether or not they are related. This allows you to modify/add some class functionality through a potentially wide range of classes without having to subclass them and alter their own class hierarchies.
In order to use a protocol, a class only needs to:
1. Include the protocol's name inside angled brackets <> after the class/superclass name declaration
2. Implement the protocol's methods
Protocols can also be useful for type checking.
Empty File
An empty file is just that - an empty file. You give it a name, but it contains no class information whatsoever (no generated methods, blocks, comments, etc.).
Sources: RyPress article on Categories and Extensions and RyPress article on Protocols. Both articles have helpful examples of each tool.
I have a plist file that contains a top level dictionary and that dictionary contains an array of strings.
I want to test:
That the dictionary is not nil
That the array is not nil
And that the array has at least one valid string object in it
I have these unit tests running great. Very de-coupled. But the problem is I have to make the class functions public in order for Xcode XCTest to be able to test them. These 3 functions are simply helper functions to get the actual data we need.
How do I employ proper visibility on these helper functions while keeping my tests? No one needs to know about these 3 functions, but I want them tested.
There are two solid options for this:
Create a second .h file named something like MyClass_TestHelpers.h where you can declare those methods you need.
Create a category on the class titled something like 'TestHelpers'.
Both do essentially the same thing: declare methods in another .h file. In either case, just include that .h file in the test class. This way the methods are only exposed to your tests.
I am learning objective-C and I know we can use extension to add some private members to an interface.
But the book said there should be nothing in the ()
I read the following code snippet
#interface Tree(Private)
- (void)blah:(int)num;
#end
I am wondering why there is Private inside ()
You can put any name in the class category declaration, usually indicating the purpose of that category.
So in your case author of the code wanted to tell that those methods are for internal use of the class itself and are not intented to be called from other classes
The declaration in your example is precisely called a category (not an extension).
You can add as many categories as you like to any given Class (even if you don't have access to the source code). Categories allow you to add new methods to a class, but not new ivars nor properties. [1]
Each category has a name, which is the bit between parenthesis. There should not be two different categories for the same Class with the same name.
When the name is empty, this is called an extension. Extensions have some slight differences with categories: you can add ivars and properties to extensions and you can only use them for Classes for which you have access to the source code. [1]
Usually, extensions (like the example in your book) are declared at the top of the .m file, and are used for declaring methods, ivars and/or properties that are to be used only within that file (usually comprised of a single Class).
P.D.: If you really want to add new properties through categories as opposed to through extensions you can actually do so using associated objects [2][3].
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html
Defining a property in iOS class extension
http://oleb.net/blog/2011/05/faking-ivars-in-objc-categories-with-associative-references/
In the case that is considered as a category, but since it's on the .m file, it will have the same effect. You can also see the tips from Xcode:
Being the mid one considered something like Tree(description) and the last one Tree ()
There are two closely related concepts here: class categories and class extensions. Class categories include a name inside the parenthesis and are most commonly used to add methods to existing classes or to organize methods into logical groups. Class extensions extend the internal implementation of the class (i.e. are used to define private properties, methods, etc).
More details can be found on Apple's dev site:
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html