Compiling with a circular dependency between methods [duplicate] - objective-c

This question already has an answer here:
Does Objective-C allow circular dependencies?
(1 answer)
Closed 8 years ago.
I have two classes. Let's call them Dog and Cat.
In Dog I have an instance of Cat, and Dog has a method, harrassCat. Inside harrassCat, I invoke a Cat method, swipeAtDogsNose:, which uses properties of Dog to calculate its output.
The problem is in the header files. I import Cat's header file into Dog and create a property. I then access this property in harrassCat.
For now, I have an NSArray with all the required properties passed as arguments in swipeAtDogsNose:. I want to directly access the properties of Dog within swipeAtDogsNose:, but I cannot import the Dog header into the Cat header because it causes a circular dependency and it fails to compile.
I read on Stack Overflow that when you have circular dependency, you can use #class to access another class. How do I import Dog using #class so that the method declaration in Cat.h looks something like this:
- (BOOL)swipeAtDogsNose:(Dog *)theDog;

What you need is called forward declaration and declare it by just adding the declaration before the interface of the other class in the header file.
#class ClassB;
#interface ClassA
...
Mind that you don't need to do it, you need it just if any method signature requires a type which is not defined and cannot be imported in the header file, if you have a #property of that type or if you have class member of that type.
Basically: if the type name appears in the header then you need to forward declare it (or #import the header), otherwise you can just #import inside .m file. You don't have to import the header inside the other header, importing inside the implementation file is enough.

ClassA:
#class ClassB;
#interface classA
#property (strong, nonatomic) classB* propertyThatUseClassB
#end
ClassB:
#class ClassA;
#interface classB
#property (strong, nonatomic) classA* propertyThatUseClassA
#end

Related

Type arguments cannot be applied to non-class type 'id'

I am new to ObjectiveC and have been working for few years in Swift. Therefore, I don't understand the below explained error in Xcode:
Type arguments cannot be applied to non-class type 'id'
My Protocol:
#protocol ExampleProtocol<NSObject>
#required
-(NSString *)title;
-(NSString *)album;
#end
My implementation in the MyService.h file:
#interface MyService : NSObject
#property (nonatomic, assign, readwrite) id<ExampleProtocol> delegate;
#end
The error occurs in the line:
> #property (nonatomic, assign, readwrite) id<ExampleProtocol> delegate;
Additionally:
I have imported the required file .h in which the ExampleProtocol code is located in the MyService.m file
Added the #class ExampleProtocol; in my MyService.h file at the top.
Also tried:
Creating a Swift protocol with #objc and : class imported over the app-Bridging.h gives me the same result with the same error message.
Clean build
Clean build folder (removed derived data)
The only thing that did work was to remove the line from the public interface to the private. This doesn't make sense. I wan't to set the delegate from another class and creating a public setter which set the private delegate is ugly workaround.
Any suggestion would be helpfull. I would like to understand why this happens. There are a lot of other protocols in my project written in ObjectiveC which work fine.
ExampleProtocol is a protocol, not a class. You don't need it if you import the header. If you don't import the header, it should be #protocol ExampleProtocol;

Workaround to accomplish protected properties in Objective-C

I've been trying to find a workaround to declare #protected properties in Objective-C so only subclasses in the hierarchy can access them (read only, not write).
I read that there is no documented way of doing this so I thought of this workaround and I wanted to ask StackOverflow's opinion about it.
Every custom class at the top of the hierarchy contains three classes, one implementation and two interfaces.
Let's name them:
ClassA.h
ClassA_protected.h
ClassA.m
Then any subclass of this ClassA would be as usual:
ClassB.h
ClassB.m
First I created the interface ClassA.h where I declare a protected int variable so any subclass of ClassA can have access to it:
#interface ClassA : NSObject{
#protected
int _myProtectedInt;
}
#end
Next step is the workaround I was talking about. However, once you read it you will see that it is quite straight forward. I declared a second interface called ClassA_protected.h which actually works as an extension of ClassA.h and allows us to tag the property as readonly:
#import "ClassA.h"
#interface ClassA ()
#property (nonatomic , readonly) int myProtectedInt;
#end
Last step of preparing the protected hierarchy is to declare its implementation in ClassA.m where we only synthesize our property:
#import "ClassA_protected.h"
#implementation ClassA
#synthesize myProtectedInt = _ myProtectedInt;
#end
This way, every class that needs to be a subclass of ClassA.h, will import ClassA_protected.h instead. So a child like, for example ClassB.h, would be as follows:
#import "ClassA_protected.h"
#interface ClassB : ClassA
#end
And an example of accessing this property from ClassB.m's implementation:
#implementation ClassB
-(void) method {
//edit protected variable
_myProtectedInt= 1;
//normal access
self.muProtectedInt;
}
#end
Sure, that works fine. Apple uses the same approach for example in the UIGestureRecognizer class. Subclasses have to import the additional UIGestureRecognizerSubclass.h file and override the methods that are declared in that file.
For simple "properties" just use ivar instead. That's as good as properties for all practical purposes.
Moreover, the default is already protected.
If you ask for opinion, this is mine: If one decides to mutate your
_myProtectedInt
he will probably succed anyway, because it's definitely possible with Objective-C runtime. Except this, your solution is quite OK.
Import the protected header in the implementation only. e.g.
ClassB.h
#import "ClassA.h"
#interface ClassB : ClassA
#end
ClassB.m
#import "ClassA_protected.h"
#implementation ClassB
#end
And in a framework the protected header should be marked project so it is not included in the public headers of the framework. Apple usually use the suffix _Internal.h for their protected methods.
For init or overriding a lazy loaded get property you would need direct access to the #proteced ivar, however for your use it would be better to redeclare the property as readwrite instead then you can take advantage of any features of the setter, atomicity for example.

What's the logic of putting #interface in .m file? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between #interface definition in .h and .m file
What is the #interface declaration in .m files used for in iOS 5 projects?
I've seen code like this:
// In Header.h
#interface Header{}
#end
// In Header.m
#interface Header()
#end
My questions are:
What's the difference in putting it in 2 files?
Why put {} after class name in ".h" file and why "()" in ".m" file?
#interface MyClass(){
NSInteger aInt;
}
#property(nonatomic,strong) NSString *name;
#end
is a class extension
with modern compilers this is a great way, to decrale methods, ivars and properties only for private use in the class MyClass.
Class extensions have to be declared in the main implementation file (not in a category).
So you can hide implementation details from the header file, they are private.
This has become a common practice for declaring "private" properties/methods for a given class. By declaring them in an anonymous class extension inside the .m, these properties/methods are not exposed to consuming objects.

Varieties of #interface declarations, some with parentheses

I've noticed a variety of #interface declarations for Objective-c classes. I'd like to understand why developers declare #interface in the following ways:
// in the .h file
#interface MyClass : NSObject
// ...
#end
// in the .m file (what's the purpose of the parens?)
#interface MyClass ()
// more property declarations which seem like they can go in the .h file
#end
// again in the .m file (what's the purpose of private?)
#interface MyClass (Private)
// some method declarations
#end
This is just a normal class interface, inheriting from NSObject, where you declare ivars, properties and methods
// in the .h file
#interface MyClass : NSObject
// ...
#end
The following two are categories, which allow you to add methods to a class. It is not a subclass however (do not declare a method with the same name, as you won't be able to access the original one). If you have a named category of the interface (like #interface MyClass (Private)), then the implementation should be provided in #implementation MyClass (Private), in the case of unnamed categories (also called extensions), the implementation can be provided as usual. Note that extensions also allow you to add ivars to the class while (named) categories do not.
// in the .m file (what's the purpose of the parens?)
#interface MyClass ()
// more property declarations which seem like they can go in the .h file
#end
// again in the .m file (what's the purpose of private?)
#interface MyClass (Private)
// some method declarations
#end
It is used to declared private methods.
This response explain this in details: What are best practices that you use when writing Objective-C and Cocoa?
What ever goes in the .m file is private. the parens are for categories so you can segment your code into categories to make it more readable. because the code is in .m and private, they called the category Private.

hide #property in objective C

How to hide #property(retain, nonatomic)NSString*str in some class?
If you want to hide it from being visible in the .h file, consider using a private class extension in the .m file:
#interface YourClass ()
#property(retain, nonatomic)NSString*str;
#end
You can use a feature called “categories,” which allows you to extend an existing class by adding properties and methods to it.
Typically, you use an empty category inside your class's .m file for private methods and properties, and define a separate named category in an external .h file for protected members. Categories are actually quite interesting in that they allow you to override existing properties. So, for example, you can define a property as read-only in your .h file:
#interface Whatever {
NSObject *aValue;
}
#property (nonatomic,retain,readonly) NSObject *aValue;
#end
And then you can make it read/write for your own private use in an empty category inside your .m file:
#interface Whatever()
#property (nonatomic,retain) NSObject *aValue;
#end
You can find more about categories here.