如何将代表与 NSKeyedUnarchiver 一起使用?

Posted

技术标签:

【中文标题】如何将代表与 NSKeyedUnarchiver 一起使用?【英文标题】:How to use the delegates with NSKeyedUnarchiver? 【发布时间】:2016-04-21 20:19:50 【问题描述】:

我正在使用 NSKeyedUnarchiver 取消归档对象并希望使用委托 (NSKeyedUnarchiverDelegate),但我的委托没有被调用。归档和取消归档工作正常,但未调用委托 (unarchiver & unarchiverDidFinish)。有人可以帮忙吗?

我有以下实现:

        class BlobHandler: NSObject , NSKeyedUnarchiverDelegate

           func load() -> MYOBJECTCLASS          
              let data:NSData? = getBlob();      
              var mykeyedunarchiver:NSKeyedUnarchiver=NSKeyedUnarchiver(forReadingWithData: data!);
              mykeyedunarchiver.delegate = self;
              let temp=mykeyedunarchiver.decodeObjectForKey("rootobject")
// No delegates are called
                            if temp==nil 
                                blobsexists=false;
                            else
                                objectreturn = temp! as! MYOBJECTCLASS;
                                return objectreturn;
                            
        

    func save1(myobject:MYOBJECTCLASS)
            let data = NSMutableData()
            var keyedarchiver:NSKeyedArchiver=NSKeyedArchiver(forWritingWithMutableData: data);
            keyedarchiver.encodeObject(maptheme, forKey: "rootobject");

            let bytes = data.bytes;
            let len=data.length; 
            saveblob(bytes);
    

以下委托(也在我的 Blobhandler 中实现)永远不会被调用:

func unarchiver(unarchiver: NSKeyedUnarchiver, cannotDecodeObjectOfClassName name: String, originalClasses classNames: [String]) -> AnyClass? 
    print("I am in unarchiver !");
    return nil;


func unarchiverDidFinish(_ unarchiver: NSKeyedUnarchiver)
    print("I am in unarchiverDidFinish ! ");

【问题讨论】:

尝试调用 mykeyedunarchiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) 感谢您的帮助。我试过了。为此,我想我需要用 rootkey 对对象进行编码?但是我很愚蠢地编写这个代码。我用我的实施尝试更新了我的问题。您能否给我一个示例,如何使用根键对对象进行编码。我没有找到任何样品。 你确定你的委托在应该调用方法的时候还活着吗?能否请您发布您使用的所有方法,例如getBlob()saveblob 【参考方案1】:

我不知道它是什么,但它在清理和重建项目后工作。 我注意到在不同的情况下,构建有时不同步。有时有代码,它在 XCode 中但没有被执行。听起来难以置信,但我猜是真的。 XCode 7.2

【讨论】:

【参考方案2】:

我认为第一个函数永远不会被调用,因为您实际上根本没有提供“cannotDecodeObjectOfClassName”,因为您只是尝试取消归档以前归档的数据。你可以试试这个方法(或者一些需要类名的东西)来验证你的解决方案(喂一个类不符合 NSCoding):

unarchiver.decodeObjectOfClass(cls: NSCoding.Protocol, forKey: String)

第二个有点棘手。我在类似的情况下尝试过这种方法,结果发现 unarchiverDidFinish 只有在完成完整的取消归档工作并且可能在它被销毁之前才会被调用。例如,我有一个 NSCoding 类,方便启动器就像

required convenience init?(coder aDecoder: NSCoder) 
    let unarchiver = aDecoder as! NSKeyedUnarchiver
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

    unarchiver.delegate = appDelegate.uad


    let name = unarchiver.decodeObjectForKey(PropertyKey.nameKey) as! String

    print(321)

    self.init(name: name, photo: photo, rating: rating)

uad 是类的一个实例:

class UAD:NSObject, NSKeyedUnarchiverDelegate 
    func unarchiverDidFinish(unarchiver: NSKeyedUnarchiver) 
        print(123)
    

在视图控制器中加载过程就像

func load() -> [User]? 
    print(1)
    let ret = NSKeyedUnarchiver.unarchiveObjectWithFile(ArchiveURL.path!) as? [User]
    print(2)
    return ret

输出如下:

1 321 321 321 321 321 123 2

加载完一组用户后,unarchiverDidFinish 终于被调用了一次。请注意,这是一个类函数,并创建了一个匿名实例来完成这句话:

NSKeyedUnarchiver.unarchiveObjectWithFile(ArchiveURL.path!) as? [User]

所以我真的相信这个函数只有在它被销毁或者一组回调函数完成之前才会被调用。

我不太确定您是否属于这种情况。您可以尝试将您的 unarchiver 对象设为全局并在加载完成后将其销毁,以查看是否调用了此函数。

如有不妥之处请指正。

【讨论】:

亲爱的阿尔文佐。非常感谢您的帮助和努力。对于 +50 的声望,我不知道现在该怎么办,因为最后我会说这是一个 XCode 问题。编译后的代码与我在 XCode 中的 textform 中的内容不同步(不是 100% 肯定,但我过去已经观察到这样的问题,调试时它没有达到某些代码,直到我重建项目)。重建项目(很大)后,会调用委托。我没有更改代码中的任何内容,并且该对象始终充满数据。 @mcflysoft 完全没有问题。很高兴知道这已解决。也许我们在谈论不同的场景。【参考方案3】:

要正确调用unarchiverWillFinish:unarchiverDidFinish:,我们必须在解码完成时调用finishDecoding

配置好解码器对象后,要解码对象或数据项,请使用decodeObjectForKey: 方法。完成对键控存档的解码后,您应该在释放 unarchiver 之前调用finishDecoding

我们通知 NSKeyedUnarchiver 实例的委托,并通过调用此方法对存档执行任何最终操作。根据 Apple 的官方文档,一旦调用此方法,我们的 unarchiver 将无法解码任何进一步的值。如果我们在调用finishDecoding 后继续执行任何解码操作,我们将收到以下消息:

*** -[NSKeyedUnarchiver decodeObjectForKey:]:解压已经完成,不能再解码了

这对于 encoding 对应物也有意义。

【讨论】:

以上是关于如何将代表与 NSKeyedUnarchiver 一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

IOS 序列化与反序列化NSKeyedUnarchiver

Swift - NSMutableArray 中的 NSKeyedUnarchiver unarchiveObjectWithData

NSKeyedUnarchiver - 如何防止崩溃

如何在 Swift 中捕获 NSKeyedUnarchiver“NSInvalidUnarchiveOperationException”?

错误处理 - NSKeyedUnarchiver

iOS 数据的归档(NSKeyedArchiver )与数据的解档(NSKeyedUnarchiver) 加密 提高安全性