0

Lets say I have one object, maybe a UIImageView...

it is .hidden = NO;

the alpha is .alpha = 0.425;

the background color is [UIColor blackColor];

Is there anyway that if I have another UIImageView I can set all of the properties to match this UIImageView's properties.

imageView2.properties = imageView1.properties;

Maybe a for-loop? something like:

//for (properties *property in object1) {

Or do I have to just go through every possibility.

imageView2.alpha = imageView1.alpha;
imageView2.hidden = imageView1.hidden;
imageView2.backgroundColor = imageView1.backgroundColor;
imageView2.center = imageView1.center
//etc.
Tarek Hallak
  • 18,422
  • 7
  • 59
  • 68
Albert Renshaw
  • 17,282
  • 18
  • 107
  • 195
  • Do you have a fixed set of properties (e.g. hidden, background, alpha) or do you want it to find *all* properties at runtime? – Martin R Jul 14 '13 at 14:21
  • You can take a look at this question http://stackoverflow.com/questions/2299841/objective-c-introspection-reflection. – Tarek Hallak Jul 14 '13 at 14:29
  • You can fairly easily use key-value coding to copy properties in a loop, but you need a list of the names of the properties to copy. – Hot Licks Jul 14 '13 at 14:31
  • @MartinR I'd like code for _all_ properties but for now just a fixed list will do! – Albert Renshaw Jul 15 '13 at 03:39

2 Answers2

4

If you're working with a specific set of properties, you can build an array of their names and then use key-value coding to set them:

for(NSString * key in @[@"hidden", @"frame", @"backgroundColor"]) {
    [toObject setValue:[fromObject valueForKey:key] forKey:key];
}

If you want this to copy all properties of any object, you can get the list of declared properties for a class using the class_copyPropertyList() function in objc/runtime.h. This has a lot of caveats, though:

  1. This call will return private properties that you shouldn't touch. As an example, gesture recognizers were only officially available in iOS 3.2, but they were a private class at least as far back as 3.1, and possibly in 3.0 as well.
  2. It will return readonly properties, even though setting them may be dangerous (KVC can set instance variables, but doesn't necessarily know how to do so correctly) or even impossible.
  3. It won't include anything that isn't in a property. For example, targets and actions for UIControls aren't exposed by a (public) property.
  4. It won't necessarily know how to handle certain properties that can't be shared between two objects, like layout constraints.
  5. A lot of very common data types—NSString, NSArray, and NSDictionary, for example—don't really store their data in properties, so this will completely miss the point on those sorts of classes.

In other words, it's very likely to break in horrible ways. Don't do it unless you really know what you're doing.

Becca Royal-Gordon
  • 17,541
  • 7
  • 56
  • 91
3

For a fixed list of properties you can use Key-Value Coding:

NSArray *propList = @[@"alpha", @"hidden"];
NSDictionary *dict = [imageView1 dictionaryWithValuesForKeys:propList];
[imageView2 setValuesForKeysWithDictionary:dict];

You could copy all properties by using the Objective-C runtime function class_copyPropertyList() to determine the properties dynamically at runtime. But I see two problems with that:

  • Copying "internal" properties might cause unwanted side-effects.
  • You would also have to copy the properties defined in the superclass. For example, alpha is not a property of UIImageView but of UIView.
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382