Saving a PFFile into cloud - where did it go? - parse-platform

According the the Files section of the Parse documentation, to save a PFFile, we should follow these steps:
Create the PFFile
Save the PFFile to the cloud
After saving completes, associate the PFFile with a PFObject
I have troubles visualizing step #2. Here's the example code they provided, which I tried to run myself:
//1. Creating the PFFile
let str = "Working with Parse is great!"
let data = str.dataUsingEncoding(NSUTF8StringEncoding)!
let file = PFFile(name: "resume.txt", data: data)
//2. Saving the PFFile
file.saveInBackgroundWithBlock { succeeded, error in
if error != nil {
println(error)
}
if succeeded {
println("succeeded saving PFFile to cloud")
}
}
When I ran the code, the file succeeded in saving. But upon checking in my Parse app database, I see nothing that indicates the object is saved.
What is the point of step #2?

Step #2 doesn't result in anything visible in the Parse database browser. It uploads the file, but nothing references it so it's not visible. You need to associate it with an object, and then it'll be visible via the field you save it in within that object.
Also, if you look in the Settings -> General area in Parse.com for your app, near the bottom of the main pane, you'll see a link for "Clean Up Files". I believe this looks at all the files that have been uploaded, but are not associated with any objects in your database, and removes them.

Related

How to retrieve the XPC service of a file provider extension on macOS?

I have extended my example project from my previous question with an attempt to establish an XPC connection.
In a different project we have successfully implemented the file provider for iOS. The exposed service must be resolved by URLs it is responsible for. On iOS it is the only possibility and on macOS it appears like that, too. Because on macOS the system takes care of managing files there are no URLs except the one which can be resolved through NSFileProviderItemIdentifier.rootContainer.
In the AppDelegate.didFinishLaunching() method I try to retrieve the service like this (see linked code for full reference, I do not want to unnecessarily bloat this question page for now):
let fileManager = FileManager.default
let fileProviderManager = NSFileProviderManager(for: domain)!
fileProviderManager.getUserVisibleURL(for: NSFileProviderItemIdentifier.rootContainer) { url, error in
// [...]
fileManager.getFileProviderServicesForItem(at: url) { list, error in
// list always contains 0 items!
}
}
The delivered list always is empty. However the extension is creating a service source on initialization which creates an NSXPCListener which has an NSXPCListenerDelegate that exports the NSFileProviderReplicatedExtension object on new connections. What am I missing?
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
os_log("XPC listener delegate should accept new connection...")
newConnection.exportedObject = fileProviderExtension
newConnection.exportedInterface = NSXPCInterface(with: SomeProviderServiceInterface.self)
newConnection.remoteObjectInterface = NSXPCInterface(with: SomeProductServiceInterface.self)
newConnection.resume()
return true
}
Suspicious: serviceName of the FileProviderServiceSource never is queried. We are out of ideas why this is not working.
There is a protocol which your extension's principal class can implement, NSFileProviderServicing.
https://developer.apple.com/documentation/fileprovider/nsfileproviderservicing

Is it safe to use NSFileManager.fileExists(atPath:) for files in iCloud that might not have been downloaded?

I need a 100% fail-safe way to determine if a file name/file URL is available for writing data to disk without accidentally deleting an existing file.
Currently I'm using NSFileManager.fileExists(atPath:), but I'm wondering, what if the parent directory is in iCloud and my file URL points to an existing file in iCloud that hasn't been downloaded to the device yet?
What got me thinking are these two methods of URL:
func checkResourceIsReachable() throws -> Bool
func checkPromisedItemIsReachable() throws -> Bool
There is a distinction between a resource and a promised item. A promised item is defined as:
A promised item is not guaranteed to have its contents in the file
system until you use a file coordinator to perform a coordinated read
on its URL, which causes the contents to be downloaded or otherwise
generated.
Background:
What I'm after is an extension for FileManager that returns the next available, non-existing file name for a given (existing) file URL. For example:
Let's say my existing document is: /documents/Text.txt
The next available file name could be: /documents/Text 2.txt
How can I check that Text 2.txt really doesn't exist locally and in iCloud?
Here's my current approach:
// Safer than: FileManager.default.fileExists(at: url) ?
private func fileExists(at url:URL) throws -> Bool
{
if (try url.resourceValues(forKeys: [.isUbiquitousItemKey])).isUbiquitousItem == true
{
return try url.checkPromisedItemIsReachable()
}
else
{
return try url.checkResourceIsReachable()
}
}

Error: "include is invalid for non-ParseObjects" (using parse-osx-library-1.7.5)

I have a Meal object that stores pointers to n created objects "FoodInfo" using the key "MealItems".
When I query for the meal I take advantage of the [query includeKey:#"MealItems"] to fetch the items pointed to while fetching the "Meal".
This works swimmingly if the objects are created while online (ie. all are stored in the cloud db).
However, since I cannot assume access to the cloud at all time for this app I am now trying to enable the local datastore so I've changed my queries to use:
[query fromLocalDatastore];
and I've changed all of my objects' save methods to pinInBackgroundWithBlock followed by (assuming success of local save) saveInBackgroundWithBlock followed by (assuming failure) saveEventually.
To test this, I:
turned off wifi
ran the code to create a meal and then add newly created foods to it. This works with no error codes.
ran a report that then queries for the meal just created. This fails with the following:
Error: Error Domain=Parse Code=121
"include is invalid for non-ParseObjects" UserInfo=0x60800007f400 {
error=include is invalid for non-ParseObjects,
NSLocalizedDescription=include is invalid for non-ParseObjects,
code=121
} {
NSLocalizedDescription = "include is invalid for non-ParseObjects";
code = 121;
error = "include is invalid for non-ParseObjects";
}
Is this scenario not supported?
When I re-enable wifi, the meal is successfully added to the online db, but the query failure still happens when I run the query with the includeKey locally.
Am I missing something here? I'm quite surprised to see this failing. It seems like a really basic feature that should work whether local or cloud based.
Parse objects are not created until you save them. Try using saveEventually first before using pinInBackgroundWithBlock.

trouble accessing files loaded into project

I've added a bunch of files to my swift project folder like so:
I need to access these files at a certain point in the project for two purposes:
Use the name of each file to populate Categories (ie. Age, Alone, Amazing...)
Access the data within the files to populate each Category items page
I've implemented this code in the viewDidLoad of my class to access and iterate through the files
//get categories
let fileManager = NSFileManager.defaultManager()
let directoryPath = NSHomeDirectory() + "/Categories"
let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(directoryPath)!
while let element = enumerator.nextObject() as? String {
println(String(element))
}
This does not work and produces the error fatal error: unexpectedly found nil while unwrapping an Optional value on the line let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(directoryPath)!. I suspect (and correct me if I'm wrong), that it is accessing the applications internal file structure and as a result cannot find the files specified. As I am new to IOS development, my general understanding of how this works is nebulous at best.
So How exactly do I access files I've added the project in the way I've shown in the image, so as to iterate through and get the data I'm looking for
EDIT
So I've changed the structure to make the Categories folder an actual folder like so:
I'm currently trying to use NSBundle to access the application route, however I am not sure how to do that. Any guidance would be appreciated.
The problem is that xcode's project navigator folders are not actual folders in the disk. So this:
let directoryPath = NSHomeDirectory() + "/Categories"
does not exist in your hdd. If you want this folder you have to navigate to your projects folder on your hdd, create it manually and add the files you want in it.
You can refer to a file and read it like this:
let htmFile = NSBundle.mainBundle().pathForResource("aboutText", ofType: "html")
let htmlString = NSString(contentsOfFile: htmFile!, encoding: NSUTF8StringEncoding, error: nil)
for json you can get a dictionary with
let jsonFile = NSBundle.mainBundle().pathForResource("aboutText", ofType: "json")
let dict = NSDictionary(contentsOfFile: jsonFile)

Issues on saving to isolatedStorageSettings

When I am saving data(String) to isolated data storage,it was saving data successfully ,but the while retrieve data from data Storage,I a getting data of previous page.
I am having String variable in App.xaml.cs and i assign the values to it from pages,on deactivating the app,information abt last page gets saved and when i restore it ,i should get my saved String,But this is place i am getting this issue,I get some time the previous or before pages values,If i delete the app and build app successfully it works successfully,but when withou deleting the app and when going on doing build and build process,I am getting this issue.
if (IsolatedStorageSettings.ApplicationSettings.Contains("endResponse"))
{
IsolatedStorageSettings.ApplicationSettings[endResponse] = App.endResponse;
}
else
{
settings.Add("endResponse", App.endResponse);
}
and for retreiving i am using
if (IsolatedStorageSettings.ApplicationSettings.Contains("endResponse"))
{
IsolatedStorageSettings.ApplicationSettings.TryGetValue<String>("endResponse", out App.endResponse);
}
Debug.WriteLine("App.end Response in IsolatedStorage while activation>>>" + App.endResponse);
When deleting the app from simulator and while testing the app,it works well ,apart from it I am not getting exact values always.
I am attaching the screenshot of issue,plz check and tell me ,if i miss anything.
After writing your settings, you need to call the Save method :-
http://msdn.microsoft.com/en-us/library/system.io.isolatedstorage.isolatedstoragesettings.save%28v=vs.95%29.aspx
Shouldn't you use
IsolatedStorageSettings.ApplicationSettings["endResponse"]
rather then this in your post?
IsolatedStorageSettings.ApplicationSettings[endResponse]

Resources