| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef BASE_MAC_OBJC_PROPERTY_RELEASER_H_ | |
| 6 #define BASE_MAC_OBJC_PROPERTY_RELEASER_H_ | |
| 7 | |
| 8 #import <Foundation/Foundation.h> | |
| 9 | |
| 10 #include "base/base_export.h" | |
| 11 | |
| 12 namespace base { | |
| 13 namespace mac { | |
| 14 | |
| 15 // ObjCPropertyReleaser is a C++ class that can automatically release | |
| 16 // synthesized Objective-C properties marked "retain" or "copy". The expected | |
| 17 // use is to place an ObjCPropertyReleaser object within an Objective-C class | |
| 18 // definition. When built with the -fobjc-call-cxx-cdtors compiler option, | |
| 19 // the ObjCPropertyReleaser's destructor will be called when the Objective-C | |
| 20 // object that owns it is deallocated, and it will send a -release message to | |
| 21 // the instance variables backing the appropriate properties. If | |
| 22 // -fobjc-call-cxx-cdtors is not in use, ObjCPropertyReleaser's | |
| 23 // ReleaseProperties method can be called from -dealloc to achieve the same | |
| 24 // effect. | |
| 25 // | |
| 26 // Example usage: | |
| 27 // | |
| 28 // @interface AllaysIBF : NSObject { | |
| 29 // @private | |
| 30 // NSString* string_; | |
| 31 // NSMutableDictionary* dictionary_; | |
| 32 // NSString* notAProperty_; | |
| 33 // IBFDelegate* delegate_; // weak | |
| 34 // | |
| 35 // // It's recommended to put the class name into the property releaser's | |
| 36 // // instance variable name to gracefully handle subclassing, where | |
| 37 // // multiple classes in a hierarchy might want their own property | |
| 38 // // releasers. | |
| 39 // base::mac::ObjCPropertyReleaser propertyReleaser_AllaysIBF_; | |
| 40 // } | |
| 41 // | |
| 42 // @property(retain, nonatomic) NSString* string; | |
| 43 // @property(copy, nonatomic) NSMutableDictionary* dictionary; | |
| 44 // @property(assign, nonatomic) IBFDelegate* delegate; | |
| 45 // @property(retain, nonatomic) NSString* autoProp; | |
| 46 // | |
| 47 // @end // @interface AllaysIBF | |
| 48 // | |
| 49 // @implementation AllaysIBF | |
| 50 // | |
| 51 // @synthesize string = string_; | |
| 52 // @synthesize dictionary = dictionary_; | |
| 53 // @synthesize delegate = delegate_; | |
| 54 // @synthesize autoProp; | |
| 55 // | |
| 56 // - (id)init { | |
| 57 // if ((self = [super init])) { | |
| 58 // // Initialize with [AllaysIBF class]. Never use [self class] because | |
| 59 // // in the case of subclassing, it will return the most specific class | |
| 60 // // for |self|, which may not be the same as [AllaysIBF class]. This | |
| 61 // // would cause AllaysIBF's -.cxx_destruct or -dealloc to release | |
| 62 // // instance variables that only exist in subclasses, likely causing | |
| 63 // // mass disaster. | |
| 64 // propertyReleaser_AllaysIBF_.Init(self, [AllaysIBF class]); | |
| 65 // } | |
| 66 // return self; | |
| 67 // } | |
| 68 // | |
| 69 // @end // @implementation AllaysIBF | |
| 70 // | |
| 71 // When an instance of AllaysIBF is deallocated, the ObjCPropertyReleaser will | |
| 72 // send a -release message to string_, dictionary_, and the compiler-created | |
| 73 // autoProp instance variables. No -release will be sent to delegate_ as it | |
| 74 // is marked "assign" and not "retain" or "copy". No -release will be sent to | |
| 75 // notAProperty_ because it doesn't correspond to any declared @property. | |
| 76 // | |
| 77 // Another way of doing this would be to provide a base class that others can | |
| 78 // inherit from, and to have the base class' -dealloc walk the property lists | |
| 79 // of all subclasses in an object to send the -release messages. Since this | |
| 80 // involves a base reaching into its subclasses, it's deemed scary, so don't | |
| 81 // do it. ObjCPropertyReleaser's design ensures that the property releaser | |
| 82 // will only operate on instance variables in the immediate object in which | |
| 83 // the property releaser is placed. | |
| 84 | |
| 85 class BASE_EXPORT ObjCPropertyReleaser { | |
| 86 public: | |
| 87 // ObjCPropertyReleaser can only be owned by an Objective-C object, so its | |
| 88 // memory is always guaranteed to be 0-initialized. Not defining the default | |
| 89 // constructor can prevent an otherwise no-op -.cxx_construct method from | |
| 90 // showing up in Objective-C classes that contain a ObjCPropertyReleaser. | |
| 91 | |
| 92 // Upon destruction (expected to occur from an Objective-C object's | |
| 93 // -.cxx_destruct method), release all properties. | |
| 94 ~ObjCPropertyReleaser() { | |
| 95 ReleaseProperties(); | |
| 96 } | |
| 97 | |
| 98 // Initialize this object so that it's armed to release the properties of | |
| 99 // object |object|, which must be of type |classy|. The class argument must | |
| 100 // be supplied separately and cannot be gleaned from the object's own type | |
| 101 // because an object will allays identify itself as the most-specific type | |
| 102 // that describes it, but the ObjCPropertyReleaser needs to know which class | |
| 103 // type in the class hierarchy it's responsible for releasing properties | |
| 104 // for. For the same reason, Init must be called with a |classy| argument | |
| 105 // initialized using a +class (class) method such as [MyClass class], and | |
| 106 // never a -class (instance) method such as [self class]. | |
| 107 // | |
| 108 // -.cxx_construct can only call the default constructor, but | |
| 109 // ObjCPropertyReleaser needs to know about the Objective-C object that owns | |
| 110 // it, so this can't be handled in a constructor, it needs to be a distinct | |
| 111 // Init method. | |
| 112 void Init(id object, Class classy); | |
| 113 | |
| 114 // Release all of the properties in object_ defined in class_ as either | |
| 115 // "retain" or "copy" and with an identifiable backing instance variable. | |
| 116 // Properties must be synthesized to have identifiable instance variables. | |
| 117 void ReleaseProperties(); | |
| 118 | |
| 119 private: | |
| 120 id object_; | |
| 121 Class class_; | |
| 122 }; | |
| 123 | |
| 124 } // namespace mac | |
| 125 } // namespace base | |
| 126 | |
| 127 #endif // BASE_MAC_OBJC_PROPERTY_RELEASER_H_ | |
| OLD | NEW |