/*! * iOS SDK * * Tencent is pleased to support the open source community by making * Hippy available. * * Copyright (C) 2019 THL A29 Limited, a Tencent company. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #import "HippyWeakProxy.h" @interface HippyWeakProxy () @property (nonatomic, weak) id target; @end @implementation HippyWeakProxy + (instancetype)weakProxyForObject:(id)target { HippyWeakProxy *proxy = [HippyWeakProxy alloc]; proxy.target = target; return proxy; } - (id)forwardingTargetForSelector:(SEL)aSelector { return _target; } - (BOOL)respondsToSelector:(SEL)aSelector { return [_target respondsToSelector:aSelector]; } #pragma mark Handling Unimplemented Methods - (void)forwardInvocation:(NSInvocation *)invocation { // Fallback for when target is nil. Don't do anything, just return 0/NULL/nil. // The method signature we've received to get here is just a dummy to keep `doesNotRecognizeSelector:` from firing. // We can't really handle struct return types here because we don't know the length. void *nullPointer = NULL; [invocation setReturnValue:&nullPointer]; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { // We only get here if `forwardingTargetForSelector:` returns nil. // In that case, our weak target has been reclaimed. Return a dummy method signature to keep `doesNotRecognizeSelector:` from firing. // We'll emulate the Obj-c messaging nil behavior by setting the return value to nil in `forwardInvocation:`, but we'll assume that the return // value is `sizeof(void *)`. Other libraries handle this situation by making use of a global method signature cache, but that seems heavier than // necessary and has issues as well. See https://www.mikeash.com/pyblog/friday-qa-2010-02-26-futures.html and // https://github.com/steipete/PSTDelegateProxy/issues/1 for examples of using a method signature cache. return [NSObject instanceMethodSignatureForSelector:@selector(init)]; } @end