iOS: NSString when uploaded to parse.com shows blank - objective-c

I have taken an NSString from one class to another to be saved on parse.com
I have a quiz view controller where a user enters a question in a UITextView and then they press next to go to the select friends view controller where they select a user and then send the question over parse.
quiz.h
#property (nonatomic,strong) IBOutlet UITextView *textField;
#property (nonatomic, strong) NSString *text;
quiz.m
- (void)viewDidLoad {
[super viewDidLoad];
UITextView *textView = [[UITextView alloc] init];
NSString *text = self.textField.text;
selectFriendsViewController *sfvc = [[selectFriendsViewController alloc] init];
sfvc.string = text;
}
- (IBAction)next:(id)sender {
if ([text length] == 0) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error!"
message:#"Enter some text"
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
} else {
}
}
selectfriendsviewcontroller.h
#property (nonatomic, strong) NSString *string;
selectfriendsviewcontroller.m
- (void)viewDidLoad {
[super viewDidLoad];
quizViewController *qvc = [[quizViewController alloc] init];
qvc.text = string;
UITextView *textfield = [[UITextView alloc] init];
string = textfield.text;
NSLog(#"%#", self.string);
}
if i remove everything except the NSLog in the selectfriends.m file in viewdidload method, the file wont upload to parse. and i get the alertView showing and error saying not file or directory exists.
then i upload to parse.com
- (void) uploadMessage;
{
NSString *text =string;
NSString *fileType= #"text";
NSString * fileName= #"text.txt";
NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
PFFile *file = [PFFile fileWithName:fileName data:data];
[file saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Please try sending your message again" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
1) the string does not pass as null as null does not show in the console at runtime. (nothing shows in the console even with the NSLog statement)
2) the file uploads to parse.com as a text.txt file but when i download the file to check the text the file is blank.
So in quizVC type a question then press next to go to selectfirendsVC then select friends and upload to parse.com
how can i upload the textfile to show the user inputted text in the UITextView in the quizVC?

You don't want to communicate with just any instance of your SelectFriends vc, like the one created in your viewDidLoad. You must communicate with the instance that is going to be presented.
Remove the code in Quiz vc's viewDidLoad. Create a segue from Quiz vc to SelectFriends vc. In Quiz vc, implement prepareForSegue. In that method, interrogate the textView's text and set the string property on the segue.destinationViewController. That's the one that will be presented.
(A more general treatment of vc-vc communication here).

Related

Parse error iOS [unrecognized selector sent to instance]

I have an app saving images to parse, it consists of a collection view in the first VC and a detail view controller where you add a picture via UIImagePickerController. I've worked with parse a bit in Objective-C before, but keep getting this error
[PFObject setPhoto:]: unrecognized selector sent to instance 0x7fa15ac8f1c0
I have a parse class in the project with the properties, I know there is a different way but I've usually done it like this and had no problems.
Parse class header file
#import <Parse/Parse.h>
#interface Picture : PFObject <PFSubclassing>
#property (nonatomic, strong) NSString *Caption;
#property (nonatomic, strong) NSArray *Likes;
#property (nonatomic, strong) PFFile *Photo;
+ (NSString *)parseClassName;
#end
.m file
#import "Picture.h"
static NSString * const ClassName = #"Picture";
#implementation Picture
#dynamic Caption;
#dynamic Likes;
#dynamic Photo;
+ (NSString *)parseClassName {
return ClassName;
}
#end
Here is where I save the image
- (IBAction)saveImage:(id)sender {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:#"Add caption" message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = #"title";
}];
[alertController addAction:[UIAlertAction actionWithTitle:#"Save" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSArray *textFields = [alertController textFields];
NSString *nameString = ((UITextField *)textFields[0]).text;
NSData *imageData = UIImagePNGRepresentation(self.chosenImage);
// PFObject *object = [PFObject objectWithClassName:#"Picture"];
Picture *picture = [Picture object];
PFFile *file = [PFFile fileWithData:imageData];
[picture saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) {
if (succeeded) {
picture.Photo = file;
picture.Caption = nameString;
[picture saveInBackground];
[picture pinInBackground];
UIAlertController *successAlert = [UIAlertController alertControllerWithTitle:#"Photo Saved!" message:nil preferredStyle:UIAlertControllerStyleAlert];
[successAlert addAction:[UIAlertAction actionWithTitle:#"Okay" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:successAlert animated:YES completion:nil];
}
else {
NSLog(#"%#", error.localizedDescription);
}
}];
[alertController addAction:[UIAlertAction actionWithTitle:#"Okay!" style:UIAlertActionStyleCancel handler:nil]];
//save to parse here
}]];
[self presentViewController:alertController animated:YES completion:nil];
}
//image picker delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
self.chosenImage = info[UIImagePickerControllerEditedImage];
self.imageView.image = self.chosenImage;
[picker dismissViewControllerAnimated:YES completion:nil];
}
I thought at first it could be the size of the image but when I comment that part out and just try to save the caption I get the same error but with "setCaption" rather than "setPhoto"
Update: The objects have saved to parse but there is no data in the column, the keys (properties) are spelled right and everything too.
Thanks!
The problem appears to be that the dynamically generated setters are not getting created on your custom PFObject.
The problem may be your choice of case on your properties. The convention as defined by Apple is to start a property with a lowercase letter and have it be camel case thereafter. You should change the case to lowercase, as that may be causing a conflict with the creation of the getters.
You already have
PFObject *object = [PFObject objectWithClassName:#"Picture"];
and I'm guessing that your code did not work with that.
The other thing I can suggest is to move
picture.Photo = file;
picture.Caption = nameString;
out of the block and put it after PFFile *file = [PFFile... and delete
[picture saveInBackground];
as you appear to be saving your picture object twice. From your description that corresponds to the empty record that you are getting in Parse. Therefore, that save is being successfully performed. It is the second save that is failing.
Also, try adding
#import <Parse/PFObject+Subclass.h>
to your implementation (.m) file as that is where the class method for object is defined.

error: address doesn't contain a section that points to a section in a object file

Hi i have searched here on the forum but no help found so i am posting it new. Here is the scenario, i am creating a mfmailcomposeviewcontroller in the main rootviewcontroller, i am displaying it by calling presentviewcontroller but when it is dismissed i get this error :
error: address doesn't contain a section that points to a section in a object file
The code i am using is given below:
-(void) mailButtonTapped
{
if ([MFMailComposeViewController canSendMail]) {
mailViewController_ = [[MFMailComposeViewController alloc] init];
mailViewController_.mailComposeDelegate = self;
[mailViewController_ setSubject:#"Try ..."];
[mailViewController_ setMessageBody:#"Hey I just tried ..." isHTML:NO];
NSData *videoData = [NSData dataWithContentsOfURL:movieURL_];
[mailViewController_ addAttachmentData:videoData mimeType:#"video/quicktime" fileName:#"Video.mov"];
[self presentViewController:mailViewController_ animated:YES completion:nil];
}
else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Sharing Not Possible" message:#"Configure your mail to send the mail" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertView show];
[alertView release];
}
}
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
NSString *title = #"Email";
NSString *msg = nil;
if (result == MFMailComposeResultFailed)
msg = #"Unable to send, check your email settings";
else if (result == MFMailComposeResultSent)
msg = #"Email Sent Successfully!";
else if (result == MFMailComposeResultCancelled || result == MFMailComposeResultSaved)
msg = #"Sending Cancelled";
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:title message:msg delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
[self dismissViewControllerAnimated:YES completion:nil];
}
After dismissing i receive the error:
error: address doesn't contain a section that points to a section in a object file
Please help me
I also had this error but with another scenario. I had a block property defined with #property (assign, nonatomic).
To fix this issue, I declared my block property with #property (copy, nonatomic).
Cheers
This error happens when an object / pointer is being accessed that doesn't exist anymore . And can also cause other bad access, 0x00000 value accessed etc.. errors.
So you are deleting/releasing a pointer , and then accessing later .
From looking at the code, and this is just a guess without debugging, you set the second AlertView's delegate to self, but then immediately dismiss the viewcontroller.
Try dismissing after the alert view is dismissed or the button is pressed, or maybe just setting the AlertView delegate to nil.
Even if that's not exactly the error, the main reason is somewhere you are releasing an object then trying to call a function or access it.
You can use it like this:
MFMailComposeViewController *mailViewController_ = [[MFMailComposeViewController alloc] init];
mailViewController_.mailComposeDelegate = self;
[mailViewController_ setSubject:#"Try ..."];
[mailViewController_ setMessageBody:#"Hey I just tried ..." isHTML:NO];
NSData *videoData = [NSData dataWithContentsOfURL:movieURL_];
[mailViewController_ addAttachmentData:videoData mimeType:#"video/quicktime" fileName:#"Video.mov"];
[self presentViewController:mailViewController_ animated:YES completion:nil];
[mailViewController_ release];
I also had this problem but caused by a very silly error, i wrote a property called frameon a class that inherits from UIView (it was a UITableViewCell but i think this would happen with every class that inherits from UIView) this overwrote the original frame property and caused this error.
Fixed just by changing property name.
The completion expects a block to be called when the animation of dismissal is completed.
Just remove "completion:nil" and it should work!
Regards.

NSMutableArray to NSString and Passing NSString to Another View IOS5.1

I have an NSMutableArray of names. I want the pass the data (selected name) inside of NSMutableArray as text to another view's label.
FriendsController.m:
- (void)viewDidLoad {
[super viewDidLoad];
arrayOfNames=[[NSMutableArray alloc] init];
arrayOfIDs=[[NSMutableArray alloc] init];
userName=[[NSString alloc] init];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
long long fbid = [[arrayOfIDs objectAtIndex:indexPath.row]longLongValue];
NSString *user=[NSString stringWithFormat:#"%llu/picture",fbid];
[facebook requestWithGraphPath:user andDelegate:self];
userName=[NSString stringWithFormat:#"%#",[arrayOfNames objectAtIndex:indexPath.row]];
FriendDetail *profileDetailName = [[FriendDetail alloc] initWithNibName: #"FriendDetail" bundle: nil];
profileDetailName.nameString=userName;
[profileDetailName release];
}
- (void)request:(FBRequest *)request didLoad:(id)result {
if ([result isKindOfClass:[NSData class]]) {
transferImage = [[UIImage alloc] initWithData: result];
FriendDetail *profileDetailPicture = [[FriendDetail alloc] initWithNibName: #"FriendDetail" bundle: nil];
[profileDetailPicture view];
profileDetailPicture.profileImage.image= transferImage;
profileDetailPicture.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:profileDetailPicture animated:YES];
[profileDetailPicture release];
}
}
In FriendDetail.h
NSString nameString;
IBOutlet UILabel *profileName;
#property (nonatomic, retain) UILabel *profileName;
#property (nonatomic, retain) NSString *nameString;
In FriendDetail.m
- (void)viewDidLoad
{
[super viewDidLoad];
profileName.text=nameString;
}
nameString in second controller(FriendDetail) returns nil. When i set a breakpoint in firstcontroller I see the string inside of nameString is correct but after that it returns to nil somehow.
-----------------------EDIT----------------------------------------
According to answers I have improved my code little bit
FriendsController.h
FriendDetail *friendController;
#property (strong, nonatomic) FriendDetail *friendController;
FriendsController.m
- (void)viewDidLoad
{
[super viewDidLoad];
arrayOfNames=[[NSMutableArray alloc] init];
arrayOfIDs=[[NSMutableArray alloc] init];
arrayOfThumbnails=[[NSMutableArray alloc] init];
userName=[[NSString alloc] init];
friendController= [[FriendDetail alloc] initWithNibName: #"FriendDetail" bundle: nil];
}
-(void)request:(FBRequest *)request didLoad:(id)result{
if ([result isKindOfClass:[NSData class]])
{
transferImage = [[UIImage alloc] initWithData: result];
friendController.nameString=userName;
[friendController view];
friendController.profileImage.image= transferImage;
friendController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:friendController animated:YES];
}
//this is how i take facebook friends list
if ([result isKindOfClass:[NSDictionary class]]){
items = [[(NSDictionary *)result objectForKey:#"data"]retain];
for (int i=0; i<[items count]; i++) {
NSDictionary *friend = [items objectAtIndex:i];
long long fbid = [[friend objectForKey:#"id"]longLongValue];
NSString *name = [friend objectForKey:#"name"];
NSLog(#"id: %lld - Name: %#", fbid, name);
[arrayOfNames addObject:[NSString stringWithFormat:#"%#", name]];
[arrayOfIDs addObject:[NSNumber numberWithLongLong:fbid]];
}
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
long long fbid = [[arrayOfIDs objectAtIndex:indexPath.row]longLongValue];
NSString *user=[NSString stringWithFormat:#"%llu/picture",fbid];
userName=[NSString stringWithFormat:#"%#",[arrayOfNames objectAtIndex:indexPath.row]];
[facebook requestWithGraphPath:user andDelegate:self];
[username retain]
}
Now when i select row first time it sends name. When i come back to tableview and select another name it shows the old name.
If I delete [username retain] in didSelectRowAtIndexPath: it still sends nil to nameString
when I set break point at didSelectRowAtIndexPath: at line `
userName=[NSString stringWithFormat:#"%#",[arrayOfNames objectAtIndex:indexPath.row]]`
I can see userName = #"Adam Dart" which is correct
in my second breakpoint at line friendController.nameString=userName; I see that nameString =nil and userName = Variable is not CFString
ARC is set to NO
The value is nil because you did not pass the value in request:didLoad: function.
In function didSelectRowAtIndexPath, You create a local instance of another ViewController and set the value of nameString, but you did not present the view and release the ViewController immediately. You actually do nothing in these few lines of code:
FriendDetail *profileDetailName = [[FriendDetail alloc] initWithNibName: #"FriendDetail" bundle: nil];
profileDetailName.nameString = userName;
[profileDetailName release];
In function request:didLoad:, again you create a local instance of another ViewController with image. But this instance is only local to this function, which means no relation to the one created in didSelectRowAtIndexPath.
What you need to do is, remember the name of clicked row first in didSelectRowAtIndexPath, here you dont have to create the ViewController instance. When the request finish, set both the image and name to the controller and then present it. But you should avoid user from clicking different rows at the same time, because you don't know when the request finish.
You have two instances of FriendDetail called profileDetailPicture. Both of theses profileDetailPicture are not the same. So in your didSelectRowAtIndexPath method, the value that you assigned to the nameString will not be visible/available to the nameString of the profileDetailPicture In the request:(FBRequest *)request didLoad method.
Edit for solution:
Create an iVar or property (profileDetailPicture) in the FriendController.
Only do one allocation in the request:(...) method.
Remove the allocation statement in the didSelectRowAtIndexPath.
Any chance it has to do with the fact that you assign to profileDetailName and then immediately release it?
profileDetailName.nameString=userName;
[profileDetailName release];
You have to allocate the "first_controller" in your "second_controller"
to pass objects such as your string. and you would call the nameString differently.
example:
second_controller.h
#import "first_controller.h"
...
#interface second_controller : UIViewController{
first_controller* firstController;
}
second_controller.m
- (void)viewDidLoad {
[super viewDidLoad];
firstController = [[first_controller alloc] init];
profileName.text = firstController.nameString;
}
Which you'll have to init it correctly, because its two views sharing information.

Image cannot be saved using UIImageWriteToSavedPhotosAlbum to photo album

I have a save button called save to photo album. On top of the button is the small UIImageView where user can click the button below to save the actual size of the photo to photo album. My problem is that when I click the save button, it shows an error : Unable to save image to Photo Album.
I think I have done it right but my experience is too limited.
H file:
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController {
IBOutlet UIButton *btnReturn;
IBOutlet UIButton *savePhoto;
IBOutlet UIImage *saveImage;
}
#property (nonatomic, retain) IBOutlet UIButton *btnReturn;
#property (nonatomic, retain) IBOutlet UIButton *savePhoto;
#property (nonatomic, retain) IBOutlet UIImage *saveImage;
-(IBAction) saveToPhotoAlbum;
#end
Below is my code:
-(IBAction) saveToPhotoAlbum{
NSString *saveMyPhoto=[NSHomeDirectory() stringByAppendingPathComponent:#"sample.png"];
UIImage *saved=[UIImage imageWithContentsOfFile:saveMyPhoto];
NSData *imageData = [NSData dataWithContentsOfFile:(NSString *)UIImagePNGRepresentation(saved)];
[imageData writeToFile:(NSString *)saved atomically:YES ];
UIImageWriteToSavedPhotosAlbum(saved, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
UIAlertView *alert;
if (error)
alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Unable to save image to Photo Album."
delegate:self cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
else
alert = [[UIAlertView alloc] initWithTitle:#"Success"
message:#"Image saved to Photo Album."
delegate:self cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
[alert release];
}
Just create a UIImage object and load the image from file. Then just call the UIIMageWriteToSavedPhotoAlbum function and pass the UIImage object as the first parameter and then the rest could all be NIL. See the Apple SDK documentation.
These lines look really really suspect :
NSString *saveMyPhoto=[NSHomeDirectory() stringByAppendingPathComponent:#"sample.png"];
...
UIImage *saved = [UIImage imageWithContentsOfFile:saveMyPhoto];
...
[imageData writeToFile:(NSString *)saved atomically:YES ];
What are you expecting this to do? You get a path to an image, load it and then save it again but you've cast a UIImage to an NSString and are hoping it will magically turn into a valid path on the disk?
As for the question you're asking, are you sure that your image is a valid image?

stop Saving Image to photo library

How to stop saving image. which is already exist in iphone photo library.
This code is for savingImage.....
-(IBAction)saveImage:(id)sender
{
NSLog(#"calling save");
if (coverPage !=nil)
{
NSData * imageData = UIImagePNGRepresentation(coverPage);
UIImage *theImage = [UIImage imageWithData:imageData];
UIImageWriteToSavedPhotosAlbum(theImage, self, nil, nil);
}
else {
UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:#"Alert" message:#"Image is nil" delegate:self cancelButtonTitle:#"Cancle" otherButtonTitles:#"OK",nil];
[alertView show];
[alertView release];
}
}
if image is saved and clicking again and again the photo is saving..... How to stop saving image once it saved.
Without having more context it is difficult to say, but broadly speaking you can use a variable to track whether or not you have previously saved the current coverPage and simply avoid re-saving it if you have. For example:
-(IBAction)saveImage:(id)sender{
NSLog(#"calling save");
if (coverPageAlreadySaved) {
UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:#"Alert" message:#"Silly user, you already saved this image." delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK",nil];
[alertView show];
[alertView release];
}
else if (coverPage !=nil) {
NSData * imageData = UIImagePNGRepresentation(coverPage);
UIImage *theImage = [UIImage imageWithData:imageData];
UIImageWriteToSavedPhotosAlbum(theImage, self, nil, nil);
coverPageAlreadySaved = YES;
}
else {
UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:#"Alert" message:#"Image is nil" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK",nil];
[alertView show];
[alertView release];
}
}
...just be sure to set coverPageAlreadySaved = NO whenever the coverPage is changed (wherever you happen to be doing that in your code).
Alternately, since you already have the check against nil, you could just do:
-(IBAction)saveImage:(id)sender{
NSLog(#"calling save");
if (coverPage !=nil) {
NSData * imageData = UIImagePNGRepresentation(coverPage);
UIImage *theImage = [UIImage imageWithData:imageData];
UIImageWriteToSavedPhotosAlbum(theImage, self, nil, nil);
coverPage = nil;
}
else {
UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:#"Alert" message:#"Image is nil" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK",nil];
[alertView show];
[alertView release];
}
}
...which will prevent the image from being re-saved until it gets updated somewhere else in your code (at which point I assume it counts as a new coverPage).
If it's just one image you're saving then you can perform this just with a BOOL ivar for flag, like:
BOOL imageSaved;
And whenever you tap the button it'll just check if !imageSaved then perform the saving.
But if it's more then one image then you can do this using NSMutableArray.Like:
NSMutableArray *savedImages;//it's an ivar
Then before performing the saving operation:
NSString *imageName=......//Here I asssume you can get the image's name
if(!imageSaved)
NSMutableArray *savedImages=[[NSMutableArray alloc]init];
if (![savedImages containsObject:imageName]){
.........here comes the saving operation
and at the end you add the imageName to the array
[savedimages addObject:imageName];
}
I've given you just an example. You might not know the names of the images you save. If that's the case you can mark the image (which can be performed in several ways) and add the image itself.
Set the UIButton as an IBOutlet as well. Then set the enabled property to NO in the IBAction. Set the UIButton IBOutlet back to YES somewhere else in your program to 'reset' the button. It is similar to using a UIStepper in that you have to declare it twice...once as an IBAction and once as an IBOutlet.
This will allow you to use the button once, then it is 'greyed out' or 'muted' to prevent further activation. Basically you are disabling the UIGestureRecognizer from the UIButton.
Set the IBAction and IBOutlet.
- (IBAction)saveImageButton:(id)sender;
#property (weak, nonatomic) IBOutlet UIButton *saveImageButton;
Set the enabled to NO in the IBAction.
- (IBAction)saveImageButton:(id)sender {
UIImageWriteToSavedPhotosAlbum(_processedImageView.image, nil, nil, nil);
_saveImageButton.enabled = NO;
}
Then change it to YES somewhere else in your program to 'reset' the button so you can use it again.
_saveImageButton.enabled = YES;