How to use the delegates with NSKeyedUnarchiver?

亡梦爱人 提交于 2019-12-23 07:28:13

问题


I am using NSKeyedUnarchiver to unarchive an object and would like to use the delegates (NSKeyedUnarchiverDelegate), but my delegates are not called. Archiving and Unarchiving is working fine, but the Delegates (unarchiver & unarchiverDidFinish) are not called. Can someone help?

I have the following implementation:

        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);
    }

The following delegates, which are also implemented in my Blobhandler, are never called:

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 ! ");
}

回答1:


I don't know what it was, but its working after a clean and rebuild of the project. I notice with different cases, that the builds are not in sync sometimes. There is sometimes code, which is in XCode but it is not executed. Sounds unbelievable, but I guess its true. XCode 7.2




回答2:


I think the first function is never called since you didn't actually feed a "cannotDecodeObjectOfClassName" at all, since you only did try to unarchive previously archived data. You can try this method(or something requires a class name) to validate your solution(feed a class doesn't conform NSCoding):

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

The second one is a little bit tricky. I've tried this method in a similar situation and it turned out that unarchiverDidFinish only get called when a complete unarchiving job is done and probably before it's destroyed. For example, I had a NSCoding class and the convenience initiator is like

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 is an instance of class:

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

And in the view controller the loading process is like

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

And the output is like:

1 321 321 321 321 321 123 2

After finishing loading a group of users, the unarchiverDidFinish finally got called once. Notice that this is a class function and an anonymous instance is created to finish this sentence:

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

So I really believe that this function only get called before it is destroyed or a group of call back functions is finished.

I am not quite sure if this is the case for you. You may try to make your unarchiver object global and destroy it after your loading is done to see whether this function is called.

Correct me if anything not right.




回答3:


To make either unarchiverWillFinish: and unarchiverDidFinish: be called properly, we have to invoke finishDecoding when finished decoding.

Once you have the configured decoder object, to decode an object or data item, use the decodeObjectForKey: method. When finished decoding a keyed archive, you should invoke finishDecoding before releasing the unarchiver.

We notify the delegate of the instance of NSKeyedUnarchiver and perform any final operations on the archive through invoking this method. And once this method is invoked, according to Apple's official documentation, our unarchiver cannot decode any further values. We would get following message if we continue to perform any decoding operation after invoked finishDecoding:

*** -[NSKeyedUnarchiver decodeObjectForKey:]: unarchive already finished, cannot decode anything more

It also makes sense for encoding counterparts.



来源:https://stackoverflow.com/questions/34824624/how-to-use-the-delegates-with-nskeyedunarchiver

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!