tzzzoz
tzzzoz

Reputation: 346

How to implement Deep copy for the Class in UIKit?

I have an object imageView1. I want to create another object to keep the deep copy of imageView1. Like this,

UIImageView *imageView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]];
UIImageView *imageView2 = [imageView1 copy];

I know it does't work, because UIImageView doesn't conform to NSCopying. But how should i do?

Upvotes: 2

Views: 1262

Answers (2)

graver
graver

Reputation: 15213

To create a deep copy of UIImageView object you need to archive it using NSKeyedArchiver and then unarchive it with NSKeyedUnarchiver, but there is a problem with this approach because UIImage does not conform to the NSCoding protocol. What you need to do first is to extend the UIImage class to support NSCoding.

Add a new category with name NSCoding on UIImage and place the following code:

UIImage+NSCoder.h

#import <UIKit/UIKit.h>

@interface UIImage (NSCoding)
- (id)initWithCoder:(NSCoder *)decoder;
- (void)encodeWithCoder:(NSCoder *)encoder;
@end

UIImage+NSCoder.m

#import "UIImage+NSCoder.h"

@implementation UIImage (NSCoding)
- (id)initWithCoder:(NSCoder *)decoder {
    NSData *pngData = [decoder decodeObjectForKey:@"PNGRepresentation"];
    [self autorelease];
    self = [[UIImage alloc] initWithData:pngData];
    return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:UIImagePNGRepresentation(self) forKey:@"PNGRepresentation"];
}

@end

Then add a new category with name DeepCopy (for ex.) on UIImageView and the following code:

UIImageView+DeepCopy.h

#import <UIKit/UIKit.h>

@interface UIImageView (DeepCopy)
-(UIImageView *)deepCopy;
@end

UIImageView+DeepCopy.m

#import "UIImageView+DeepCopy.h"
#import "UIImage+NSCoder.h"

@implementation UIImageView (DeepCopy)

-(UIImageView *)deepCopy
{
    NSMutableData *data = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:self forKey:@"imageViewDeepCopy"];
    [archiver finishEncoding];
    [archiver release];

    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    UIImageView *imgView = [unarchiver decodeObjectForKey:@"imageViewDeepCopy"];
    [unarchiver release];
    [data release];

    return imgView;
}

@end

Usage: Import your UIImageView+DeepCopy.h

UIImageView *imgView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"picture.jpg"]];
UIImageView *imageView2 = [imgView1 deepCopy];

Upvotes: 4

Mayur Birari
Mayur Birari

Reputation: 5835

Shallow copy
One method of copying an object is the shallow copy. In this process, B is attached to the same memory block as A. This is otherwise known as address copy. This results in a situation in which same data is shared between A and B, thus modifying the one will alter the other. The original memory block of B is now no longer referred to from anywhere. If the language does not have automatic garbage collection the original memory block of B has probably been leaked. The advantage of shallow copies is that their execution speed is fast and does not depend on the size of the data. Bitwise copies of objects which are not made up of a monolithic block are shallow copies.

Deep copy
An alternative is a deep copy. Here the data is actually copied over. The result is different from the result a shallow copy gives. The advantage is that A and B do not depend on each other but at the cost of a slower more expensive copy.

enter image description here
So following snippet will work for you to do deep copy.

UIImageView *imageView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]];
UIImageView *imageView2 = [[UIImageView alloc] initWithImage:imageView1.image];

Upvotes: 4

Related Questions