Why iOS cannot get subviews property for class UIView using class_getProperty function? - objective-c

I want to get the information about subviews property of class UIView:
objc_property_t property = class_getProperty([UIView class], "subviews");
But, it returns nil? I think it is so strange. Could someone explain this behavior to me?

Weird. If you use -valueForKey:, it can clearly be shown to exist. This used to be a bug with the old LLVM clang compiler in Xcode 3.2.3, where properties in categories (yes, it is declared in a category on UIView) wouldn't get recognized by the runtime, and there was even a bug report filed here about it. I know recent versions of Xcode have been having trouble with categories of late...

I just write a test code:
#interface Cat : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic) NSInteger age;
#property (nonatomic, readonly, copy) NSArray *subviews;
#end
It is ok. So Apple maybe be do so magic on it I guess.

Related

Hiding implementation details with .h and .m in objc

I'm confused about something. If in your .h file you have:
#property (nonatomic, strong, readonly) NSArray *categories;
and then in the .m you have:
#interface MyClass ()
#property (nonatomic, strong, readwrite) NSMutableArray *categories;
#end
If I want to later set categories in the .m file, I can do:
[self setCategories:[NSArray arrayWithArray:categories]];
But then Xcode complains that incompatible pointer types sending NSArray to NSMutableArray. I'm basically trying to hide the implementation details and have the .m use a NSMutableArray and to a consumer
use an NSArray.
[self setCategories:[NSMutableArray arrayWithArray:categories]]; // this gives no Xcode warning
By using the [NSMutableAray arrayWithArray:] method, does it still prevent the consumer of my Class from mutating my categories array?
You've done all you can in objc.
Your internal readwrite declaration needs a mutable array, so Xcode's complaining is right, you have to use a mutable for the setter.
The consumer can do everything with that object, even if it's declared as NSArray you can find out it's a NSMutableArray in reality and change it.
You can't prevent that. But your public declaration shows it should be assumed immutable. There's nothing more you can do.

RLMArray properties in unmanaged RLMObjects in Objective-C

I cannot find a good example code of this anywhere....but the information I find is contradictory and confusing...
#interface DAORealmMetadata : RLMObject
#property (nonatomic, copy) NSString* id;
#end
RLM_ARRAY_TYPE(DAORealmMetadata)
#interface DAORealmBase : RLMObject
#property (nonatomic, copy) NSString* id;
#property (nonatomic, copy) RLMArray<DAORealmMetadata*><DAORealmMetadata>* metadata;
#end
RLM_ARRAY_TYPE(DAORealmBase)
Question:
Am I supposed to add #dynamic metadata in the DAORealmBase implementation...or not?
I've tried it with and without and have the same end result...a crash.
I create the unmanaged object with this code:
DAORealmBase* baseObj = [[DAORealmBase alloc] init];
DAORealmMetadata* metadataObj = [[DAORealmMetadata alloc] init];
[baseObj.metadata addObject:metadataObj];
Question:
Why does the last line cause a crash/exception?
I can only assume that I"m doing something wrong, but I cannot find any specifics as to what I did.
Thanks!
Well, I tracked the problem down, and through some trial and error, determined that the problem was the property attributes on the RLMArray properties.
Changing
#property (nonatomic, copy) RLMArray<DAORealmMetadata*><DAORealmMetadata>* metadata;
to
#property RLMArray<DAORealmMetadata*><DAORealmMetadata>* metadata;
seems to have resolved the problem. I believe specifically the 'copy' attribute.
Now, I know that the Realm docs say that the attributes are ignored and not needed, but the lint checker I'm using wants them there...and since they are "ignored", what's the harm?
Well, they are ignored on normal Realm properties, but on the RLMArray properties they aren't ignored, and problems ensue.
Hopefully this will help someone else in the future and save them some time.

Do i need to use synthesize

I'm fairly new to objective-c, and I want to write a model class in iOS 7 using ARC, but I'm not sure whether I need the synthesize in the .m file. Could any one give me some advice on this?
//user.h
#interface User : NSObject
#property(nonatomic, assign) NSInteger age;
#property(nonatomic, copy) NSString *firstname;
#property(nonatomic, copy) NSString *lastname;
#end
//user.m
#implementation User
#synthesize age, firstname, lastname;
#end
Now comes my question:
Is the user.m file's synthesize necessary or not if in another class (e.g. ViewContoller class), I want to read & set the User class's age property, or firstname/lastname properties?
Not needed . Modern objective C compiler will auto synthesize the properties for you. Its a compiler feature started with the LLVM 4.0 comes with Xcode 4.4. If you just want the default behaviour of property no need of manual #synthesize.

"Expected a type" error pointing to the return type of a method

I've attempted to compile, but every time I do, one method throws a strange "expected a type" error. I have a method in the header:
-(ANObject *)generateSomethingForSomethingElse:(NSString *)somethingElse;
The error points at the return type for this method. I've imported ANObject into the header using #import "ANObject.h" and ANObject is compiling fine..
Why is this happening?
This is to do with the order that the source files are compiled in. You are already probably aware that you can't call a method before it is defined (see below pseudocode):
var value = someMethod();
function someMethod()
{
...
}
This would cause a compile-time error because someMethod() has not yet been defined. The same is true of classes. Classes are compiled one after the other by the compiler.
So, if you imagine all the classes being put into a giant file before compilation, you might be able to already see the issue. Let's look at the Ship and BoatYard class:
#interface BoatYard : NSObject
#property (nonatomic, retain) Ship* currentShip;
#end
#interface Ship : NSObject
#property (nonatomic, retain) NSString* name;
#property (nonatomic, assign) float weight;
#end
Once again, because the Ship class has not yet been defined, we can't refer to it yet. Solving this particular problem is pretty simple; change the compilation order and compile. I'm sure you're familliar with this screen in XCode:
But are you aware that you can drag the files up and down in the list? This changes the order that the files will be compiled in. Therefore, just move the Ship class above the BoatYard class, and all is good.
But, what if you don't want to do that, or more importantly, what if there is a circular relationship between the two objects? Let's increase the complexity of that object diagram by adding a reference to the current BoatYard that the Ship is in:
#interface BoatYard : NSObject
#property (nonatomic, retain) Ship* currentShip;
#end
#interface Ship : NSObject
#property (nonatomic, retain) BoatYard* currentBoatYard;
#property (nonatomic, retain) NSString* name;
#property (nonatomic, assign) float weight;
#end
Oh dear, now we have a problem. These two can't be compiled side-by-side. We need a way to inform the compiler that the Ship* class really does exist. And this is why the #class keyword is so handy.
To put it in layman's terms, you're saying, "Trust me man, Ship really does exist, and you'll see it really soon". To put it all together:
#class Ship;
#interface BoatYard : NSObject
#property (nonatomic, retain) Ship* currentShip;
#end
#interface Ship : NSObject
#property (nonatomic, retain) BoatYard* currentBoatYard;
#property (nonatomic, retain) NSString* name;
#property (nonatomic, assign) float weight;
#end
Now the compiler knows as it compiles BoatYard, that a Ship class definition will soon appear. Of course, if it doesn't, the compilation will still succeed.
All the #class keyword does however is inform the compiler that the class will soon come along. It is not a replacement for #import. You still must import the header file, or you will not have access to any of the class internals:
#class Ship
-(void) example
{
Ship* newShip = [[Ship alloc] init];
}
This cannot work, and will fail with an error message saying that Ship is a forward declaration. Once you #import "Ship.h", then you will be able to create the instance of the object.
I found this error hapenning when there is circular dependency on the headers. Check if the .h file where you declare this method is imported in ANObject.h
You basically add
#class ANObject;
before #interface!
So, for some reason I was getting this error while trying to set a method with an enum type in the parameters. Like so:
- (void)foo:(MyEnumVariable)enumVariable;
I had previously used it like this and never had an issue but now I did. I checked for circular dependency and could find none. I also checked for typos multiple times and no dice. What ended up solving my issue was to adding 'enum' before I wanted to access the variable. Like so:
- (void)foo:(enum MyEnumVariable)enumVariable;
{
enum MyEnumVariable anotherEnumVariable;
}
Usually when I see an error like this it's because I have a typo on a previous line, such as an extra or missing parenthesis or something.
It may sound stupid, but wrong shelling or wrong use of uppercase/lowercase letterwrong case this.
I got this message, when the variable type was misspelled. See below this below
e.g.
-(void)takeSimulatorSafePhotoWithPopoverFrame:(GCRect)popoverFrame {
instead of.....
-(void)takeSimulatorSafePhotoWithPopoverFrame:(CGRect)popoverFrame {
Strangely enough, changing the order of my imports has fixed this in the past... Try moving the import to the bottom after all your other imports.
I solved it by adding #class class_name to the .h file

Program receives SIGABRT when setting an ivar

[[self numSidesBox] setName: #"numSidesBox"];
This line of code receives the SIGABRT signal and i don't know why. numSidesBox is an instance of my subclass of UITextField. I have an NSString ivar that uses the
#property (nonatomic, retain) NSString *name;
way of creating setters/getters. I have no idea what's causing this problem.
Why not try:
self.numSidesBox.name=#"numSidesbox"
This assumes you have the following in your numSidesBox header:
#property (nonatomic, retain) NSString*name;
and in your .m:
#synthesize name;
This is just a general idea to get you started and point you in the right direction; you might prefer something other than retain and will also need your numSidesBox object similarly synthesized in the current .h/.m to use dot notation on it.
Additionally, just because numSidesBox has an ivar, does not mean it actually exists in memory. Before you can use it, you have to at some point initialize it with alloc and init or a custom or dedicated initializer.