bridged cast: __bridge_transfer vs __bridge with synthesized setter

后端 未结 3 2069
再見小時候
再見小時候 2020-12-30 07:43

I am using ARC, and have confusion while using __bridge_transfer. I have a property userName as following:

@property (nonatomic, re         


        
3条回答
  •  难免孤独
    2020-12-30 08:27

    Case 1 and case 2 are equivalent. Think of it like this:

    Case 1:

    -(void)func {
      NSString *name = someObject;  // Retain, so +1 on the reference count
      self.userName = name;         // Retain, so +1 on the reference count
      // End of function, name is going out of scope,
      // so release name, so -1 on the reference count.
      // Total change to the reference count: +1 for self.userName.
    }
    

    Case 2:

    -(void)func {
      self.userName = someObject;   // Retain, so +1 on the reference count
      // End of function.
      // Total change to the reference count: +1 for self.userName.
    }
    

    So they work out the same. Note that the compiler is allowed to cancel out a retain and release pair, if it is safe to do so. In a simple case like this it would certainly elide them. Thinking about it with all the +1 and -1 changes to the reference count is just to make it clearer.

    To answer the bit about __bridge versus __bridge_transfer: you have called ABRecordCopyCompositeName, which returns a reference to an unmanaged object (a CFStringRef). The Copy in the function name tells you that this object is now owned by you, and you need to release it eventually.

    You can either do this by calling CFRelease, or you can ask ARC to do it for you. __bridge tells ARC that it is not allowed to take ownership (in other words, you want to release the object manually, or it isn't owned by you). __bridge_transfer tells ARC that it should take ownership and release the object at the end of the full expression (in other words, you are asking ARC to do the release for you).

    With __bridge_transfer:

    self.userName = (__bridge_transfer NSString *)ABRecordCopyCompositeName(person);  // +1 inside ABRecordCopyCompositeName, +1 for self.userName, -1 at the end, because of the __bridge_transfer.
    // self.userName now is the only strong reference.  Good.
    

    With __bridge:

    CFStringRef userName = ABRecordCopyCompositeName(person);  // +1 inside ABRecordCopyCompositeName.
    self.userName = (__bridge NSString *)userName;             // +1 for self.userName, ARC does nothing because of the __bridge.
    CFRelease(userName);                                       // -1.
    // self.userName now is the only strong reference.  Good.
    

    With __bridge and a memory leak:

    self.userName = (__bridge NSString *)ABRecordCopyCompositeName(person);  // +1 inside ABRecordCopyCompositeName, +1 for self.userName, ARC does nothing because of the __bridge.
    // self.userName now is one strong reference, but reference count is 2.
    // Memory leak.
    

提交回复
热议问题