| // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef BASE_MAC_OBJC_PROPERTY_RELEASER_H_ | 
 | #define BASE_MAC_OBJC_PROPERTY_RELEASER_H_ | 
 |  | 
 | #import <Foundation/Foundation.h> | 
 |  | 
 | #include "base/base_export.h" | 
 |  | 
 | namespace base { | 
 | namespace mac { | 
 |  | 
 | // ObjCPropertyReleaser is a C++ class that can automatically release | 
 | // synthesized Objective-C properties marked "retain" or "copy". The expected | 
 | // use is to place an ObjCPropertyReleaser object within an Objective-C class | 
 | // definition. When built with the -fobjc-call-cxx-cdtors compiler option, | 
 | // the ObjCPropertyReleaser's destructor will be called when the Objective-C | 
 | // object that owns it is deallocated, and it will send a -release message to | 
 | // the instance variables backing the appropriate properties. If | 
 | // -fobjc-call-cxx-cdtors is not in use, ObjCPropertyReleaser's | 
 | // ReleaseProperties method can be called from -dealloc to achieve the same | 
 | // effect. | 
 | // | 
 | // Example usage: | 
 | // | 
 | // @interface AllaysIBF : NSObject { | 
 | //  @private | 
 | //   NSString* string_; | 
 | //   NSMutableDictionary* dictionary_; | 
 | //   NSString* notAProperty_; | 
 | //   IBFDelegate* delegate_;  // weak | 
 | // | 
 | //   // It's recommended to put the class name into the property releaser's | 
 | //   // instance variable name to gracefully handle subclassing, where | 
 | //   // multiple classes in a hierarchy might want their own property | 
 | //   // releasers. | 
 | //   base::mac::ObjCPropertyReleaser propertyReleaser_AllaysIBF_; | 
 | // } | 
 | // | 
 | // @property(retain, nonatomic) NSString* string; | 
 | // @property(copy, nonatomic) NSMutableDictionary* dictionary; | 
 | // @property(assign, nonatomic) IBFDelegate* delegate; | 
 | // @property(retain, nonatomic) NSString* autoProp; | 
 | // | 
 | // @end  // @interface AllaysIBF | 
 | // | 
 | // @implementation AllaysIBF | 
 | // | 
 | // @synthesize string = string_; | 
 | // @synthesize dictionary = dictionary_; | 
 | // @synthesize delegate = delegate_; | 
 | // @synthesize autoProp; | 
 | // | 
 | // - (id)init { | 
 | //   if ((self = [super init])) { | 
 | //     // Initialize with [AllaysIBF class]. Never use [self class] because | 
 | //     // in the case of subclassing, it will return the most specific class | 
 | //     // for |self|, which may not be the same as [AllaysIBF class]. This | 
 | //     // would cause AllaysIBF's -.cxx_destruct or -dealloc to release | 
 | //     // instance variables that only exist in subclasses, likely causing | 
 | //     // mass disaster. | 
 | //     propertyReleaser_AllaysIBF_.Init(self, [AllaysIBF class]); | 
 | //   } | 
 | //   return self; | 
 | // } | 
 | // | 
 | // @end  // @implementation AllaysIBF | 
 | // | 
 | // When an instance of AllaysIBF is deallocated, the ObjCPropertyReleaser will | 
 | // send a -release message to string_, dictionary_, and the compiler-created | 
 | // autoProp instance variables. No -release will be sent to delegate_ as it | 
 | // is marked "assign" and not "retain" or "copy". No -release will be sent to | 
 | // notAProperty_ because it doesn't correspond to any declared @property. | 
 | // | 
 | // Another way of doing this would be to provide a base class that others can | 
 | // inherit from, and to have the base class' -dealloc walk the property lists | 
 | // of all subclasses in an object to send the -release messages. Since this | 
 | // involves a base reaching into its subclasses, it's deemed scary, so don't | 
 | // do it. ObjCPropertyReleaser's design ensures that the property releaser | 
 | // will only operate on instance variables in the immediate object in which | 
 | // the property releaser is placed. | 
 |  | 
 | class BASE_EXPORT ObjCPropertyReleaser { | 
 |  public: | 
 |   // ObjCPropertyReleaser can only be owned by an Objective-C object, so its | 
 |   // memory is always guaranteed to be 0-initialized. Not defining the default | 
 |   // constructor can prevent an otherwise no-op -.cxx_construct method from | 
 |   // showing up in Objective-C classes that contain a ObjCPropertyReleaser. | 
 |  | 
 |   // Upon destruction (expected to occur from an Objective-C object's | 
 |   // -.cxx_destruct method), release all properties. | 
 |   ~ObjCPropertyReleaser() { | 
 |     ReleaseProperties(); | 
 |   } | 
 |  | 
 |   // Initialize this object so that it's armed to release the properties of | 
 |   // object |object|, which must be of type |classy|. The class argument must | 
 |   // be supplied separately and cannot be gleaned from the object's own type | 
 |   // because an object will allays identify itself as the most-specific type | 
 |   // that describes it, but the ObjCPropertyReleaser needs to know which class | 
 |   // type in the class hierarchy it's responsible for releasing properties | 
 |   // for. For the same reason, Init must be called with a |classy| argument | 
 |   // initialized using a +class (class) method such as [MyClass class], and | 
 |   // never a -class (instance) method such as [self class]. | 
 |   // | 
 |   // -.cxx_construct can only call the default constructor, but | 
 |   // ObjCPropertyReleaser needs to know about the Objective-C object that owns | 
 |   // it, so this can't be handled in a constructor, it needs to be a distinct | 
 |   // Init method. | 
 |   void Init(id object, Class classy); | 
 |  | 
 |   // Release all of the properties in object_ defined in class_ as either | 
 |   // "retain" or "copy" and with an identifiable backing instance variable. | 
 |   // Properties must be synthesized to have identifiable instance variables. | 
 |   void ReleaseProperties(); | 
 |  | 
 |  private: | 
 |   id object_; | 
 |   Class class_; | 
 | }; | 
 |  | 
 | }  // namespace mac | 
 | }  // namespace base | 
 |  | 
 | #endif  // BASE_MAC_OBJC_PROPERTY_RELEASER_H_ |