parse-community / Parse-SDK-iOS-OSX

The Apple SDK for Parse Platform (iOS, macOS, watchOS, tvOS)
https://parseplatform.org
Other
2.81k stars 872 forks source link

NSAttributedString to Parse #329

Closed dailenspencer closed 9 years ago

dailenspencer commented 9 years ago

Heres my problem...

Im working in swift and am essentially attempting to create a twitter feed. On the "create post" page, there is a uitextview where the user types a body for the post and can insert images if desired. Everything works fine up until the user clicks the post button and sends the post object to my parse database.

I receive the error... PFObject values may not have class: NSConcreteAttributedString

I receive this error because I am saving the body of the post as type NSAttributedString. After searching the internet, using this type seemed like the only way for a uitextview to hold both text and image. What am i doing wrong? Or better, what would be the best way for the contents of the uitextview on the "create post" page to make it to my database so that the post can then appear in a uitableviewcell on the "post feed" page where all the posts are shown in a uitableview. Thanks

nlutsenko commented 9 years ago

Hey @dailenspencer, thanks for raising this!

NSAttributedString is indeed a type that you cannot save as a field on a PFObject. There are 2 potential ways to store NSAttributedString on Parse:

Let me know what you think, and whether these would work for you.

dailenspencer commented 9 years ago

Hey @nlutsenko, i'd love to encode it into NSData. What column should i pick in parse? (String,number,boolean,date,file,geopoint,array,object,pointer,relation).

Also, could you give an example on how to take the NSAttributed string and turn it into NSData? I tried a few times and took some examples form stackoverflow but keep receiving errors. Thanks

nlutsenko commented 9 years ago

You can use an object column type. It should be encoded into our specific type on save. Read more about the data types here.

The general approach would be something like

NSAttributedString *string = ...;
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:string];
parseObject[@"attributedString"] = data;
dailenspencer commented 9 years ago

@nlutsenko Okay so now its storing to parse but when i retrieve it another issue arises. The error is:

Error Domain=Parse Code=111 "invalid type for key bodydata, expected map, but got bytes"

Here is my code for retrieving.

let bodyData : NSData = object.valueForKey("bodydata") as! NSData let body: NSAttributedString = NSKeyedUnarchiver.unarchiveObjectWithData(bodyData) as! NSAttributedString

I assume this is because im trying to retrieve "bodydata" as NSData, even though its a pfobject. but how could i retrieve the pfobject and then convert it into nsdata so i can then use NSKeyedUnarchiver on it?

dailenspencer commented 9 years ago

ohh i need to encode it like you previously said ill try that

dailenspencer commented 9 years ago

hmm.. okay maybe i confused myself.

dailenspencer commented 9 years ago

I got it!!! Thanks for you help i just had to do a little digging! Thanks so much

dailenspencer commented 9 years ago

@nlutsenko okay actually one last thing(hopefully). Now the image is appearing inside the uitextview within the uiteableviewcell with the text around it. Which is perfect but would you suggest any way of making the image look better? I cant apply basic attributes(layer.cornerradius, border color, etc) currently because its just a uiimage and i need a uiimageview. I was thinking i could just add an uiimageview as the nstextattachment but i dont think thats possible. Any advice?

dailenspencer commented 9 years ago

Wow, ended up figuring out that one on my own too. im on a roll today.

nlutsenko commented 9 years ago

:) Great, glad to hear it all worked out for you. Let me know if there is anything else I can help you with.

dailenspencer commented 9 years ago

@nlutsenko okay i know this is closed but i was wondering if you could help me with something else completely unrelated to Parse. Im pretty knew to swift but ive built a fairly complex app and trying to add Google Drive API. however, when i follow the google drive api ios quickstart steps(which ive completely before successfully before in a practice project), i receive the error

Undefined symbols for architecture i386:

and then 51 errors follow. This is a pretty popular issue on stack overflow but everytime the solution is that someone hasnt added the ".m" file to the compiled sources. Ive searched and searched and i cant find the issue. I know this issue board is specifically related to parse but you seem to have the solution for everything so thats why im coming to you haha. Hope you can help!!

nlutsenko commented 9 years ago

Can you paste the error here? WIl definetly help you, just wondering what is the exact error that you see. Don't know everything, but will do my best to help you :D

dailenspencer commented 9 years ago

screenshot 2015-09-26 22 44 40

theres 61 of those red highlights that continue on below

nlutsenko commented 9 years ago

Hmm... This seems to be related though. Looks like you are missing

Also, looks like you are using ParseFacebookUtils.framework and ParseFacebookUtilsV4.framework. They are mutually exclusive (V4 is built for Facebook SDK v4, the regular one is for Facebook SDK v3).

What probably happened is that you started seeing these after adding -ObjC to your linker flags, which force links every single piece of code to your app, and starts to require all of the pieces, even if you are not using them.

dailenspencer commented 9 years ago

okay i downloaded the Facebook SDK and added AudienceNetwork, CoreKit, loginkit, messengersharekit, and sharekit( i already had bolts so i didnt drag that one in). And i also added social and accounts. But im now sitting at 53 errors, not the same ones i dont think but still related to the i386

screenshot 2015-09-26 23 27 59

dailenspencer commented 9 years ago

i also removed ParseFacebookUtils

dailenspencer commented 9 years ago

ohh I may need to drag in the docsets? Is that correct? I only moved in the frameworks

dailenspencer commented 9 years ago

not quite, I added them and still getting same errors

dailenspencer commented 9 years ago

@nlutsenko

Im starting to understand the errors. I added AVfoundation and it took about 13 errors away but im not sure which frameworks i should add to get rid of these..

screenshot 2015-09-26 23 37 52

nlutsenko commented 9 years ago

Ok, great... Now the problem is more isolated. From the errors, you need to add these frameworks:

It looks like most of these are coming from FBAudienceNetwork, which I am not sure if you need. (if you want just login with Facebook, you don't need FBAudienceNetwork, just FBSDKCoreKit, FBSDKLoginKit)

dailenspencer commented 9 years ago

Sorry for all the comments but I think im solving it. The reason no other stackoverflow answers made sense is because usually with this error they would have one or two but i had 51 so i figured there was some massive error but it turns out, like you said, im just missing a ton of frameworks haha ill keep you updated

dailenspencer commented 9 years ago

@nlutsenko so will this make my app run slower? Im not concerned AT ALL with allowing the user to log into facebook or anything like that. But once i imported the Google Drive API, all these errors started appearing so im just adding all the frameworks that are appearing in the errors. Is there any negatives to that?

nlutsenko commented 9 years ago

Hmm... negatives... Every framework that you link to potentially adds few milliseconds to start of your application, but I wouldn't worry about it, tbh. Another potential downside to linking to all of these frameworks is binary size. If that matters to your application, I would check the end binary size of your app...

richardjrossiii commented 9 years ago

Nanoseconds, not milliseconds; at least on iOS with the DYLD cache.

nlutsenko commented 9 years ago

Nanoseconds :disappointed:

dailenspencer commented 9 years ago

@nlutsenko Haha yea wouldnt want to take such a big hit on my loading time... So now i have a google drive button on the create post page which takes users through the google log in process and to a uitableview with all of their google drive files. The user can go down and select files they want to attach. the files go into an array which is then sent back to the create post page through a delegate. My problem now is figuring out the best way to attach these files inside of the uitextview. The google drive files have an extension(i guess thats what you call it) "defaultopenwithlink". So when the user clicks on it its going to open the google drive file with whatever defualt applcation they have set. How could i put this clickable link inside uitextview? It might be helpful to note that whenever i create a post that contains a link(manually type in https://google.com), the link isnt visible on the feed page. Its definitely there because when i click on the whitespace it opens up safari, but i cant see the text. This help has been awesome this is pretty much the final step in the app

nlutsenko commented 9 years ago

I believe NSAttributedString has an ability to add NSLinkAttribute. First thing found online was this answer.

dailenspencer commented 9 years ago

@nlutsenko Okay so i figured out how to get the links working for the uitextview but now ive hit a setback. All of a sudden the method i was using to select the multiple cells starting gigivng me EXC_Bad_Access. I was using didselectrowatindexpath. Every cell has a variable called embed link. every time the user clicks on a cell it adds the embed link to a "selectedlinks" array. Unless the object is already in the array, then it removes it from the array. Heres a screenshot of the didselectrowatindexpath and cellforrowatindexpath

screenshot 2015-09-28 00 08 00

the opendot and closedot images are set when a file is selected.

dailenspencer commented 9 years ago

for some reason the files "embed link" is coming out as nil in the didselectrowatindexpath

dailenspencer commented 9 years ago

Okay i half way figured it out by putting some print statements in the didselectrowatindex. It seems as though a small percentage of the files just dont have embed links. So when i fetch the files im just going to have to put an if statement that exludes the ones that dont have embed links though. I would hate for a user to get onto the app and wonder why some of their files dont appear...