karstenBriksoft / PlistExplorer

Cocoa Tool to inspect files written by NSKeyedArchiver
Creative Commons Zero v1.0 Universal
89 stars 13 forks source link

Convert to Cocoa Touch Framework #9

Open craigaps opened 6 years ago

craigaps commented 6 years ago

Hi

I created a new Cocoa Touch Framework (Objective-C) project and added you files. I needed to update the header references to <Cocoa/Cocoa.h> to <UIKit/UIKit.h> and the import references from #import "objc/objc-class.h" to #import <objc/runtime.h>.

All seemed to build OK, however when I run the same archive file through the Cocoa Touch Framework library I crash out with:

-[__NSArrayI enumerateKeysAndObjectsUsingBlock:]: unrecognized selector sent to instance 0x60c0002726c0
2018-05-11 16:18:01.395263+1000 tester2[44019:14690035] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI enumerateKeysAndObjectsUsingBlock:]: unrecognized selector sent to instance 0x60c0002726c0'

I've create a simple iOS app in Swift to invoked the PlistExplorer functions as follows:

import UIKit
import PlistExplorerKit

class ViewController: UIViewController
{
    override func viewDidLoad() 
    {
        super.viewDidLoad()
        guard let path = Bundle.main.path(forResource: "accounts", ofType: "archive") else
        {
            print("can't find accounts.archive file.")
            return
        }

        let explorer = PlistExplorer.init()
        _ = explorer .crackFile(path)
        explorer.logYourself()
    }
}

When I execute NSLog(@"\n%@", [data logString]); in the Cocoa Touch library the output is: NSData with: 4742 Bytes

In the PlistExplorer code, the same file returns: NSData with: 5182 Bytes

Are you aware of any differences between a Cocoa app vs a Cocoa Touch Framework? Do you have any suggestions to convert the project into a framework that can be used in Swift?

Thanks for your help.

karstenBriksoft commented 6 years ago

The error you are seeing happens because -enumerateKeysAndObjectsUsingBlock: is sent to an NSArray, where it is only implemented in NSDictionary. I don't see this method called from anywhere within this project so you should check your code. I also don't know why the file-sizes are different. If the NSData says it's different maybe the files are not the same at all. From what I understand about Swift, you should be capable of calling Objective-C code, so no conversion should be necessary for this project.

craigaps commented 6 years ago

Many thanks for the reply!

I've instead copied the PlistExplorer files (.h and .m) into the Swift project and impressively it built just fine after commenting out in logYourselfLevelfunction.

printf("%s\n",[[NSString stringWithFormat:@"%@%@",[self gapForLevel:level],[self className]] UTF8String]);

The build error I was getting: /Users/craig/Desktop/Updater/PlistExplorerKit/PlistExplorerKit/Morphic.m:54:90: No visible @interface for 'Morphic' declares the selector 'className'. Morphic.m

Not being an Objective-C savvy, I think the reason the app crashes is because of the error above. I know if I change the file to say Info.plist, I'm no longer seeing the crash like I first reported, but nothing gets printed out to the debug window either.

Thanks again

karstenBriksoft commented 6 years ago

className is indeed only available on macOS (https://developer.apple.com/documentation/objectivec/nsobject/1411337-classname). But you can replace it by NSStringFromClass(self.class).

But that problem has nothing to do with the previous crash you had. This is a build error, meaning it cannot compile / link. The error you were seeing before was a runtime error that happened while the app was running.

craigaps commented 6 years ago

I'm not crashing the app anymore and to stop the build error, I updated logYourselfLevel from:

printf("%s\n",[[NSString stringWithFormat:@"%@%@",[self gapForLevel:level],[self className]] UTF8String]);

to

printf("%s\n",[[NSString stringWithFormat:@"%@%@",[self gapForLevel:level],[self class]] UTF8String]);

Now when I reference Info.plist as the file, nothing is being returned from explorer.crackFile. Here is the updated ViewController code.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        guard let path = Bundle.main.path(forResource: "Info", ofType: "plist") else
        {
            print("can't find file.")
            return
        }

        let explorer = PlistExplorer.init()
        guard let result = explorer.crackFile(path) else
        {
            print("no result.")
            return
        }

        print(result)
        explorer.logYourself()
    }
}

I get no result printed in the console. Am I actually calling your code correctly?

karstenBriksoft commented 6 years ago

You don't need to use PlistExplorer for info.plist files. It's purpose is to inspect files that contain NSKeyedArchiver data. If you want to inspect the info.plist you can just use [NSDictionary dictionaryWithContentsOfFile: file].

craigaps commented 6 years ago

yeah, true. Let me grab another archive file

craigaps commented 6 years ago

Hi I downloaded the sample app from Apple which demonstrates creating an archive. Persist Data

Got the archive off from the device and added it to sample app which uses the PlistExplorer code. Again, the same error occurred as reported initially. But referencing the archive in your Mac OSX project, it works fine - exactly the same code and archive file.

This is the sample iOS project I've been working with, I'm stumped as to why the archive is not loading, even though it's the same file used in PlistExplorer, if you have any ideas and time... tester2.zip

thanks again.