Hello, I'm having trouble saving the value of an NSURL object.
The code bellow is used in a c++ project, however, this issue shouldn't be exclusive to this scenario.
I want to use document picker, only to choose a file and get its url, which I would use on c++ side to read/write data. That I've managed to do successfully, by passing the url to c++ side by calling FileWasPicked(std::string)
c++ method.
However, since document picker allows us to choose files only from public folders, I need to call start/stopAccessingSecurityScopedResource,
and to call them I need to pass an NSURL object, that I get from the document picker. I call startAccessingSecurityScopedResource
method before leaving didPickDocumentsAtURLs
method, however I can't do that with the stopAccessingSecurityScopedResource
.
I've tried to save the NSURL we get from document picker in a class variable @property NSURL *m_LastUsedURL;
, however it's value changes after leaving didPickDocumentsAtURLs
method. My guess, is that after leaving the before mention method, the value of the object that we save a pointer to gets deinitialized.
Passing the string value back from c++ and converting it to an NSURL object doesn't work either.
Is there any way to save NSURL object value in this case, or call the stopAccessingSecurityScopedResource
method in a different manner?
I attach my current code:
@implementation DocumentPicker //In a DocumentPicker.mm file
//We call this method from c++, to open document picker
- (void)openDocumentPicker:(NSString*)pickerType //We pass the picker type from c++
{
//Find the current app window, and its view controller object
UIApplication* app = [UIApplication sharedApplication];
UIWindow* rootWindow = app.windows[0];
UIViewController* rootViewController = rootWindow.rootViewController;
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[pickerType] inMode:UIDocumentPickerModeOpen];
documentPicker.delegate = self;
documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
[rootViewController presentViewController:documentPicker animated:YES completion:nil];
}
//Callback, that gets called after user successfully chooses a file
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls
{
//Start accessing file, that the user have picked
if ( [urls[0] startAccessingSecurityScopedResource] )
{
_m_LastUsedURL = urls[0];
//Pass the url and exit this method, to do actions in c++
GlobalCppClass->FileWasPicked(urls[0].absoluteString.UTF8String);
}
else
{
NSLog(@"startAccessingSecurityScopedResource failed");
}
}
//This would be called, after we finish reading the file in c++
-(void)stopAccesingFile
{
[_m_LastUsedURL stopAccessingSecurityScopedResource];
}
@end
Hello,
This issue does not exists on native XCode generated projects, only on Qt generated XCode projects.
So the closest conclusion that I've came to is different memory management in Qt generated XCode project and native XCode projects. On a native XCode project, if you assign an NSURL
object that we get at didPickDocumentsAtURLs
method, to a class variable, the object is being kept alive and we can use it even if we leave the didPickDocumentsAtURLs method.
However on a Qt generated XCode project, as soon as we leave didPickDocumentsAtURLs
method, the NSURL
object value is deinitialized.
ARC (Automatic Reference Counting) is disabled on Qt (according to: https://stackoverflow.com/questions/55181370/arc-enabled-for-qt-project-on-macos), and XCode has it enabled by default. My guess that this is the cause for the memory management difference, and there is no way to solve this issue. Or atleast if there is a solution, it's too much of a hassle.