年年有"余"

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 9544|回复: 1

第二十六讲:Objective-C内存管理之深拷贝

[复制链接]
  • TA的每日心情

    2024-10-15 10:05
  • 签到天数: 372 天

    [LV.9]以坛为家II

    发表于 2014-1-22 21:43:22 | 显示全部楼层 |阅读模式
    继续上一讲的浅拷贝,深拷贝的区别在于是否拷贝对象中的引用对象1、创建一个数组array,将类Car创建三个对象并保存到数组array中,使用[[NSMutableArray alloc] initWithArray:array]方法将array数组拷贝到array1中,修改array中的car元素,查看array1中的car是否发生变化;
    2、使用[[NSMutableArray alloc] initWithArray:array copyItems:YES]方法将array拷贝到array2中,修改array中的car元素,查看array2中的car是否发生变化;
    SACar.h
    1. //
    2. //  SACar.h
    3. //  DeepCopy
    4. //
    5. //  Created by yusian on 14-1-22.
    6. //  Copyright (c) 2014年 yusian. All rights reserved.
    7. //
    8. #import <Foundation/Foundation.h>
    9. @interface SACar : NSObject <NSCopying>
    10. @property (assign) NSString * name;
    11. @property int year;
    12. @end
    复制代码
    SACar.m
    1. //
    2. //  SACar.m
    3. //  DeepCopy
    4. //
    5. //  Created by yusian on 14-1-22.
    6. //  Copyright (c) 2014年 yusian. All rights reserved.
    7. //
    8. #import "SACar.h"
    9. @implementation SACar
    10. //***************************************NSCopying
    11. - (id) copyWithZone:(NSZone *)zone {
    12.     SACar * c = [[[[self class] allocWithZone:zone] init] autorelease];
    13.     c.name = self.name;
    14.     c.year = self.year;
    15.     return c;
    16. }
    17. //***************************************NSCopying_end
    18. - (NSString *) description {
    19.     return [NSString stringWithFormat:@"%@ age is %d", self.name, self.year];
    20. }
    21. - (void) dealloc {
    22.     NSLog(@"%@ is dealloc", self.name);
    23.     self.name = nil;
    24.     [super dealloc];
    25. }
    26. @end
    复制代码
    main.m
    1. //
    2. //  main.m
    3. //  DeepCopy
    4. //
    5. //  Created by yusian on 14-1-22.
    6. //  Copyright (c) 2014年 yusian. All rights reserved.
    7. //
    8. #import <Foundation/Foundation.h>
    9. #import "SACar.h"
    10. int main(int argc, const char * argv[])
    11. {
    12.     @autoreleasepool {
    13.         NSMutableArray * array = [[NSMutableArray alloc] init];
    14.         
    15.         for (int i = 0; i < 3; i ++) {
    16.             SACar * car = [[SACar alloc] init];
    17.             car.name = [NSString stringWithFormat:@"Car%d", i];
    18.             car.year = 2000 + i;
    19.             [array addObject:car];
    20.             [car release];
    21.         }
    22.         NSLog(@"%@", array);
    23.         
    24.         NSMutableArray * array1 = [[NSMutableArray alloc] initWithArray:array];
    25.         [[array1 objectAtIndex:0] setName:@"NewCar"];
    26.         NSLog(@"%@", array);
    27.         
    28.         NSMutableArray * array2 = [[NSMutableArray alloc] initWithArray:array copyItems:YES];
    29.         [[array2 objectAtIndex:0] setName:@"SecondCar"];
    30.         NSLog(@"%@", array);
    31.         NSLog(@"%@", array2);
    32.         
    33. //        [array release];
    34. //        [array1 release];
    35. //        [array2 release];
    36.     }
    37.     return 0;
    38. }
    复制代码
    运行结果:
    1. 2014-01-22 21:40:09.327 DeepCopy[2643:303] (
    2.     "Car0 age is 2000",
    3.     "Car1 age is 2001",
    4.     "Car2 age is 2002"
    5. )
    6. 2014-01-22 21:40:09.329 DeepCopy[2643:303] (
    7.     "NewCar age is 2000",
    8.     "Car1 age is 2001",
    9.     "Car2 age is 2002"
    10. )
    11. 2014-01-22 21:40:09.329 DeepCopy[2643:303] (
    12.     "NewCar age is 2000",
    13.     "Car1 age is 2001",
    14.     "Car2 age is 2002"
    15. )
    16. 2014-01-22 21:40:09.329 DeepCopy[2643:303] (
    17.     "SecondCar age is 2000",
    18.     "Car1 age is 2001",
    19.     "Car2 age is 2002"
    20. )
    21. 2014-01-22 21:40:09.330 DeepCopy[2643:303] Car2 is dealloc
    22. 2014-01-22 21:40:09.330 DeepCopy[2643:303] Car1 is dealloc
    23. 2014-01-22 21:40:09.330 DeepCopy[2643:303] SecondCar is dealloc
    24. Program ended with exit code: 0
    复制代码
    结果表示:
    进行浅拷贝后,修改array中的Car0为“NewCar”后,array与array1中的Car0都变成了NewCar;
    进行深拷贝后,修改array2中的Car0为“SecondCar”后,array中的Car0依然为之前的NewCar;
    array2打印出来的结果中,Car0被修改成SecondCar,并且array2被自动释放,array与array1却没有,为什么?
  • TA的每日心情

    2024-10-15 10:05
  • 签到天数: 372 天

    [LV.9]以坛为家II

     楼主| 发表于 2014-1-22 22:55:30 | 显示全部楼层
    深拷贝还可以通过归档的方式来实现:
    1、创建好的数组array归档到data中;
    2、将data解档到array1中,该过程会将归档的数据读出重新加载到数组array1中;
    3、需要注意的是:前面使用数组的copy方法,Car中的Name属性为assign,使用数组copy后会自动内存管理,但通过归档方式实现,解档时会报错,因此,在声明属性时,需要使用copy属性:@property(copy) NSString * name;
    代码如下:
    SACar.h
    1. //
    2. //  SACar.h
    3. //  DeepCopy
    4. //
    5. //  Created by yusian on 14-1-22.
    6. //  Copyright (c) 2014年 yusian. All rights reserved.
    7. //
    8. #import <Foundation/Foundation.h>
    9. @interface SACar : NSObject <NSCopying, NSCoding>
    10. @property (copy) NSString * name;
    11. @property int year;
    12. @end
    复制代码
    SACar.m
    1. //
    2. //  SACar.m
    3. //  DeepCopy
    4. //
    5. //  Created by yusian on 14-1-22.
    6. //  Copyright (c) 2014年 yusian. All rights reserved.
    7. //
    8. #import "SACar.h"
    9. @implementation SACar
    10. //***************************************NSCopying
    11. - (id) copyWithZone:(NSZone *)zone {
    12.     SACar * c = [[[[self class] allocWithZone:zone] init] autorelease];
    13.     c.name = self.name;
    14.     c.year = self.year;
    15.     return c;
    16. }
    17. //***************************************NSCopying_end
    18. //***************************************NSCoding
    19. - (void) encodeWithCoder:(NSCoder *)aCoder {
    20.     [aCoder encodeObject:self.name forKey:@"Name"];
    21.     [aCoder encodeInt:self.year forKey:@"Year"];
    22. }
    23. - (id) initWithCoder:(NSCoder *)aDecoder {
    24.     if (self = [super init]) {
    25.         self.name = [aDecoder decodeObjectForKey:@"Name"];
    26.         self.year = [aDecoder decodeIntForKey:@"Year"];
    27.     }
    28.     return self;
    29. }
    30. //***************************************NSCoding_end
    31. - (NSString *) description {
    32.     return [NSString stringWithFormat:@"%@ age is %d", self.name, self.year];
    33. }
    34. - (void) dealloc {
    35.     NSLog(@"%@ is dealloc", self.name);
    36.     self.name = nil;
    37.     [super dealloc];
    38. }
    39. @end
    复制代码
    main.m
    1. //
    2. //  main.m
    3. //  DeepCopy
    4. //
    5. //  Created by yusian on 14-1-22.
    6. //  Copyright (c) 2014年 yusian. All rights reserved.
    7. //
    8. #import <Foundation/Foundation.h>
    9. #import "SACar.h"
    10. int main(int argc, const char * argv[])
    11. {
    12.    
    13.     @autoreleasepool {
    14.         NSMutableArray * array = [[NSMutableArray alloc] init];
    15.         
    16.         for (int i = 0; i < 3; i ++) {
    17.             SACar * car = [[SACar alloc] init];
    18.             car.name = [NSString stringWithFormat:@"Car%d", i];
    19.             car.year = 2000 + i;
    20.             [array addObject:car];
    21.             [car release];
    22.         }
    23.         NSLog(@"%@", array);
    24.         
    25.         NSData * data = [NSKeyedArchiver archivedDataWithRootObject:array];
    26.         NSMutableArray * array1 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    27.         [[array1 objectAtIndex:0] setName:@"NewCar"];
    28.         NSLog(@"%@", array);
    29.         
    30.         [array release];
    31.         //[array1 release];
    32.    
    33.     }
    34.     return 0;
    35. }
    复制代码
    输出结果:
    1. 2014-01-22 22:46:06.956 DeepCopy[3316:303] (
    2.     "Car0 age is 2000",
    3.     "Car1 age is 2001",
    4.     "Car2 age is 2002"
    5. )
    6. 2014-01-22 22:46:06.958 DeepCopy[3316:303] (
    7.     "Car0 age is 2000",
    8.     "Car1 age is 2001",
    9.     "Car2 age is 2002"
    10. )
    11. 2014-01-22 22:46:06.958 DeepCopy[3316:303] Car0 is dealloc
    12. 2014-01-22 22:46:06.959 DeepCopy[3316:303] Car1 is dealloc
    13. 2014-01-22 22:46:06.959 DeepCopy[3316:303] Car2 is dealloc
    14. 2014-01-22 22:46:06.959 DeepCopy[3316:303] NewCar is dealloc
    15. 2014-01-22 22:46:06.960 DeepCopy[3316:303] Car1 is dealloc
    16. 2014-01-22 22:46:06.960 DeepCopy[3316:303] Car2 is dealloc
    17. Program ended with exit code: 0
    复制代码
    同样的道理,通过归档进行深拷贝的对象不需要release,这与@autoreleasepool有关系,原因暂未知;
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    手机版|小黑屋|Archiver|iOS开发笔记 ( 湘ICP备14010846号 )

    GMT+8, 2024-11-27 12:09 , Processed in 0.044281 second(s), 19 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表