// Copyright 2016 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. #include "base/mac/objc_release_properties.h" #include #include #include "base/logging.h" #include "base/memory/free_deleter.h" namespace { bool IsRetained(objc_property_t property) { // The format of the string returned by property_getAttributes is documented // at // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW6 const char* attribute = property_getAttributes(property); while (attribute[0]) { switch (attribute[0]) { case 'C': // copy case '&': // retain return true; } do { attribute++; } while (attribute[0] && attribute[-1] != ','); } return false; } id ValueOf(id obj, objc_property_t property) { std::unique_ptr ivar_name( property_copyAttributeValue(property, "V")); // instance variable name if (!ivar_name) return nil; id ivar_value = nil; Ivar ivar = object_getInstanceVariable(obj, &*ivar_name, reinterpret_cast(&ivar_value)); DCHECK(ivar); return ivar_value; } } // namespace namespace base { namespace mac { namespace details { void ReleaseProperties(id self, Class cls) { unsigned int property_count; std::unique_ptr properties( class_copyPropertyList(cls, &property_count)); for (size_t i = 0; i < property_count; ++i) { objc_property_t property = properties[i]; if (!IsRetained(property)) continue; [ValueOf(self, property) release]; } } } // namespace details } // namespace mac } // namespace base