Property attribute in continuation class does not match the primary class - ios

In MyClass.h, I do:
#property (weak, nonatomic, readonly) CustomGridView *gridView;
and In MyClass.m, I do:
#property (weak, nonatomic, assign) CustomGridView *gridView;
However, I am getting a warning:
Property attribute in continuation class does not match the primary class
Can somebody tell me what I am missing here and how to silence the compiler?

It should be:
#property (weak, nonatomic, readwrite) CustomGridView *gridView;
You can't have weak and assign in the same property as they are both trying to specify the write type. What you have missed is the read/write access capability.

why do you need to duplicate Instance in .h and .m files ?
if you want to make your instance (gridView) readonly and need to access to instance (gridView) inside .m file you just need to override setGridView:(CustomGridView *) method for your instance (gridView) that's all.

Related

Objective-c, method declaration in .h and private property in .m confusion

I am reading a this tutorial in which he declared a method in cell .h file which accept a block but did not implement the method in .m class, he declared a private property with same name as method #property (copy, nonatomic) void (^didTapButtonBlock)(id sender);
what is this practice? only declaring a method in .h and making a private property in .m
I tried to do it simply like this
I created a method in .h file
-(void)xyz:(NSString*)string;
in .m file
#property (nonatomic, strong) NSString *string;
But Xcode giving warning Method definition for 'xyz' not found
Kindly tell what is going behind the scene?
He's exposing the setter method for the block variable, but keeping the getter private, if you notice, the method have the word set, which is the setter method for a property
This is how you can do the same:
-(void)setXyz:(NSString*)xyz;
and in .m:
#property (nonatomic, strong) NSString *xyz;
This way is to make sure other class cannot get the property instance, but can give it value

Is it possible to declare a property which class is either 'A' or 'B'? (multiple class possibilites)

In objective-C, is it possible to do something like the following?
#property (nonatomic, strong) <UIWebView or WKWebView> *webView;
In this case I know I can use UIView or even id, but I think the scope is too broad.
Thanks!
Yes, but you would do that via class inheritance and declare the property to be of type base class, which is the super class of the view classes you want to support:
#property (nonatomic, strong) SomeBaseView *webView;
You could declare the property to be of any type (id), however that would require additional testing when actually using the instance, in order to avoid unrecognized selector exceptions:
#property (nonatomic, strong) id webView;
Perhaps the best option is to declare a protocol to confine the any type:
#property (nonatomic, strong) id<WebViewProtocol> webView;

accessing classes from another class in objective c

I have two classes.
GameData.h
#import "TeamData.h"
#property (assign, nonatomic) GameData* teamA;
TeamData.h
#interface TeamData : NSObject
#property (nonatomic, copy) NSString* teamName;
-(void) printTeamData;
A number of questions :
Inside GameData.m I have this code :
TeamData* team = self.teamA;
[team printTeamData];
The first line shows this warning :
Incompatible pointer types from TeamData* with an expression of type TeamData*
In another class, I am including GameData.h and I want to set the teamA name. How do I access that? So I want to fetch the teamA property from the GameData class and set its name property.
In GameData.h, your property points to its own class, not to TeamData
#property (assign, nonatomic) GameData* teamA;
assign is meant for primitive types such as BOOL or NSInteger.
The parent class should hold a strong reference to a child object.
So your property would be better off as
#property (strong, nonatomic) TeamData* teamA;
As for setting the teamA property, you would call setTeamA: on your GameData instance:
[myGameData setTeamA:...];

Objective-C replace a property at runtime

Can I replace an property with new one using some obj-c runtime features.
So I have a class A which contains a property:
#property (nonatomic, strong) Status *status;
So I want to inherit from this class like ClassB : ClassA and have ability to switch original #property (nonatomic, strong) Status *status; to my new property like #property (nonatomic, assign) NSInteger status;
So the reasone why I needed because I don't want to have a full copy of class A which contains 20 properties, so I just want to inherit from it and replace one with needed type.
Not sure if this possible, but I know something like swizzling and some obj-c runtime features can make a magic in the code.

Objective C Semi Readonly property

I want to declare a public NSString property in my class which acts as a readonly property outside my class but i can assign any value to it inside my class. How can i achieve this behavior.
You have to declare your property in the .h file like this
#interface MyClass : NSObject
#property (strong, nonatomic, readonly) NSString *aString;
#end
but in your .m file you have to have
#interface MyClass () // your anonymous category
#property (strong, nonatomic, readwrite) NSString *aString;
#end
#implementation MyClass
#end
Externally the aString is readonly and internally you can set the value (readwrite).
You are achieving it by implementing a anonymous category also known as class extension in Objective-C
Define the property as readonly in the header and declare it readWrite in the implementation file in a class extension. The property will be readonly outside the classs implementation and read/write in the implementation.
// Interface file:
#interface Test : NSObject
#property (nonatomic, copy, readonly) NSString *propertyString;
#end
// Implementation file:
#interface Test () // Class Extension
#property (nonatomic, copy, readwrite) NSString *propertyString;
#end
#implementation Test
#end
See: Use Class Extensions to Hide Private Information
As #Amin Negm-Awad points out in an answer: the interface and class extension do not need to be in an interface or implementation file albeit this is the usual usage.
In .h file add:
#property(nonatomic,readonly)NSString* property;
In .m file add:
#interface yourClass ()
#property(nonatomic,readwrite)NSString* property;
#end
Define the property as readonly in your header file (interface), and as readwrite in your implementation file. That also allows you easily to make it weak / strong / copy.
This might be quit obvious:
in your .h file declare property as readonly
#property (nonatomic, assign, readonly, getter = isLoading) BOOL loading;
in your .m file declare property as readwrite
#property (nonatomic, assign, readwrite, getter = isLoading) BOOL loading;
This is an example, obviously you should create strong NSString property, and I assume compiler won't allow to set other value outside the class, but inside it will.
Beside the existing answers that told you to define a readonly property and change it to a readwrite property, which is completely correct and the intended pattern (that is, what readwrite is for), I want to add an probably important information:
You put the readonly definition in the interface. (Not header!)
You put the readwrite definition in a class continuation. (Not implementation file)
One might say that this is the same, because interfaces reside in the header and class continuations reside in the implementation file. But this is only the usual case.
You can additionally put class continuations in a third file. Then something like a "friend class" can import it additionally and this "fried class" has write access. I do that very often, when developing frameworks.
MyClass.h: // public header, available for everybody
#interface MyClass : NSObject
#property (readonly, …) id property1; // Everyone can read it
#property (readonly, …) id property2; // Everyone can read it
- (void)method; // Everyone can use it
#end
MyClass_Package.h: // project header, available for framework classes, unavailable for the user of the framework
#interface MyClass()
#property (readwrite, …) id property1; // All classes inside the framework can write it
- (void)packageMethod; // All classes inside the framework can use it
#end
MyClass.m
#interface MyClass() // A second class extension inside .m
#property (readwrite, …) id property2; // Only MyClass can write it
- (void)privateMethod; // Only MyClass can use it
#end
Define the property as readonly in the header, and set it using the underscore syntax.
#property (nonatomic, readonly) NSString *myString;
- (void)someMethodInYourDotMFile {
_myString = YES;
}

Resources