iOS 8 Custom Keyboard - ios

I am trying to build a custom keyboard, it's like a emoji keyboard, but the keyboard's data is from a json file. After parse this json file and get the data, how to make the custom keyboard use it and show in the keyboard view, like the emoji keyboard that built in? Right now, I follow App Extension Keyboard: Custom Keyboard guide, and there only small bits of information here. Is there any tutorial or guide about how to create a custom emoji keyboard online? The current codes I am trying are below:
class KeyboardViewController: UIInputViewController {
override func viewDidLoad() {
super.viewDidLoad()
var error: NSError?
let yanFile = NSBundle.mainBundle().pathForResource("yan", ofType: "json")
let yanData = NSData(contentsOfFile: yanFile) as NSData
let yanDict = NSJSONSerialization.JSONObjectWithData(yanData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
println("dict: \(yanDict)") //print nothing in console
// Perform custom UI setup here
self.nextKeyboardButton = UIButton.buttonWithType(.System) as UIButton
self.nextKeyboardButton.setTitle(NSLocalizedString("Next Keyboard", comment: "Title for 'Next Keyboard' button"), forState: .Normal)
}
}
The json like below:
{
"list":
[
{
"tag": "laugh",
"yan":
[
"o(*≧▽≦)ツ┏━┓",
"(/≥▽≤/)",
"ヾ(o◕∀◕)ノ"
]
},
{
"tag": "wanna",
"yan":
[
"✪ω✪",
"╰(*°▽°*)╯",
"≖‿≖✧",
">ㅂ<",
"ˋ▽ˊ",
"✪ε✪",
"✪υ✪",
"ヾ (o ° ω ° O ) ノ゙",
"(。◕ˇ∀ˇ◕)",
"(¯﹃¯)"
]
}
]
}

You can build a xib file by clicking new file -> view
1) inside the xib file create a uiview 320x216 and you can drag'n'drop whatever controls you want into it
2) then you can load the nib like this into your keyboard's inputView:
// Perform custom UI setup here
UIView *layout = [[[NSBundle mainBundle] loadNibNamed:#"keyboardXib" owner:self options:nil] objectAtIndex:0];
[self.inputView addSubview:layout];
3) i think it's amazing if you build a JSON to keyboard api
you send a JSON of the keyboard map to your app
and the app knows how to arrange the keys on the inputView accordingly
let us know if you build this project!
EDIT:
4) Most of what you need to do is parse the JSON and display the content you want from the JSON uibuttons, and also decide what text they are inserting into the text field
check out this question: How to parse a JSON file in swift?
Good luck!

First of all you need to create your UI for keyboard in your KeyboardViewController. It's up to you how you customize it, add buttons, views, gestures etc.. (By the way height of view is limited, to standard keyboard height size, so don't try to make it higher it won't draw) Template that is generated it's just sample to show how you can put a single button in it. After you setup your UI make sure you have Next Keyboard Button it's required.
Regarding Emoji, it's not real images, they are just unicode characters that later replaced with images by system. So you can't pass images, the only input that you can provide is NSString [self.textDocumentProxy insertText:#"hello "]; // Inserts the string "hello " at the insertion point
More details can be found here https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/Keyboard.html.

Related

Instantly format a UITextView using AttributedString

I'm developing a macOS rich-text editor that applies pre-defined style for each line of the text view.
To format the lines, I'm using NSAttributedString, then, I'm inserting that string into my UITextView. To make things easier, I'm using a tool called SwiftRichString.
My code looks like below. It's straight-forward and works fine.
import Cocoa
import SwiftRichString
import AppKit
class ViewController: NSViewController {
#IBOutlet var textView: NSTextView!
override func viewDidLoad() {
super.viewDidLoad()
// Format the string
let style = Style {
$0.font = NSFont(name: "Arial", size: 20)
$0.color = NSColor.black
$0.alignment = .center
}
let attributedText = "Hello World!".set(style: style)
// Add formatted string to the text view
textView.textStorage?.append(attributedText)
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
Current situation:
User is typing a formatted line. Then when user hits Return and types something, format of the new line returns back to the default style of the UITextView.
What I want:
User is typing a certain formatted line, then he hits Return. The next line should be formatted to another pre-defined style on-the-go.
Example:
User is typing the Title line. Current style is (Arial, bold, 20pt).
He hits Return.
Next line should be styled as Normal Text using a pre-defined style (Arial, 12pt).
Important Note:
In my above code, I was able to format the line easily because it's hard-coded. My real issue is, how can I instantly format the next line, because the next line will be entered by the user. The style should be applied to the next line before user begins writing it.
Okay, I just figured out how to use typingAttributtes to solve this question (thanks to #Larme for the hint).
// Define next attributes
let attributes: [NSAttributedString.Key: Any] = [
.foregroundColor: NSColor.red,
.font: NSFont(name: "Arial", size: 12)!,
]
// Assign attributes to the text view typing attributes
textView.typingAttributes = attributes
Very easy!
Pardon off topic. If you're making a text editor, you may consider using a table view, where each text line is a cell - this is extra work for you as a programmer but it'll boost the performance significantly. That's how Xcode editor is built.
Maybe you might use optional func textViewDidChange(_ textView: UITextView)
https://developer.apple.com/documentation/uikit/uitextviewdelegate/1618599-textviewdidchange
and after the change, just parse the text, find new lines, split them and apply all styling you want

Printing random string from an array on textview

I can't seem to get my array printed onto my textview. I have an array and have set my textview (texthold) to the randomIndex of the array.. Anything you guys see I'm doing wrong?
This is my button that when clicked is supposed to get a random string from the devices array and print it into the textview field. I am getting no errors just nothing displays onto the textview when the button is clicked
#IBAction func Generate(_ sender: Any) {
let devices = ["Apple Watch", "iPhone", "iPad", "Mac", "Apple TV"]
// Generate a random index
let randomIndex = Int(arc4random_uniform(UInt32(devices.count)))
// Get a random item
let randomItem = devices[randomIndex]
texthold.text = devices[randomIndex]
}
This code works in my program. Check your layout using "Debug view hierarchy tool", maybe it will help.
And:
texthold.text = randomItem
Name methods with lowercase (Generate -> generate)
Check if your button touch calls this method
Check if your UI items have connected outlets.
There may be problem with changing text from background thread, but if you really have this method connected from storyboard/xib as method for outlet's action - this situation impossible.
And check that your code is being called on .touchUpInside action of your button (second screenshot in storyboard)!

Emoji view in iOS chat application using Swift

I am working on chat application, Where I need to show Emoji view on button selection. So I can select and send emoji within the text message. This functionality is already inside Messenger application. I know there is button already in keyboard but I want to add button outside keyboard. Please let me know if there is any resource available to get it done quickly.
This way you can array of Emoji.
let emojiRanges = [
0x1F601...0x1F64F, // emoticons
0x1F30D...0x1F567, // Other additional symbols
0x1F680...0x1F6C0, // Transport and map symbols
0x1F681...0x1F6C5 //Additional transport and map symbols
]
var emojis: [String] = []
for range in emojiRanges {
for i in range {
let c = String(describing: UnicodeScalar(i)!)
emojis.append(c)
}
}

Structuring UIViewControllers with images inside of text

I have to create an application that has 5 UIViewControllers, each with big text and images inside the text. What I have done so far was to add a UITextView in the UIViewController and load with an rtf file the whole text (every text is big).
Now I have to add images inside the text in some places. What do you propose that could be the best way to construct it? I tried to add the image inside the the rtf file but it is not working properly. Since the text is too big I did not want to add the text manually by typing it. Also, I have a top bar menu that slides the view to each content, that is why I had to have only one UITextView. I am looking for a best solution.
What about adding your texts with images on UIWebView with loading these texts by wrapping them into html?
You can also add javascript callbacks which you will be able to handle in swift or obj-c by adding JavascriptCore.framework to your build phases:
Add button in your code:
<button text="Close" onclick="javascript:callSwiftCode()">Call swift code</button>
And in your UIWebViewDelegate class:
func webViewDidFinishLoad(webView: UIWebView) {
let context: JSContext = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
let codeClosure: #convention(block) ()->() = { ()->() in
print ("This is callback from javascript you can add your code in this closure")
}
let casted: AnyObject = unsafeBitCast(codeClosure, AnyObject.self) as AnyObject
context.setObject(casted, forKeyedSubscript: "callSwiftCode")
}
You can achieve this using NSAttributedString and NSTextAttachment. Attributed strings are strings with formatting attached(bold, italics, colors, etc), but you can also attach the images inside attributed strings, and they just get drawn right along with the text. Below example might help you understand:
//Create a mutable attributed string so that we could append everything to it.
let bigText = NSMutableAttributedString(string: "Your text starts here")
//Create a NSTextAttachment
let image1Attachment = NSTextAttachment()
image1Attachment.image = UIImage(named: "image1.png")
// wrap the attachment in its own attributed string so we can append it
let image1String = NSAttributedString(attachment: image1Attachment)
// add the NSTextAttachment wrapper to our full string, then add some more text.
bigText.appendAttributedString(image1String)
bigText.appendAttributedString(NSAttributedString(string: "End of text"))
// Then set this bigText to your label's attributedText property.
yourLabel.attributedText = bigText

text editing & saving in IOS app

I have a UITextview showing certain text by calling rtf files.
I want to let users to edit the text on UITextView and save the changes they made in rtf file.
Is there any way I can change the rtf file itself by changing the text on UITextView??
If you want a save-as-you-type solution to the problem:
Make your view controller conform to UITextViewDelegate
Connect the text view's delegate to the view controller
Add the following function to your view controller:
// Path to your RTF file
let url = NSBundle.mainBundle().URLForResource("my_document", withExtension: "rtf")!
func textViewDidChange(textView: UITextView) {
let data = try! textView.attributedText.dataFromRange(NSMakeRange(0, textView.attributedText.length), documentAttributes: [NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType])
data.writeToURL(url, atomically: true)
}
This will save every keystroke to the file. No idea on the performance though. I have not tested this on a real iPhone. If it's too hard on the device, consider putting a time delay between saves or have an NSTimer to save every n seconds.

Resources