代码之家  ›  专栏  ›  技术社区  ›  James Bucanek

macOS 12.0.1(蒙特利)XIB加载失败;抛出异常“此编码器期望替换的对象…从NSClassSwapper返回”

  •  0
  • James Bucanek  · 技术社区  · 4 年前

    我有包含自定义对象的XIB,其中一个实际上是一个类集群,其 -init 方法总是返回相同的singleton对象。

    大体上

    - (instancetype)init
    {
        self = [super init];
        if (HelpLinkHelperSingleton==nil)
            {
            // This is the first instance of DDHelpLink: make it the immortal singleton
            HelpLinkHelperSingleton = self;
            }
        else
            {
            // Not the first DDHelpLink object to be created: discard this instance
            //  and return a reference to the shared singleton
            self = HelpLinkHelperSingleton;
            }
        return self;
    }
    

    从macOS 12.0.1开始,加载XIB会引发以下异常:

    This coder is expecting the replaced object 0x600002a4f680 to be returned from NSClassSwapper.initWithCoder instead of <DDHelpLink: 0x600002a487a0>

    我试着实现 <NSSecureCoding> 做同样的事情,但这也不起作用。

    是否还有办法在NIB中使用类集群?

    0 回复  |  直到 4 年前
        1
  •  1
  •   Kai Oezer    4 年前

    我通过在XIB中使用一个代理对象来解决这个问题,该代理对象将消息转发给singleton。

    @interface HelpLinkHelperProxy : NSObject
    @end
    
    @implementation HelpLinkHelperProxy
    {
        HelpLinkHelper* _singleton;
    }
    
    - (void) forwardInvocation:(NSInvocation*)invocation
    {
        if (_singleton == nil)
        {
            _singleton = [HelpLinkHelper new];
        }
    
        if ([_singleton respondsToSelector:[invocation selector]])
        {
            [invocation invokeWithTarget:_singleton];
        }
        else
        {
            [super forwardInvocation:invocation];
        }
    }
    
    @end
    

    如果我们从 NSProxy 而不是 NSObject ,解决方案如下所示:

    @interface HelpLinkHelperProxy : NSProxy
    @end
    
    @implementation HelpLinkHelperProxy
    {
        HelpLinkHelper* _singleton;
    }
    
    - (instancetype) init
    {
        _singleton = [HelpLinkHelper new];
        return self;
    }
    
    - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel
    {
        return [_singleton methodSignatureForSelector:sel];
    }
    
    - (void) forwardInvocation:(NSInvocation*)invocation
    {
        if ([_singleton respondsToSelector:[invocation selector]])
        {
            [invocation invokeWithTarget:_singleton];
        }
        else
        {
            [super forwardInvocation:invocation];
        }
    }
    
    + (BOOL) respondsToSelector:(SEL)aSelector
    {
        return [HelpLinkHelper respondsToSelector:aSelector];
    }
    
    @end