Open Recent Menu only works inside Xcode.

Hi.


I am implementing the Open Recent Menu in a not NSDocument app.


After getting the url of the file throught NSOpenPanel whith the full path to the file, the app proceds to open the file and peocces it, in succes, the app cals:


[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:self.URLFile];


this adds the file to Open Recent Menu, at this point all ok.


When I try to open the file throught Open Recent Menu, the app cals:


- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename


returning YES if the file is sucesfully open, at this point all ok Works fine.... BUT only works if the app is running into XCode, if archive the app export an launch in Finder, not works. Simple this last method is neveer called.


A thinkg at I ma missing somethig... any help to make this works outside Xcode will be apreciated.


Manuel.


Edit:


After loogin the app inside XCode as in Terminal App, the problem is when I try to convert from NSString to NSURL. this is the code:


- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{
    // paths in NSDocumentController recentDocumentURLs array
    NSLog(@"Paths in recentDocumentURLs");
    for (NSURL *url in [NSDocumentController sharedDocumentController].recentDocumentURLs) {
        NSLog(@"Path: %@",[url absoluteString]);
    }

    NSLog(@"Path filename: %@", filename);

    NSString *temp = [filename stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"Path temp: %@", temp);

    self.archivoURL = [NSURL fileURLWithPath:filename isDirectory:NO];
    NSLog(@"Path self.archivoURL: %@", self.archivoURL);

    if (self.archivoURL == nil) return NO;

    // open file...
   
    return YES;
} // Fin de application:OpenFile


this code inside XCode logs:


Paths in recentDocumentURLs

2016-12-21 00:08:23.118577 AppMake[9424:253018] Path: file:///Users/Manuel/Documents/Modelos%203D/X_single_Ring_round_40.stl

2016-12-21 00:08:23.118612 AppMake[9424:253018] Path: file:///Users/Manuel/Documents/Modelos%203D/pirinola.stl

2016-12-21 00:08:23.118625 AppMake[9424:253018] Path: file:///Users/Manuel/Documents/Modelos%203D/cubo%203.stl

2016-12-21 00:08:23.118636 AppMake[9424:253018] Path filename: /Users/Manuel/Documents/Modelos 3D/cubo 3.stl

2016-12-21 00:08:23.118665 AppMake[9424:253018] Path temp: /Users/Manuel/Documents/Modelos%203D/cubo%203.stl

2016-12-21 00:08:23.118706 AppMake[9424:253018] Path self.archivoURL: file:///Users/Manuel/Documents/Modelos%203D/cubo%203.stl


this code outside XCode and launch app throught Terminal.app for see logs, logs:


2016-12-21 00:08:05.564 AppMake[9410:252746] Paths in recentDocumentURLs

2016-12-21 00:08:05.566 AppMake[9410:252746] Path: file:///Users/Manuel/Documents/Modelos%203D/X_single_Ring_round_40.stl

2016-12-21 00:08:05.566 AppMake[9410:252746] Path: file:///Users/Manuel/Documents/Modelos%203D/pirinola.stl

2016-12-21 00:08:05.566 AppMake[9410:252746] Path: file:///Users/Manuel/Documents/Modelos%203D/cubo%203.stl

2016-12-21 00:08:05.566 AppMake[9410:252746] Path filename: /Users/Manuel/Documents/Modelos 3D/cubo 3.stl

2016-12-21 00:08:05.566 AppMake[9410:252746] Path temp: /Users/Manuel/Documents/Modelos%203D/cubo%203.stl

2016-12-21 00:08:05.566 AppMake[9410:252746] Path self.archivoURL: (null)

Any Idea??

Thanks Manuel

Replies

I don't know why "application:openFile:" is not being called, but perhaps there is an error message being logged? Use the Console utility to look in the system log, and see if there are any messages logged when your app is run stand-alone.

How do you know it's not being called oustide XCode ?

Thnaks for your interest. In Cosole app I can not find any reference to my app. any NSLog... is sent to console app. 😕

You right application:openFile it is called, but the parameter openfile:(NSString *)fileName is null.


Apparently the path to the file is not being stored in the array of "Open Recent", the interesting thing is that the file name appears in the Open Recent menu, but when you click on the name, and it is called the method application:openFile, The string containing the path is null. Repeat only happens when the app is run from the finder.


Any Idea?


Thanks

I proceeded as follow to build the URL (in Swift, bet easy to write in ObjC):


        let str  = filename as NSString //     /Users/myName/Desktop/TEST Results.exts
        let path : NSString = str.stringByDeletingLastPathComponent    // /Users/myName/Desktop
        let shortName  : NSString = str.lastPathComponent      // TEST Results.exts
        let escapedShortName = shortName.stringByAddingPercentEncodingWithAllowedCharacters(.URLUserAllowedCharacterSet())   // TEST%Results.exts
       guard var realFileURL = NSURL(string: "file://" + (path as String) + "/" + escapedShortName!) //  file : ///Users/myName/Desktop/TEST%20Results.exts
            else { return false }
In case anyone else is struggling with getting "open recent" to work in a non-document based app... this may help.

You have likely written your own 'open file' function, probably in your ViewController... somewhere in there drop this line:
Code Block
NSDocumentController.shared.noteNewRecentDocumentURL(myFileURL)

where myFileURL is an unwrapped URL (not NSURL, and definitely not a string). This line instantiates the document controller and should get your URL (now magically shortened to just the file name!) to the open recent menu. You do not need to instantiate the document controller elsewhere, this line does that.

Now that the menu is being fed URLs from your app, you need to create the logic to open a file when the user selects a file to open. In your AppDelegate, create this function:
Code Block
func application(_ sender: NSApplication, openFile filename: String) -> Bool {
    let url = URL(fileURLWithPath: filename)
     
    if let controller = NSApplication.shared.mainWindow?.contentViewController as? ViewController {
      let result = controller.openFunction(url: url)
      return result
    } else {
      print("could not instantiate controller object in AppDelegate.")
      return false
    }
  }

Notice: the URL is being returned as a string. The next line turns it back into a URL, and even handles white space, which the usual let url = URL(string: filename) does not. In the next line I will instantiate a handle to my ViewController class, if your file opening logic is elsewhere, instantiate accordingly. The next line calls my 'openFunction' function in my viewController, which takes a URL and returns a bool related to the success of opening the file. This is now functional in my app, hopefully it will work in your own.