// Copyright 2013 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/ios/weak_nsobject.h" #include "base/mac/scoped_nsautorelease_pool.h" #include "base/mac/scoped_nsobject.h" namespace { // The key needed by objc_setAssociatedObject. char sentinelObserverKey_; } namespace base { WeakContainer::WeakContainer(id object) : object_(object) {} WeakContainer::~WeakContainer() {} } // namespace base @interface CRBWeakNSProtocolSentinel () // Container to notify on dealloc. @property(readonly, assign) scoped_refptr container; // Designed initializer. - (id)initWithContainer:(scoped_refptr)container; @end @implementation CRBWeakNSProtocolSentinel @synthesize container = container_; + (scoped_refptr)containerForObject:(id)object { if (object == nil) return nullptr; // The autoreleasePool is needed here as the call to objc_getAssociatedObject // returns an autoreleased object which is better released sooner than later. base::mac::ScopedNSAutoreleasePool pool; CRBWeakNSProtocolSentinel* sentinel = objc_getAssociatedObject(object, &sentinelObserverKey_); if (!sentinel) { base::scoped_nsobject newSentinel( [[CRBWeakNSProtocolSentinel alloc] initWithContainer:new base::WeakContainer(object)]); sentinel = newSentinel; objc_setAssociatedObject(object, &sentinelObserverKey_, sentinel, OBJC_ASSOCIATION_RETAIN); // The retain count is 2. One retain is due to the alloc, the other to the // association with the weak object. DCHECK_EQ(2u, [sentinel retainCount]); } return [sentinel container]; } - (id)initWithContainer:(scoped_refptr)container { DCHECK(container.get()); self = [super init]; if (self) container_ = container; return self; } - (void)dealloc { self.container->nullify(); [super dealloc]; } @end