Custom GIF Keyboard in iOS8 - ios

I am creating Custom GIF Keyboard in iOS8 using app extension. I was created layout of my custom keyboard. I was implement LongPress Gesture for selecting GIF Image but its not work. so what can i do for this or any suggestion regarding to this?
- (void)textWillChange:(id<UITextInput>)textInput {
[self.textDocumentProxy insertText:#"Hi"];
}
I also tried with UITextInputDelegate mentioned above.
This method is also deals with only text append. But My concern is to load gif or png image in input area.

I have done with long press gesture and make a method for touch handler.
-(void)tapped:(id)sender
{
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
UIImage *image = [UIImage imageNamed:#"img_temp.gif"];
NSData *imgData = UIImagePNGRepresentation(image);
[pasteboard setData:imgData forPasteboardType:[UIPasteboardTypeListImage objectAtIndex:0]];
}
I also given become first responder aswell.
-(BOOL)canBecomeFirstResponder
{
return YES;
}
I can copy text in pasteboard, but I can't copy .gif or .png image.

What Popkey, for example, are doing is copy the clicked GIF to the pasteboard.
The user then needs to long click their rich text field and paste the content into their iMessage for example.

You couldn't load a gif directly in the input area. To do that you have to copy the gif to the pasteboard and then paste the gif in the input area.
To copy the gif into the pasteboard you need to convert it into the NSData.
Here is the demo code in Swift 3.0.
let pb = UIPasteboard.general
let data = NSData(contentsOfURL: url)
if data != nil
{
self.pb.setData(data!, forPasteboardType: kUTTypeGIF as String)
}

Related

Create PDF with proper format and Images in Objective - C

Please read my scenario carefully,
I have one UITextView and one UIImageView bottom of TextView.
Each time there will be dynamic content in TextView and accordingly that, I am asking User to make a signature and it will be displayed as an image in bottom ImageView.
Now the requirement is I have to pass these details on the server along with Signature in one PDF file, So I have to create PDF file which contains both TextView text and ImageView image.
Note: TextView is containing Html text also, so it should show in the same format in PDF also.
Check below Images as required and current pdfs.
This is required PDF
This is current PDF
Only Put the code which can be helpful for both HTML support and Image merge with text. Please don't show simple PDF creation as I have done it already.
you don't need a 3rd party library, Cocoa and Cocoa touch have rich PDF support. I've stubbed you out a little start, do this in your viewController. There may be a few small errors, Ive been using swift for a couple of years now but I used my very rusty objC here because you tagged the question that way. Let me know any problems, good luck
-(NSData *)drawPDFdata{
// default pdf..
// 8.5 X 11 inch #72dpi
// = 612 x 792
CGRect rct = {{0.0 , 0.0 } , {612.0 , 792.0}}
NSMutableData *pdfData = [[NSMutableData alloc]init];
UIGraphicsBeginPDFContextToData(pdfData, rct, nil);
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
UIGraphicsBeginPDFPage();
//textView drawing
CGContextSaveGState(pdfContext);
CGContextConcatCTM(pdfContext, CGAffineTransformMakeTranslation(50.0,50.0));//this is just an offset for the textView drawing. You will want to play with the values, espeecially if supporting multiple screen sizes you might tranform the scale as well..
[textView.layer renderInContext:pdfContext]
CGContextRestoreGState(pdfContext);
//imageView drawing
CGContextSaveGState(pdfContext);
CGContextConcatCTM(pdfContext, CGAffineTransformMakeTranslation(50.0,50.0)); //this is just an offset for the imageView drawing. Thee same stuff applies as above..
[imageView.layer renderInContext:pdfContext]
CGContextRestoreGState(pdfContext);
//cleanup
UIGraphicsEndPDFContext();
return pdfData;
}
here's a couple of client functions to use this NSData
//ways to use the pdf Data
-(Bool)savePDFtoPath: (NSString *)path {
return [ [self drawPDFdata] writeToFile:path atomically:YES] ;
}
//requires Quartz framework.. (can be drawn straight to a UIView)
// note you MAY owe a CGPDFDocumentRelease() on the result of this function (sorry i've not used objC in a couple of years...)
-(CGPDFDocument *)createPDFdocument {
NSData *data = [self drawPDFdata];
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL , data , sizeof(data) ,NULL);
CGPDFDocument result = CGPDFDocumentCreateWithProvider(provider);
CGDataProviderRelease(provider); //not sure if this is still required under ARC?? (def not in swift)
return result;
}
Try this useful third party library :
https://github.com/iclems/iOS-htmltopdf
Use this function for your problem :
+ (id)createPDFWithHTML:(NSString*)HTML pathForPDF:(NSString*)PDFpath pageSize:(CGSize)pageSize margins:(UIEdgeInsets)pageMargins successBlock:(NDHTMLtoPDFCompletionBlock)successBlock errorBlock:(NDHTMLtoPDFCompletionBlock)errorBlock;

How do I paste an image programmatically with Swift?

I have a working code where I copy an image to UIPasteboard, but I cannot find a way to implement the PASTE functionality programmatically. Any idea or tip?
The following piece of code might work. Make sure you are testing on the device.
let image = UIImage(named: "person.png")
UIPasteboard.generalPasteboard().image = image;
based on the comment, you can do it as follows. I am putting here the objective-c code, I hope you could get the idea then convert it to the swift.
NSData* pasteData = [[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString*)kUTTypeJPEG];
you may find the swift solution in the following url
Swift UIPasteboard not copying PNG
Swift 3
If an imaged has been copied from another application (e.g. Safari) this is how I add it into my app. I trigger this from a UIAlertController as a UIAlertAction.
let pasteboard = UIPasteboard.general
if pasteboard.hasImages {
myImage.image = pasteboard.image
}
Alternatively, you may use NSData. It works on Simulator too.
// Copy
let image = UIImage(named: "sample")
let imageData = UIImageJPEGRepresentation(image!, 1)
UIPasteboard.general.setData(imageData!, forPasteboardType: "image")
// Paste
let imageData = UIPasteboard.general.data(forPasteboardType: "image")
let image = UIImage(data:imageData!)
copiedImage.image = image

app-specific UIPasteboard

I'm trying to create app-specific UIPasteboard, but have some problems figuring out how to register it:
UIPasteboard *pasteboard = [UIPasteboard pasteboardWithName:#"myPasteboard" create:YES];
If I just create it, app continues to use generalPasteboard. I really hope that I don't have to catch cut/copy/paste operations and set items manually.
Please read this article
http://nshipster.com/uimenucontroller/ (It's about UILabel, not UITextField but is useful just for example and information about how copy/paste/edit actions work and how you can customize its' behavior)
I think you need to subclass UITextField to MyTextField for example, and override -(void)copy: and -(void)paste: methods from UIResponderStandardEditActions.
In your implementation of these methods you should use your custom UIPasteboard to copy text into and paste from it, like mentioned in this answer,
How to do copy/paste function programmatically in iphone?
but instead of using [UIPasteboard generalPasteboard] use [UIPasteboard pasteboardWithName:#"myPasteboard" create:YES]
//Copy your text field text and Just App in Pasteboard
NSString * text=textfield.text;
UIPasteboard * pasteboard=[UIPasteboard generalPasteboard];
[pasteboard setString:text];
Below is a Tutorial about Pasteboard.
http://hayageek.com/uipasteboard-example-read-write-share/
//pasteboard initialization
let pasteBoard = UIPasteboard.general
// copying the content of textview to pasteboard
if(pasteBoard.hasStrings){
pasteBoard.string = textViewPB.text
}
//pasting the content of pasteboard to textview
if(pasteBoard.hasStrings){
textViewPB.text = pasteBoard.string
}

Screenshot Safari from Share Extension

Is it possible to perform a screenshot of the current visible zone of the webview in Safari from a Share Extension? I could use windows, but UIApplication isn't supported on extensions so I can't access to that window.
You can't since UIApplication can't be reached from an extension. You cannot get the first UIWindow, which is the Safari layer, so you have to play with the Javascript preprocessing file that the extensions have. So just create a Javascript file that, when sent to Safari, generates a base64 string with the current visible zone image data. Take that string through the kUTTypePropertyList identifier in your extension. Since that should be NSData, generate the UIImage from there, by using +imageWithData. That is what you're looking for, without having to load the page again, preventing a second load and a bad image if the webpage requires of a login.
As far as I know, you can't unless you invoke the API you need dynamically, and even so you might run into context permission issues and app store approval issues.
An alternative might be passing the current Safari URL to your extension, load it using a hidden UIWebView and render this view into an UIImage but you will loose the current visible zone information...
Edit: So the below works in the Simulator but does not work on the device. I'm presently looking for a solution as well.
You can't get just the visible area of Safari, but you can get a screenshot with a little ingenuity. The following method captures a screenshot from a ShareViewController.
func captureScreen() -> UIImage
{
// Get the "screenshot" view.
let view = UIScreen.mainScreen().snapshotViewAfterScreenUpdates(false)
// Add the screenshot view as a subview of the ShareViewController's view.
self.view.addSubview(view);
// Now screenshot *this* view.
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, false, 0);
self.view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Finally, remove the subview.
view.removeFromSuperview()
return image
}
This is the approved way to capture the screenshot of a webpage in a share extension:
for (NSExtensionItem *item in self.extensionContext.inputItems) {
for (NSItemProvider *itemProvider in item.attachments) {
[itemProvider loadPreviewImageWithOptions:#{NSItemProviderPreferredImageSizeKey: [NSValue valueWithCGSize:CGSizeMake(60.0f, 60.0f)]} completionHandler:^(UIImage * item, NSError * _Null_unspecified error) {
// Set the size to that desired, however,
// Note that the image 'item' returns will not necessarily by the size that you requested, so code should handle that case.
// Use the UIImage however you wish here.
}];
}
}

Why is textView:shouldInteractWithTextAttachment:inRange: never getting called on UITextView delegate?

Is anyone using this delegate method ? I get callbacks on
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
But not on this one. The documentation seems a bit ambiguous about what this is intended for
- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange
According to the documentation on the Web this is what its intended for:
Discussion
The text view calls this method if the user taps or long-presses the text attachment and its image property is not nil. Implementation of this method is optional. You can use this method to trigger an action in addition to displaying the text attachment inline with the text.
And here is Xcode 5 documentation:
Asks the delegate if the specified text view should display the provided text attachment in the given range of text.
The text view calls this method when a text attachment character is recognized in its text container by a data detector. Implementation of this method is optional. You can use this method to trigger an alternative action besides displaying the text attachment inline with the text in the given range.
EDIT:
Mmm OK I figured out the problem. If I paste an image in from iOS then it works, however if the image was pasted in from OS X it does not. It seems that the actual attachment formats used are not quite the same on both platforms despite the fact that the image appears to show up correctly in the text views. On closer inspection the NSTextAttachment classes don't appear to be the same on iOS as on OS X.
If anyone can shed any light on the cross platform compatibility here please do.
Also if I save the attributed string after pasting the image in on iOS and then retrieve it and display it in the UITextView interaction with the attachment is no longer possible. It would appear that when storing the image the image is actually placed in contents if contents is nil. So maybe I am going to have to iterate through all attachments to check what data is stored where particularly to figure out any differences in behaviour across the OS X and iOS platforms.
FURTHER EDIT:
The method only gets called if the attachment image is NOT nil and despite the fact that an image is displayed the actual image attribute can actually be nil, silly me! Anyway the fix seems to be to check all the attachments in the attributed string and to set their image attribute to something, usually the contents of the fileWrapper. The default NSTextAttachment behaviour seems to be to store the image in the fileWrapper when its archived but it does not do the reverse when its unarchived. Anyway I want to retain the original image in the attachment but depending on the device display a suitably scaled version of the original !
The chief thing is that the text view's editable property must be NO and it's selectable property must be YES. Those are the only circumstances under which this delegate method is called. If you are getting shouldBeginEditing then your text field is editable which is exactly what it must not be.
Here is what I do to ensure the NSTextAttachments image attribute gets set when restoring the UITextView's attributed string from archived data (in this case whenever the user selects a record from a Core Data store).
I set the UITextView up as a delegate for textStorage and in the didProcessEditing look for any attachments that may have been added and then check that their image attribute is set. I am also setting the scaling factor on the image to make sure the image scales appropriately for the device.
This way I don't loose the original resolution of the image and if the user wants to view it in more detail I provide the option to open it in an image browser window from a popup menu.
Hope this helps someone else.
EDIT:
Check here for more details on NSTextView and UITextView http://ossh.com.au/design-and-technology/software-development/
- (void)textStorage:(NSTextStorage *)textStorage didProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta {
//FLOG(#"textStorage:didProcessEditing:range:changeInLength: called");
[textStorage enumerateAttributesInRange:editedRange options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:
^(NSDictionary *attributes, NSRange range, BOOL *stop) {
// Iterate over each attribute and look for a Font Size
[attributes enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([[key description] isEqualToString:NSAttachmentAttributeName]) {
NSTextAttachment *attachment = obj;
//Reset the image attribute and scale for the device size if necessary
[self resetAttachmentImage:attachment];
}
}];
}];
}
- (void)resetAttachmentImage:(NSTextAttachment*)attachment {
UIImage *image = [attachment image];
float factor = 2;
if (image == nil) {
if (attachment.fileWrapper == nil || !attachment.fileWrapper.isRegularFile) {
attachment.image = [UIImage imageNamed:#"unknown_attachment.png"];
return;
}
//Usually retrieved from store
image = [UIImage imageWithData:attachment.fileWrapper.regularFileContents];
} else {
// Convert any pasted image
image = [UIImage imageWithData:UIImagePNGRepresentation(image)];
}
float imgWidth = image.size.width;
// If its wider than the view scale it to fit
if (imgWidth > _viewWidth) {
factor = imgWidth / _viewWidth + 0.5;
attachment.image = [UIImage imageWithData:UIImagePNGRepresentation(image) scale:factor];
} else {
attachment.image = [UIImage imageWithData:UIImagePNGRepresentation(image) scale:_scale];
}
}

Resources