Pasteboard - copying (image + text) creates mystery \n line break - ios

When I add an image and a string to the pasteboard I get a mysterious line break at the start of my text?
NSMutableDictionary *photo = [NSMutableDictionary dictionary];
NSMutableDictionary *text = [NSMutableDictionary dictionary];
NSData* imageData = UIImagePNGRepresentation(theImage.image);
[photo setValue:imageData forKey:(NSString*)kUTTypePNG];
[text setValue:theText.text forKey:(NSString *)kUTTypeUTF8PlainText];
[[UIPasteboard generalPasteboard] setItems:[NSArray arrayWithObjects:photo, text, nil]];
It puts the photo at the top and then it puts a line break and then the text. If I try to send the image and text in an iMessage the image separates anyways and I end up with the text in a bubble with a silly looking line-break infront of it.
If I just copy the text without the photo it does not add a mysterious line-break.
[[UIPasteboard generalPasteboard] setItems:[NSArray arrayWithObjects:text, nil]];
Does anyone know how to fix this?
If not, can anyone think of some nice workaround? Are there any unicode characters that will reverse a line-break? etc?

Store PNG as BASE64 encode. See if this helps.

Related

Display Emoji from unicode in UILabel in iOS

I am working on emoji in chat app.
When someone send me emoji in message it look like this type :- Hello...(worried) how are you(happy)?. Here (worried)and (happy) are assigned keys for emojis.
This is list for emojis and key and value.
dictemoji = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"worried-48.gif",#"(worried)",
#"sad-48.gif",#"(sad)",
#"bandit48.gif",#"(bandit)",
#"wink48.gif",#"(wink)",
#"surprised48.gif",#"(surprised)",
#"smirking48.gif",#"(smirking)",
#"laugh48.gif",#"(laugh)",
#"cool48.gif",#"(cool)",
#"stoned-48.gif",#"(stoned)",
#"smile-48.gif",#"(smile)",
#"nerd-48.gif",#"(nerd)",
#"happy-48.gif",#"(happy)",
#"evil-grin-48.gif",#"(evil-grin)",
#"tongue48.gif",#"(tongue)",
#"lips-sealed-48.gif",#"(lips-sealed)",
#"GIF48.gif",#"(GIF)",
#"dull48.gif",#"(dull)",
nil];
When I received message Hello...(worried) how are you(happy)? I want to saw my emoji instead of (worried)and(happy) in label.
So how can I take emoji instead of those words?
EDIT:-
When someone send me emoji with text message, it will replace with dictionary value :
for (NSString *emojiKey in dictemoji.allKeys)
{
if ([message containsString:emojiKey])
{
message = [message stringByReplacingOccurrencesOfString:emojiKey withString:[dictemoji valueForKey:emojiKey]];
}
}
// helllo(sad)...how are you(smile)...? ----->it will look like helllo(sad-48.gif)...how are you(smile-48.gif)...?
NSLog(#"message updated:%#",message);
cell.textLabel.text=message;
So, I want to display emoji where (sad-48.gif) and (smile-48.gif) printed in label.
Try this. It may help you.
Add one label & write the following code in viewDidLoad :
NSData *dataa = [valueUnicode dataUsingEncoding:NSUTF8StringEncoding];
NSString *valueEmoj = [[NSString alloc] initWithData:dataa encoding:NSNonLossyASCIIStringEncoding];
_lbl.text = valueEmoj;
You have to use like this ;
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
attachment.image = [UIImage imageNamed:[dictemoji valueForKey:emojiKey]];
NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];
NSMutableAttributedString *myString= [[NSMutableAttributedString alloc] initWithString:#"My label text"];
[myString appendAttributedString:attachmentString];
cell.attributedText = myString;
hope this will help.

trouble saving NSAttributedString, with image, to an RTF file

I have some output that is a very simple RTF file. When I generate this document, the user can email it. All this works fine. The document looks good. Once I have the NSAttributedString, I make an NSData block, and write it to a file, like this:
NSData* rtfData = [attrString dataFromRange:NSMakeRange(0, [attrString length]) documentAttributes:#{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType} error:&error];
This file can be emailed. When I check the email all is good.
Now, I'm tasked with adding a UIImage at the top of the document. Great, so I'm creating an attributed string like this:
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
UIImage* image = [UIImage imageNamed:#"logo"];
attachment.image = image;
attachment.bounds = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
NSMutableAttributedString *imageAttrString = [[NSAttributedString attributedStringWithAttachment:attachment] mutableCopy];
// sets the paragraph styling of the text attachment
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init] ;
[paragraphStyle setAlignment:NSTextAlignmentCenter]; // centers image horizontally
[paragraphStyle setParagraphSpacing:10.0f]; // adds some padding between the image and the following section
[imageAttrString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [imageAttrString length])];
[imageAttrString appendAttributedString:[[NSAttributedString alloc] initWithString:#"\n\n"]];
At this point, in Xcode, I can do a QuickLook on imageAttrString, and it draws just fine.
Once this string is built, I'm doing this:
[attrString appendAttributedString:imageAttrString];
And then adding in all the rest of the attributed text that I originally generated.
When I look at the file now, there is no image. QuickLook looks good in the debugger, but no image in the final output.
Thanks in advance for any help with this.
Although, RTF does support embedded images on Windows, apparently it doesn't on OS X. RTF was developed by Microsoft and they added embedded images in version 1.5 (http://en.wikipedia.org/wiki/Rich_Text_Format#Version_changes). I think that Apple took earlier version of the format and their solution to images in documents was RTFD. Here is what Apple documentation says about RTF:
Rich Text Format (RTF) is a text formatting language devised by Microsoft Corporation. You can represent character, paragraph, and document format attributes using plain text with interspersed RTF commands, groups, and escape sequences. RTF is widely used as a document interchange format to transfer documents with their formatting information across applications and computing platforms. Apple has extended RTF with custom commands, which are described in this chapter.
So no images are mentioned. Finally to prove that RTF doesn't support images on mac, download this RTF document - it will show photo in Windows WordPad and won't show it in OS X TextEdit.
So as Larme mentioned - you should choose RTFD file type when adding attachments. From Wikipedia:
Rich Text Format Directory, also known as RTFD (due to its extension .rtfd), or Rich Text Format with Attachments
Although you will be able to get NSData object that contains both the text and the image (judging by its size), via dataFromRange:documentAttributes:#{NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType} error:] you probably won't be able to save it so that it could be opened successfully. At least - I wasn't able to do that.
That's probably because actually RTFD is not a file format - it's a format of a bundle. To check it, you could use TextEdit on your mac to create a new document, add image and a text to it and save it as a file. Then right click on that file and choose Show Package Contents and you'll notice that the directory contains both your image and the text in RTF format.
However you will be able to save this document successfully with this code:
NSFileWrapper *fileWrapper = [imageAttrString fileWrapperFromRange:NSMakeRange(0, [imageAttrString length]) documentAttributes:#{NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType} error:&error];
[fileWrapper writeToURL:yourFileURL options:NSFileWrapperWritingAtomic originalContentsURL:nil error:&error];
Because apparently NSFileWrapper knows how to deal with RTFD documents while NSData has no clue of what it contains.
However the main problem still remains - how to send it in email? Because RTFD document is a directory not a file, I'd say it's not very well suited for sending by email, however you can zip it and send with an extension .rtfd.zip. The extension here is the crucial because it will tell Mail app how to display contents of the attachment when user taps on it. Actually it will work also in Gmail and probably other email apps on iOS because it's the UIWebView that knows how to display .rtfd.zip. Here is a technical note about it: https://developer.apple.com/library/ios/qa/qa1630/_index.html#//apple_ref/doc/uid/DTS40008749
So the bottom line is - it can be done but the RTFD document will be an attachment to the email not the email content itself. If you want to have it as an email content you should probably look into embedding your image into HTML and sending the mail as HTML.
As Andris mentioned, Apple RTF implementation does not support embedded images.
RTFD isn't a real alternative, as only a few OS X apps can open RTFD files. For example MS Office can't.
Creating a HTML file with embedded images might help in some cases, but - for example - most email clients don't support HTML with embedded images (Apple Mail does, Outlook however doesn't).
But fortunately there is a solution to create real RTF files with embedded images!
As the RTF format of course supports embedded images (only Apples implementation doesn't), images in a NSAttributedStrings (NSTextAttachments) can be (hand) coded into the RTF stream.
The following category does all the work needed:
/**
NSAttributedString (MMRTFWithImages)
*/
#interface NSAttributedString (MMRTFWithImages)
- (NSString *)encodeRTFWithImages;
#end
/**
NSAttributedString (MMRTFWithImages)
*/
#implementation NSAttributedString (MMRTFWithImages)
/*
encodeRTFWithImages
*/
- (NSString *)encodeRTFWithImages {
NSMutableAttributedString* stringToEncode = [[NSMutableAttributedString alloc] initWithAttributedString:self];
NSRange strRange = NSMakeRange(0, stringToEncode.length);
//
// Prepare the attributed string by removing the text attachments (images) and replacing them by
// references to the images dictionary
NSMutableDictionary* attachmentDictionary = [NSMutableDictionary dictionary];
while (strRange.length) {
// Get the next text attachment
NSRange effectiveRange;
NSTextAttachment* textAttachment = [stringToEncode attribute:NSAttachmentAttributeName
atIndex:strRange.location
effectiveRange:&effectiveRange];
strRange = NSMakeRange(NSMaxRange(effectiveRange), NSMaxRange(strRange) - NSMaxRange(effectiveRange));
if (textAttachment) {
// Text attachment found -> store image to image dictionary and remove the attachment
NSFileWrapper* fileWrapper = [textAttachment fileWrapper];
UIImage* image = [[UIImage alloc] initWithData:[fileWrapper regularFileContents]];
// Kepp image size
UIImage* scaledImage = [self imageFromImage:image
withSize:textAttachment.bounds.size];
NSString* imageKey = [NSString stringWithFormat:#"_MM_Encoded_Image#%zi_", [scaledImage hash]];
[attachmentDictionary setObject:scaledImage
forKey:imageKey];
[stringToEncode removeAttribute:NSAttachmentAttributeName
range:effectiveRange];
[stringToEncode replaceCharactersInRange:effectiveRange
withString:imageKey];
strRange.length += [imageKey length] - 1;
} // if
} // while
//
// Create the RTF stream; without images but including our references
NSData* rtfData = [stringToEncode dataFromRange:NSMakeRange(0, stringToEncode.length)
documentAttributes:#{
NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType
}
error:NULL];
NSMutableString* rtfString = [[NSMutableString alloc] initWithData:rtfData
encoding:NSASCIIStringEncoding];
//
// Replace the image references with hex encoded image data
for (id key in attachmentDictionary) {
NSRange keyRange = [rtfString rangeOfString:(NSString*)key];
if (NSNotFound != keyRange.location) {
// Reference found -> replace with hex coded image data
UIImage* image = [attachmentDictionary objectForKey:key];
NSData* pngData = UIImagePNGRepresentation(image);
NSString* hexCodedString = [self hexadecimalRepresentation:pngData];
NSString* encodedImage = [NSString stringWithFormat:#"{\\*\\shppict {\\pict \\pngblip %#}}", hexCodedString];
[rtfString replaceCharactersInRange:keyRange withString:encodedImage];
}
}
return rtfString;
}
/*
imageFromImage:withSize:
Scales the input image to pSize
*/
- (UIImage *)imageFromImage:(UIImage *)pImage
withSize:(CGSize)pSize {
UIGraphicsBeginImageContextWithOptions(pSize, NO, 0.0);
[pImage drawInRect:CGRectMake(0, 0, pSize.width, pSize.height)];
UIImage* resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
/*
hexadecimalRepresentation:
Returns a hex codes string for all bytes in a NSData object
*/
- (NSString *) hexadecimalRepresentation:(NSData *)pData {
static const char* hexDigits = "0123456789ABCDEF";
NSString* result = nil;
size_t length = pData.length;
if (length) {
NSMutableData* tempData = [NSMutableData dataWithLength:(length << 1)]; // double length
if (tempData) {
const unsigned char* src = [pData bytes];
unsigned char* dst = [tempData mutableBytes];
if ((src) &&
(dst)) {
// encode nibbles
while (length--) {
*dst++ = hexDigits[(*src >> 4) & 0x0F];
*dst++ = hexDigits[(*src++ & 0x0F)];
} // while
result = [[NSString alloc] initWithData:tempData
encoding:NSASCIIStringEncoding];
} // if
} // if
} // if
return result;
}
#end
The basic idea was taken from this article.

NSDictionary / Base64 String Logs

I have this weird problem about NSDictionary and base64 String and I cannot locate where the problem is. Here's the code:
NSData *pictureData = [[NSData alloc]init];
pictureData = UIImagePNGRepresentation([UIImage imageNamed:#"logo"]);
NSString * picture = [pictureData base64EncodedString];
picture = [picture stringByReplacingOccurrencesOfString:#"+" withString:#"%2B"];
if(picture == nil){
picture = #"";
}
self.postDictionary = [[NSDictionary alloc]initWithObjectsAndKeys:picture,#"picture",#"some text",#"caption", nil];
What happens is If I log the string,"picture", the log is very fine and okay.
But when I try logging the dictionary it says something like this
{
caption = "some text";
picture = "iVBORw0KGgoAAAANSUhEUgAAAoAAAABYCAIAAADqXdEfAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAHGlET1QAAAACAAAAAAAAACwAAAAoAAAALAAAACwAAI2cl9ZnZQAAQABJREFUeAGM3euyXVl5HmDdWa7EuYec7sDBlZSrErtS+RP/clXiuCr+YzAYaKDpBmPABpr0S...and it gets CUT some part then... picture = iVBORw0KGgoAAAANSUhEUgAAAoAAAABYCAIAAADqXdEfAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAHGlET1QAAAACAAAAAAAAACwAAAAoAAA..till the end of the base64 string";
}
The problem is the word "picture" as key is found also in the string object inside picture. The base64 string was cut first then followed by the picture = then the full text of the base64 string
Does not happen on simulator but happens on device. Before was just fine. I didn't changed anything on the codes. and I cannot change the NSDictionary codes also.
If I don't log it it's still like that when the web service receives the POST.
So if you guys can help me find a way. Thanks :)

How to convert formatted content of NSTextView to string

I need transfer content of NSTextView from Mac app to iOS app. I'm using XML as transfered file format.
So I need to save content of NSTextView (text, fonts, colors atd.) as a string. Is there any way how to do that?
One way to do this is to archive the NSAttributedString value. Outline sample code typed directly into answer:
NSTextView *myTextView;
NSString *myFilename;
...
[NSKeyedarchiver archiveRootObject:myTextStorage.textStorage
toFile:myFilename];
To read it back:
myTextView.textStorage.attributedString = [NSKeyedUnarchiver unarchiveObjectWithFile:myFilename];
That's all that is needed to create and read back a file. There are matching methods which create an NSData rather than a file, and you can convert an NSData into an NSString or just insert one into an NSDictionary and serialise that as a plist (XML), etc.
Your best bet is probably to store the text as RFTD and load it as such in the other text view via an NSAttributedString.
// Load
NSFileWrapper* filewrapper = [[NSFileWrapper alloc] initWithPath: path];
NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper: filewrapper];
NSAttributedString* origFile = [NSAttributedString attributedStringWithAttachment: attachment];
// Save
NSData *data = [origFile RTFDFromRange: NSMakeRange(0, [origFile length]) documentAttributes: nil];
[[NSFileManager defaultManager] createFileAtPath: path contents: data attributes:nil];

iOS: How to copy HTML into the cut-paste buffer?

I'm interested in letting my users copy the text they've entered into the cut-and-paste buffer, but I'd like to do that as HTML.
Is such a thing even possible? Or do I need to use a MIME format? (I have no idea.)
Thanks.
The following code will get your HTML out of your app and into Apple's Mail app. The documentation doesn't give you a great deal of help on this, so in part it's a matter of looking at what Apple's apps park on the pasteboard and then reverse engineering that. This solution draws on an earlier stackoverflow post - follow up the links there for more background.
NSLog(#"Place HTML on the pasteboard");
UIPasteboard* pasteboard = [UIPasteboard generalPasteboard];
NSString *htmlType = #"Apple Web Archive pasteboard type";
// example html string
NSString* htmlString = #"<p style=\"color:gray\"> Paragraft<br><em>Less than a word processor, more than plain text</em>";
NSMutableDictionary *resourceDictionary = [NSMutableDictionary dictionary];
[resourceDictionary setObject:[htmlString dataUsingEncoding:NSUTF8StringEncoding] forKey:#"WebResourceData"];
[resourceDictionary setObject:#"" forKey:#"WebResourceFrameName"];
[resourceDictionary setObject:#"text/html" forKey:#"WebResourceMIMEType"];
[resourceDictionary setObject:#"UTF-8" forKey:#"WebResourceTextEncodingName"];
[resourceDictionary setObject:#"about:blank" forKey:#"WebResourceURL"];
NSDictionary *containerDictionary = [NSDictionary dictionaryWithObjectsAndKeys:resourceDictionary, #"WebMainResource", nil];
NSDictionary *htmlItem = [NSDictionary dictionaryWithObjectsAndKeys:containerDictionary,htmlType,nil];
[pasteboard setItems: [NSArray arrayWithObjects: htmlItem, nil]];
// This approach draws on the blog post and comments at:
// http://mcmurrym.wordpress.com/2010/08/13/pasting-simplehtml-into-the-mail-app-ios/
This solution puts both a HTML and a plain text representation into the pasteboard:
#import <MobileCoreServices/MobileCoreServices.h>
NSString *html = #"<h1>Headline</h1>text";
NSData *data = [html dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = #{#"WebMainResource": #{#"WebResourceData": data, #"WebResourceFrameName": #"", #"WebResourceMIMEType": #"text/html", #"WebResourceTextEncodingName": #"UTF-8", #"WebResourceURL": #"about:blank"}};
data = [NSPropertyListSerialization dataWithPropertyList:dict format:NSPropertyListXMLFormat_v1_0 options:0 error:nil];
NSString *archive = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSString *plain = [html stringByReplacingOccurrencesOfRegex:#"<[^>]+>" withString:#""];
[UIPasteboard generalPasteboard].items = #[#{#"Apple Web Archive pasteboard type": archive, (id)kUTTypeUTF8PlainText: plain}];
It uses -stringByReplacingOccurrencesOfRegex: from RegexKitLite to strip the HTML tags.
I absolutely adore this method of creating HTML-based content that you can paste into other HTML-aware apps, like Mail. However, I noticed that the above solution by Matthew Elton only allowed the pasteboard to be pasted onto HTML-aware apps. Trying to paste the exact same content into the Notes app for example, would fail.
I took the tips from this post: https://stackoverflow.com/a/1078471/351810 and can now successfully paste both HTML and plain text versions of the content that I want.
I use w3schools.
I cut and paste my html code over their example code , on any of their many "Try it yourself" tutorials and then use their "run" button.
e.g. https://www.w3schools.com/html/default.asp

Resources