iOS parse.com push error - ios

I have an array of string's that I am trying to save to parse as the channels for push notifications. The array is correct, put I have no idea what is going on. Can anybody throw some light on this? Thanks.
Error:
Error: Bad channel name: TestString123 (Code: 112, Version: 1.1.30)
Code:
- (void)saveSelectedDepartmentsToParse:(NSMutableDictionary *)dictionary {
NSArray *array = [dictionary allKeysForObject:#"YES"];
NSLog(#"Array = %#", array);
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation addObjectsFromArray:array forKey:#"channels"];
[currentInstallation saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error == nil) {
NSLog(#"Parse Save Succeeded");
}
else {
NSLog(#"Parse Save Failed, %#", error.localizedDescription);
}
}];
}

The reason is because Parse does not accept whitespaces or any special characters in the channels. After removing all white spaces and special characters, the operation succeeded.

Related

PFInstallation Error When Trying Save

Im trying to update a field in a PFInstallation object. My iOS Code is:
PFInstallation *installation = [PFInstallation currentInstallation];
installation[#"userId"] = #"none";
[installation saveEventually:^(BOOL suceeded, NSError *error){
if (suceeded) {
[PFUser logOutInBackgroundWithBlock:^(NSError *error){
if (!error) {
[self dismissViewControllerAnimated:YES completion:nil];
}
}];
}
else{
NSLog(#"Error Logging Out: %#", error);
}
}];
It use to work fine before, but for some reason using Parse Server I get the following error:
[Error]: at least one ID field (deviceToken, installationId) must be specified in this operation (Code: 135, Version: 1.12.0)
Anyone know how to fix this?

Parse- [query findObjectsInBackgroundWithBlock:^.)]; Block Doesn't execute w/ Action Extension

I'm trying to develop and Action Extension for iOS9.1 that is supposed to query Parse for some data.
I've added, enabled and tested Parse in the extension and I'm successful at creating test objects and checking for current user.
I can not get the code inside Parse's query method
[query findObjectsInBackgroundWithBlock:^ to execute. LLDB just keeps skipping it so I'm really at a loss.
This code executes perfectly within the container app so I'm a bit confused.
- (void)viewDidLoad
{
[super viewDidLoad];
[Parse enableLocalDatastore];
[Parse enableDataSharingWithApplicationGroupIdentifier:#"group.com.app.slinky"
containingApplication:#"com.app.Slinky"];
[Parse setApplicationId:#"xxxxx"
clientKey:#"xxxxx"];
for (NSExtensionItem *item in self.extensionContext.inputItems) {
for (NSItemProvider *itemProvider in item.attachments) {
if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypePropertyList]) {
[itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypePropertyList options:nil completionHandler:^(NSDictionary *jsDict, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSDictionary *jsPreprocessingResults = jsDict[NSExtensionJavaScriptPreprocessingResultsKey];
NSString *pageTitle = jsPreprocessingResults[#"title"];
NSString *pageURL = jsPreprocessingResults[#"URL"];
if ([pageURL length] > 0) {
self.siteURL.text = pageURL;
self.URLstring = pageURL;
}
if ([pageTitle length] > 0) {
self.siteTitle.text = pageTitle;
}
});
}];
break;
}
}
}
[self queryParse];
}
-(void)queryParse{
PFQuery *query = [self.friendsRelation query];
[query orderByAscending:#"username"];
**[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"%# %#", error, [error userInfo]);
} else {
self.friends = objects;
[self.tableView reloadData];
}
}];**
}
There are some limit to fetch Objects from Parse. Read Here
One has a limit of obtaining 100 objects, but anything from 1 to 1000 has a valid limit.
You have to set the limit again for the query for next objects and skip the properties of PFQuery.
You will have to query again and again until you reach the total count.
For Example - If you have 3000 objects to be fetched, then you have to query 3 times with a count of say 1000.
OR
Call [self queryParse]; inside dispatch_async(dispatch_get_main_queue(), ^{ }); block.
Hope this might workout.
This was just a result of a 12 hour refractoring marathon :-(
When I moved the queryParse call into its own method. I lost the definition of
self.friendsRelation = [[PFUser currentUser] objectForKey:#"friendsRelation"];
essentially sending a bad query... I don't know why it isn't return an error but regardless I can check that off now.
Thank you all for you help!

Unable to save channels to PFInstallation

I'm trying to save multiple channels for the same user
But just keeps me first. Others do not save.
NSString *business =self.business.name;
NSArray *subscribedChannels = [PFInstallation currentInstallation].channels;
for (NSString *channel in subscribedChannels){
NSLog(#"Channel %# ",channel);
}
[currentInstallation addUniqueObject:business forKey:#"channels"];
NSLog(#"Business : %#",business );
[currentInstallation saveInBackground];
When I go to the table of parse web , it is only created the first channel.
What am I doing wrong?

Saving an retrieving sound on Parse.com

I am trying to download some short sound file on Parse.com in an iOS application.
The file has previously been saved using the following code:
NSData *soundData = [NSData dataWithContentsOfURL:myURL];
parse_Sound = [PFFile fileWithName:#"XXYYZZ"
data:soundData];
[parse_Sound saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!succeeded) {
NSLog(#"sound-upload NG”);
} else {
NSLog(#"sound-upload OK");
}];
}
}];
Seeing the message on the debugging console, it appearently works.
Now what kind of code do I need to run to retrieve(download) the sound file?
I have browsed the net, but found nothing clear and working.
To get data back from the server you need to need to run a query asking for that object but you haven't associated the uploaded file with a column in any Class yet. Uploading a PFFile is iOS is a two step process:
1) Upload the PFFile to the server
2) In the callback associated the PFFile with a column in a data object
NSData *soundData = [NSData dataWithContentsOfURL:myURL];
parse_Sound = [PFFile fileWithName:#"XXYYZZ"
data:soundData];
[parse_Sound saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!succeeded) {
NSLog(#"sound-upload NG”);
} else {
NSLog(#"sound-upload OK");
PFObject *soundStuff = [PFObject objectWithClassName:#"Sounds"];
soundStuff[#"soundFile"] = parse_Sound;
[soundStuff saveInBackground];
}];
}
}];
Now to get the data back you would run a query on the Sounds class that will have the sound data in the soundFile column:
PFQuery *query = [PFQuery queryWithClassName:#"Sounds"];
[query whereKey:#"someKey" equalTo:#"someValue"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
PFFile *soundFile = object[#"soundFile"];
NSData *soundData = [soundFile getData];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
I haven't tested any of this code but it at least demonstrates the steps needed and should get you started.
Here are the examples from the documentation:
PFObject *jobApplication = [PFObject objectWithClassName:#"JobApplication"]
jobApplication[#"applicantName"] = #"Joe Smith";
jobApplication[#"applicantResumeFile"] = file;
[jobApplication saveInBackground];
Then to get the data back:
PFFile *applicantResume = anotherApplication[#"applicantResumeFile"];
NSData *resumeData = [applicantResume getData];
Notice that file is being associated with the applicantResumeFile column of the JobApplication class so that the file data can be retrieved in queries.
You need to keep a reference to that file somewhere (ideally in a column of the PFObject it belongs to).
If you don't keep a reference you're out of luck and you can't retrieve already uploaded files that have no association to any object.
I suggest you read through the Parse documentation for files on iOS https://www.parse.com/docs/ios_guide#files/iOS

iOS return bool value in block

I am trying to return a bool value from a class method I call that has a block in it. I get the error, Incompatible block pointer types sending.... How would I get around this? I just want to know if the class method I call completes with or without error...
+ (BOOL)saveSelectedDepartmentsToParse:(NSMutableDictionary *)dictionary {
NSArray *array = [dictionary allKeysForObject:#"YES"];
NSMutableArray *trimmedArray = [[NSMutableArray alloc] init];
for (NSString *string in array) {
NSString *final = [string removeAllInvalidCharacters];
[trimmedArray addObject:final];
}
NSLog(#"Array = %#", trimmedArray);
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation removeObjectForKey:#"channels"];
[currentInstallation addObjectsFromArray:trimmedArray forKey:#"channels"];
[currentInstallation saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error == nil) {
NSLog(#"Parse Save Succeeded");
[self saveDepartmentsDictionary:dictionary];
}
else {
NSLog(#"Parse Save Failed, %#", error.localizedDescription);
}
}];
}
I just want to know if the class method I call
This is a misunderstanding of how asynchronous code works. When you are supplying a block to saveInBackgroundWithBlock:, that code is not executed straight away. It's executed at some later point by the Parse framework, and whichever part of Parse that does so would get the return value if the block were defined to have one, which it isn't. Your block isn't executed at the point at which you write it, so you can't return anything at the point at which you write it.
Your code isn't calling the block, and you can't return values to your code from it. It doesn't make sense to do so. If another part of your code wants to know when the saving has finished, you'll need to use some other mechanism than return values, such as calling a method from your block, posting a notification, or Key-Value Observing.
From the block keyword InBackground:
[currentInstallation saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error == nil) {
NSLog(#"Parse Save Succeeded");
[self saveDepartmentsDictionary:dictionary];
} else {
NSLog(#"Parse Save Failed, %#", error.localizedDescription);
}
}];
I guess the block is called asynchronously.
If you want to get the result, you can wait here until the block is executed, but this make the saveInBackgroundWithBlock useless.
So NSNotification may be better:
[currentInstallation saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error == nil) {
NSLog(#"Parse Save Succeeded");
[self saveDepartmentsDictionary:dictionary];
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationParseSaveSucceeded object:nil];
} else {
NSLog(#"Parse Save Failed, %#", error.localizedDescription);
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationParseSaveFailed object:nil];
}
}];

Resources