代码之家  ›  专栏  ›  技术社区  ›  rob5408

更改自身指针

  •  1
  • rob5408  · 技术社区  · 16 年前

    我有一个对象,我像普通的一样alloc/init只是为了得到一个实例。稍后在我的应用程序中,我想从磁盘加载该对象的状态。我想我可以取消我的类(符合NSCoding)的归档,只交换实例指向的位置。为此,我使用这个代码。。。

    NSString* pathForDataFile = [self pathForDataFile];
    if([[NSFileManager defaultManager] fileExistsAtPath:pathForDataFile] == YES)
    {
        NSLog(@"Save file exists");
        NSData *data = [[NSMutableData alloc] initWithContentsOfFile:pathForDataFile];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        [data release];
    
        Person *tempPerson = [unarchiver decodeObjectForKey:@"Person"];
        [unarchiver finishDecoding];
        [unarchiver release];   
    
        if (tempPerson)
        {
            [self release];
            self = [tempPerson retain];
        }
    }
    

    self.person: <Person: 0x3d01a10> (After I create the object with alloc/init)
    self: <Person: 0x3d01a10> (At the start of this method)
    tempPerson: <Person: 0x3b1b880> (When I create the tempPerson)
    self: <Person: 0x3b1b880> (after i point self to the location of the tempPerson)
    self.person: <Person: 0x3d01a10> (After the method back in the main program)
    

    我错过了什么?

    2 回复  |  直到 16 年前
        1
  •  5
  •   drawnonward    16 年前

    self 是实例方法的函数参数。给self赋值是完全合理的,就像给其他函数参数赋值是完全合理的一样。因为 自己 如果是当前函数,则代码会泄漏一个对象并以最有可能导致崩溃的方式释放另一个对象。

    唯一有意义的时间 自己 init 初始化 方法可以释放self并分配一个新对象来返回或只返回nil。这样做的唯一原因是返回值是self和的调用者 初始化 期望使用返回值。

    正如gf所指出的,正确的方法是使用load函数为实例的成员分配新的值,而不是试图替换实例。

        2
  •  6
  •   Georg Fritzsche    16 年前

    别这样。除此之外,它破坏了标识规则,您不能更改程序的其他部分保持的指针值。

    更好的方法是使用PIMPL习惯用法:您的类持有一个指向实现对象的指针,而您只交换该指针。

    @class FooImpl;
    @interface Foo {
        FooImpl* impl;
    }
    // ...
    - (void)load;
    @end
    
    @implementation Foo
    - (void)load {
        FooImpl* tmp = loadFromDisk();
        if (tmp) {
            FooImpl* old = impl;
            impl = tmp;
            [old release];
        }
    }
    @end