Why have multiple classes in one source file? - objective-c

I was going over a sample Cocoa app from Apple (ImageKitDemo) and noticed that one of the source files (the .m file) actually contains the definition (interface and implementation) of another class. What are the benefits of doing this?

It also has the added benefit of emphasizing the fact that a certain class is only intended to serve as an implementation detail of another class, and should not be used elsewhere.

Less total number of files in your project. Besides that, no difference. You could write an entire project in 1 .m file if you really wanted to.

Related

Why Xcode allows create duplicate Objective-C Category?

Xcode does not allow you to create duplicate class file. I'm curious why it allows you to create duplicate category file in different folders.
eg:
A folder
--- NSObject+Test
B folder
--- NSObject+Test
The project can run normally.
Xcode and Objective-C do allow you to create duplicate class files. What it doesn't allow you to do is create duplicate classes. In Objective-C, it is traditional to name the file with the same name as the class, but this is neither universal, nor enforced.
The question I think you're asking is why does Objective-C allow multiple categories with the same name (regardless of what file they're in). The reason is because Objective-C doesn't really care very much what the name of a category is. Originally categories were a way to organize large classes into multiple files (which is why they're called "categories" rather than "extensions"). Eventually they came to be used to add new methods to existing classes. At no point along the way has the compiler really bothered very much with the category names (the part in parentheses). They're generally treated as a comment.
I wouldn't assume there was a specific moment when the language designers decided "it should be legal to have multiple categories with the same name." There's just never been checked for or prevented.
The more interesting and important collision is that two categories can add the same method name. This isn't prevented by the compiler but is actually a serious problem. It's not defined which method will execute and the compiler won't tell you you've made this mistake. This is why it's important to prefix category method names to prevent collisions. It's a good idea to prefix category names, too, for consistency.
Why should the compiler care about the file name? Never heard that a compiler does such a thing.
And there might be reasons, i. e. if in Folder A resp. Folder B are different versions or configurations of the software.

What is the purpose of SomeClass+CoreDataClass files?

I'm trying to understand how Core Data works in Objective-C and can't quite get the purpose of categories that have the name SomeClass+CoreDataClass and are created when we want to subclass NSManagedObject.
As far as I know, they should be created only once and not regenerated every time we need to update our entity's structure, so we can add our methods there. However, they are recreated as blank files every time I regenerate a subclass of NSManagedObject.
I think, I'm missing something, so could you explain their purpose?
+CoreDataClass is generated by xcode, you shouldn't edit it, because you can loose changes.
You can edit SomeClass, Xcode will only create it if it isn't exist.
This division was made just for programmers convenience.
You can freely move code from +CoreDataClass to main file and delete category if you wish.

Get Coco Class files programmatically

Using the objc/runtime.h we can create classes at runtime. How to export the .h and .m files from that class which is created at runtime?
Creating a .h is conceptually possible, but you'd need to write the code yourself to do it (using ObjC runtime calls to inspect the class and then write the file by hand). I don't know of anyone who has written this code already, but writing it would likely be an excellent introduction to the ObjC runtime functions. Note that the .h probably wouldn't be very friendly. For example, all object types in method signatures will be id. So it's kind of useable, but I can't think of a lot of ways I'd want to.
Creating a .m here doesn't make a lot of sense. The implementation of a runtime-generated class is going to be a bunch of IMP pointers to existing functions (which are themselves already compiled code). I don't know what you'd expect to be in the .m. In principle you could scan the executable to work out the names of the functions, and then write out a .m that looked something like:
- (void)someMethod {
SomeMethod_IMP()
}
This would probably get pretty complicated, and I can imagine several corner cases that would bite you in the general case.
This generally isn't how dynamically-generated classes are used, though, in the fairly rare cases that they are used. They're ubiquitous in KVO (but you'd never want a .h from that), and other uses of them are kind of similar: they usually are some magical subclass of an existing interface, so you never interact with them directly (and they almost always have an identical API to their superclass). What problem are you really trying to solve?
To get the implementation, you'd have to find or write a tool to translate assembly back in to Objective-C.
For just generating a header (interface), there are tools available. Use Google.
You cannot just tell the Objective-C runtime to create a new class from the .h and .m files because it takes a compiler. You need to hard-code the creation inside your project.
Create a subclass with objc_allocateClassPair
Add methods with class_addMethod (and properties with class_addProperty...)
Then you can use the new class.

ObjC: Subclass a class whose #interface is inside a .m file

I am trying to subclass a class whose #interface and #implemetation are buried inside of another class' ".m" file in order to restyle some of the views declared within. The superclass is a cocoapod, which I am unable to modify without forking the repo, which I am really trying to avoid doing. Is there any clever/hacky way to pull this off, or is it simply impossible?
In all honesty, I fail to see why forking would be a bad idea or why you would want to avoid it. That's the entire point of forking, modifying the code to fit your need more and perhaps later merge it back if the community finds it useful as well.
You can try to hack around this by redeclaring the class or whatever, but that implementation would be far more fragile than you having a fork which you have full control over (including merging any upstream changes). I think this is more related to a mental block of thinking that a fork becomes "your" code and "your" responsibility, while in reality it is just as much to maintain as it would be to keep the hacky version working across changes to the 3rd party code.

Defining a category in the same .h/.m files of another class

Is it a good practice to define a category within the same .h/.m files of another class? I know it will build with no error and be exactly the same as if it was defined separately.
The main reason I want to do this is because I'm working on an open source control and I want it to have a single .h/.m file.
In general, the biggest problem with combining multiple classes and categories into the same header/implementation is impaired searchability. When a class is in a file with another class, the file name will no longer reflect the fact that the header/implementation contains your other class, making it much harder for others to look for your class.
If your project is small and self-contained, however, the searchability is less of an issue. When there is only one file to search, there is no question of where each particular piece of code is: it's all in that one file. It sounds like your project is both small and self-contained, so I see no problem in placing all code in a single source file if you want it that way.
Another alternative could be placing each class and category in a separate header/implementation pair of files, and then defining a header that includes them all. This would let you keep an ideal project organization, and let your users include a single header to use your component.
If you need this category in just one place I’d say that it’s not that bad having the category within the .m file.
Obviously, if you need that category in multiple places, you should definitely move to its own file: the convention is to name it in this way:
BaseClass+categoryName.{h,m}
e.g.:
NSString+reverseString.h
NSString+reverseString.m