Handlng duplicate interface - objective-c

I am new to objective-c and I want to have two interface
I am trying to reduce peer-dependency in my code so I moved .m files and am creating single .h files
I did this
#interface XyzHelper : NSObject <RCTBridgeModule>
+ (bool)isFlaggedAsRequested:(NSString * _Nonnull)handlerId;
+ (void)flagAsRequested:(NSString * _Nonnull)handlerId;
#end
#interface XyzHelper : RCTEventEmitter <RCTBridgeModule, AVAudioPlayerDelegate>
but it says Duplicate interface definition which makes sense
Any idea how I can fix it?
What I am doing?
I am creating a libraries which use
https://github.com/react-native-webrtc/react-native-incall-manager
and
https://github.com/zoontek/react-native-permissions
I don't want user to npm install both repo (and other repo's I might have) instead a single repo npm install xyz
react-native-permissions uses
#interface XyzHelper : RCTEventEmitter <RCTBridgeModule, AVAudioPlayerDelegate>
and
in-call manager have this
#interface XyzHelper : NSObject <RCTBridgeModule>
+ (bool)isFlaggedAsRequested:(NSString * _Nonnull)handlerId;
+ (void)flagAsRequested:(NSString * _Nonnull)handlerId;
#end
#interface XyzHelper : RCTEventEmitter <RCTBridgeModule, AVAudioPlayerDelegate>
what did I tried?
I tried creating a common interface
#interface XyzHelper : RCTEventEmitter <RCTBridgeModule, AVAudioPlayerDelegate>
+ (bool)isFlaggedAsRequested:(NSString * _Nonnull)handlerId;
+ (void)flagAsRequested:(NSString * _Nonnull)handlerId;
#end
but this gives duplicate symbol for a architecture x86_64

#interface XyzHelper is declared twice. Of course this is a Duplicate interface definition. Instead you could extend your XyzHelper class. In Objective-C often refered to as so called category. Given a class like the following..
NS_ASSUME_NONNULL_BEGIN
#interface XyzHelper : RCTEventEmitter <RCTBridgeModule>
+ (bool)isFlaggedAsRequested:(NSString *)handlerId;
+ (void)flagAsRequested:(NSString *)handlerId;
#end
NS_ASSUME_NONNULL_END
The extension could look like the following example. It does not only extend XyzHelper, it also declares it conforms to an extra protocol.
#interface XyzHelper (SomeAudioPlayerExtension) <AVAudioPlayerDelegate>
#end
But keep in mind when doing so you have to check if your class object conforms to a particular protocol when you want to call extra protocol methods from within the former class implementation. Why? Because the extension suggests you conform to protocol while the needed methods are maybe not available, in example the extension implementation could not be loaded or you just forgot to implement them (missing symbols). Or it was just not linked. It is anyway safer to check for conformity at least once before calling any protocol method.
Typically the file names should express they contain extended code by naming them after the classname plus extensionname. So: XyzHelper+SomeAudioPlayerExtension.h and XyzHelper+SomeAudioPlayerExtension.m

Related

<ObjectType> in Objective-C

In NSArray.h I saw the interface like this
#interface NSArray<ObjectType>
What is the significance of <ObjectType>?
That is Apple using lightweight generics. The full #interface declaration in Xcode 7.3.1 looks like this:
#interface NSArray<__covariant ObjectType> : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
ObjectType is a placeholder used to represent the generic argument you pass into so that the compiler knows where to reference them. This is different than using NSObject * because ObjectType is like id, it can refer to non-Objective-C pointer types such as CoreFoundation objects.
For example, if I wanted to create a class that mocks an array for only a specific class, I could do something like #interface MYArray<MyClass *>.
You could also specifically declare an array of strings as NSArray<NSString *>.
See this article on Objective-C Generics for more information.

Can categories be inherited?

Say I have a class Parent and the child is Child1 and Child2.
I declare Parent+ParentCategory and then I declare a method:
-(void) Redraw;
Later I want the Redraw function of Child1 to be different than the Redraw function of Child2.
Can I declare Child1+Child1Category and then override the
-(void) Redraw
Can -(void)Redraw of Child1 call the function in the parent category?
Can that be done?
What would be good approach?
I know classes can inherit each other. I know protocol can extend each other. I wonder why category doesn't?
I do not agree with the given answers:
A.: It is not true, that category's methods win against class' method. This is an implementation detail, but the behavior is not defined.
If the name of a method declared in a category is the same as a method
in the original class, or a method in another category on the same
class (or even a superclass), the behavior is undefined as to which
method implementation is used at runtime.
B.
But this does not matter. You neither define a method in a category that is defined in the class nor define a method in two clashing categories. The cit. simply does not apply to your case. It applies to something like this:
#interface A : NSObject
- (void)doSomething;
#end
#implementation A
- (void)doSomething {}
#end
#interface A (Addition)
- (void)doSomething;
#end
#implementation A (Addition)
- (void)doSomething {}
#end
If I understand you correct, you do not want to do this. You want something like that:
Base level:
#interface A : NSObject
#end
#implementation A
#end
#interface A (Addition)
- (void)doSomething;
#end
#implementation A (Addition)
- (void)doSomething {}
#end
This does not break the rule, because there is no method in the category, which is in the class.
Subclass level:
#interface B : A
#end
#implementation B
#end
#interface B (Addition)
- (void)doSomething;
#end
#implementation B (Addition)
- (void)doSomething {}
#end
There is no clash on the level of B for the same reason as there is no clash on the level of A.
Somebody might say, that there is a clash, because B inherits -doSomething from A. But this is no clash, because in this case a priority rule applies: Subclasses overwrite methods.
You can do that.
Edit:
You can check the problem simply by adding the method to the class. Would that compile? In the clashing case, it wouldn't. In your case, it would.
I will replay with a cit. from this answer:
Lets just put it this way. Don't override methods using categories, period, ever, end of answer.
The reason of this is that while it is exactly known that a category's method always win against a class method (that is, if you implement a method in a category that's already declared in the class you are extending with the category the method of the category will be called.) when you have multiple category implementing the same method which implementation takes precedence is undefined
It is not wise to use category to do this. Categories add methods to the current class. If there are multiple methods with the same name, it will replace the old one (it is NOT an override). But unfortunately it is hard to say which one is replaced. Don't do it or you may get in trouble.
And you probably can not call the method in Parent from the child category. The most proper design here is a protocol.

using #property for a class I implemented

I created two classes in objective c and I would like to use one of them as a property of the other. To be more concrete, one of the classes is a 'term' that contains an integer variable and an nsstring that acts as the variable. The other class is an 'expression' that has an nsmutable array as an instance variable that contains 'terms' as its objects. What I want to do is have add the possibility of having one of the terms have an 'expression' as a property to implement something like distributing over parentheses and substituting an expression for a variable. However, Xcode is telling me that 'expression' is not an acceptable type name despite the fact that I have imported my expression header file. I think I may have read somewhere that only foundation classes are available to use as properties. What can I do to add this class as an instance variable?
I suspect you have an import cycle, like this:
Expression.h
#import "Term.h"
#interface Expression : NSObject
...
Term.h
#import "Expression.h"
#interface Term : NSObject
...
Notice how each file imports the other? That won't work. Instead, you need to use forward declarations:
Expression.h
#class Term; // tell the compiler that Term is a class name
#interface Expression : NSObject
...
Term.h
#class Expression; // tell the compiler that Expression is a class name
#interface Term : NSObject
...
Then, in your .m files, you can safely import both .h files:
Expression.m
#import "Expression.h"
#import "Term.h"
#implementation Expression
...
Term.m
#import "Term.h"
#import "Expression.h"
#implementation Term
...
Although the above answers are also correct, in my case the problem which occured was "#end" was missing in prototype/interface declaration.

Why is the protocol defined twice in Apple's sample code?

I am looking at Apple's sample code for lazy table image loading. I see that they have two lines starting with #protocol ParseOperationDelegate. Why do they do this twice? All the documentation on Objective C protocols I've looked at do not tell you to do it twice.
#class AppRecord;
#protocol ParseOperationDelegate;
//#interface ParseOperation : NSOperation <NSXMLParserDelegate>
#interface ParseOperation : NSOperation
{
#private
id <ParseOperationDelegate> delegate;
NSData *dataToParse;
NSMutableArray *workingArray;
//AppRecord *workingEntry;
//NSMutableString *workingPropertyString;
//NSArray *elementsToParse;
//BOOL storingCharacterData;
}
- (id)initWithData:(NSData *)data delegate:(id <ParseOperationDelegate>)theDelegate;
#end
#protocol ParseOperationDelegate
- (void)didFinishParsing:(NSArray *)appList;
- (void)parseErrorOccurred:(NSError *)error;
#end
The #protocol ParseOperationDelegate; line is not defining the protocol. It's a forward declaration. Basically it's saying that "a protocol called ParseOperationDelegate exists and is defined somewhere else in the code".
They do this so that the compiler will not die with an error on the line that goes id <ParseOperationDelegate> delegate;. The alternative would be to have the entire protocol definition placed before the interface definition (which personally I think would be a better solution in this case).
In such a simple case as this one I think there is little point in having the forward declaration. But you can easily imagine a more complex case where perhaps the protocol definition lives in its own header file (or in the header file for some other class). In a case like that, using a forward declaration allows you to avoid having to #import the protocol's header file into your class's header. It's a small difference, really, but it can be useful.

What is the concept of Inheritance in Objective-C?

I am new to Objective-C and want to know about inheritance. I am aware of the concepts but confused with the methods that programmer uses to inherit a class.
I have two classes: class A and class B, and want to make B a child of A.
Sometimes a programmer uses #import "class A" and sometimes uses the # sign. Which one of them should be used, and why? Is there any difference between their uses?
Another question I have is about the ":" sign which we write after class declaration, for example #interface class_A : class_name
In past I was a student of Java and C#, and their inheritance is similar to each other. But is Objective-C (I am currently working for iPhone) the same?
There is a difference between those terms, and I can see where your confusion is.
The #import is used to load definitions of a class's h file. This is, in a way, similar to C#'s using keyword, but in Objective-C we need to specify everything in the class level, not in the namespace level -- there's no concept of namespace level encapsulation in Objective-C.
The #class keyword is used whenever you need to declare that an object is valid -- but if you're going to use the internals of that object you will eventually need to add an #import of the class anyway. There's a great answer here on the difference between #class and #import.
As with C# and Java, inheritance is achieved by using the : operator in your h file. So in your declaration of Class B, it should go like:
#interface Class_B : Class_A
Hope this clears everything up.
update for your comment:
Let's say I want to inherit class A into class B, and use class C as a variable somewhere. You'll need the ff to make it work:
#import "Class_A.h"
#class Class_C;
#interface Class_B : Class_A {
Class_C *myvariable
}
Now, lets say somewhere inside your file you need to access a Class_C member e.g., myvariable.Property1, that's the time you turn #class Class_C into #import "Class_C.h".
I don't think declaring it like this:
#class Class_A;
#interface Class_B : Class_A
would work... you'll still need an #import "Class_A.h" somewhere which makes the #class declaration somewhat redundant.
if we do this
#interface Class_B : Class_A
mean we are inheriting the Class_A into Class_B, in Class_B we can access all the variables of class_A.
if we are doing this
#import ....
#class Class_A
#interface Class_B
here we saying that we are using the Class_A in our program, but if we want to use the Class_A
variables in Class_B we have to #import Class_A in .m file(make a object and use it's function and variables).