From 5fe6464177b63f2f99fbf9b66db6cc4e5a897abc Mon Sep 17 00:00:00 2001 From: Gabriel Wong Date: Fri, 6 Oct 2017 12:47:28 +0700 Subject: [PATCH] Migrate KMTextFieldDelegate to Swift --- .../KeymanEngine.xcodeproj/project.pbxproj | 12 +-- .../Classes/KMTextFieldDelegateProxy.h | 30 ------ .../Classes/KMTextFieldDelegateProxy.m | 101 ------------------ .../Classes/KeymanTextField.swift | 30 ++---- .../KeymanTextFieldDelegateProxy.swift | 73 +++++++++++++ ios/engine/KMEI/KeymanEngine/Keyman.h | 2 - .../KeymanEngineDemo/MainViewController.swift | 2 +- 7 files changed, 88 insertions(+), 162 deletions(-) delete mode 100644 ios/engine/KMEI/KeymanEngine/Classes/KMTextFieldDelegateProxy.h delete mode 100644 ios/engine/KMEI/KeymanEngine/Classes/KMTextFieldDelegateProxy.m create mode 100644 ios/engine/KMEI/KeymanEngine/Classes/KeymanTextFieldDelegateProxy.swift diff --git a/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj b/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj index c1edd034a8..e77fef15e2 100644 --- a/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj +++ b/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ 98F9D6AE195412A60087AA43 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F26071FD158F8C4600F37184 /* CFNetwork.framework */; }; 98FFB3D41B67006F00289F0E /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 98FFB3D31B67006F00289F0E /* WebKit.framework */; }; 98FFB3D51B67008000289F0E /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 98FFB3D31B67006F00289F0E /* WebKit.framework */; }; + C0324B8D1F87480700AF3785 /* KeymanTextFieldDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0324B8C1F87480700AF3785 /* KeymanTextFieldDelegateProxy.swift */; }; C040E50E1F85FF8A00901EE4 /* KeyPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C040E50D1F85FF8A00901EE4 /* KeyPreviewView.swift */; }; C040E5101F8606E300901EE4 /* KeymanTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = C040E50F1F8606E300901EE4 /* KeymanTextField.swift */; }; C040E5121F86107E00901EE4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C040E5111F86107E00901EE4 /* AppDelegate.swift */; }; @@ -66,12 +67,10 @@ C06D37441F81F5C400F61AE0 /* KeyboardNameTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C08C62121F67C31100268D03 /* KeyboardNameTableViewCell.swift */; }; C06D37451F81F5C400F61AE0 /* KMManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F273AB9815641EC500A47CEE /* KMManager.m */; }; C06D37461F81F5C400F61AE0 /* PopoverView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0A5FF361F6682EB00BE740C /* PopoverView.swift */; }; - C06D37481F81F5C400F61AE0 /* KMTextFieldDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = F273ABA21564419700A47CEE /* KMTextFieldDelegateProxy.m */; }; C06D37491F81F5C400F61AE0 /* KMTextViewDelegateProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBD0DE1151EC30300D70779 /* KMTextViewDelegateProxy.m */; }; C06D374A1F81F5C400F61AE0 /* KMTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0A1406151EA8B3007FA4AD /* KMTextView.m */; }; C06D374B1F81F5F400F61AE0 /* Keyman.h in Headers */ = {isa = PBXBuildFile; fileRef = F27FCB67157FFE0B00FBBA20 /* Keyman.h */; settings = {ATTRIBUTES = (Public, ); }; }; C06D374D1F81FFF900F61AE0 /* KMManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F273AB9715641EC500A47CEE /* KMManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C06D374F1F81FFF900F61AE0 /* KMTextFieldDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = F273ABA11564419700A47CEE /* KMTextFieldDelegateProxy.h */; settings = {ATTRIBUTES = (Public, ); }; }; C06D37521F82001100F61AE0 /* KMTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C0A1405151EA8B3007FA4AD /* KMTextView.h */; settings = {ATTRIBUTES = (Public, ); }; }; C06D37531F82001100F61AE0 /* KMTextViewDelegateProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CBD0DE0151EC30300D70779 /* KMTextViewDelegateProxy.h */; settings = {ATTRIBUTES = (Public, ); }; }; C06D37541F82002700F61AE0 /* CWLSynthesizeSingleton.h in Headers */ = {isa = PBXBuildFile; fileRef = F273AB9A15641F0E00A47CEE /* CWLSynthesizeSingleton.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -185,6 +184,7 @@ 98F9D69A1954112F0087AA43 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 98F9D6CA19541D220087AA43 /* libKeyman.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libKeyman.a; path = build/libKeyman/libKeyman.a; sourceTree = ""; }; 98FFB3D31B67006F00289F0E /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + C0324B8C1F87480700AF3785 /* KeymanTextFieldDelegateProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeymanTextFieldDelegateProxy.swift; sourceTree = ""; }; C034BBBD1F7CCE7D00021FF5 /* KeyboardMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardMenuView.swift; sourceTree = ""; }; C040E50D1F85FF8A00901EE4 /* KeyPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPreviewView.swift; sourceTree = ""; }; C040E50F1F8606E300901EE4 /* KeymanTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeymanTextField.swift; sourceTree = ""; }; @@ -221,8 +221,6 @@ F273AB9815641EC500A47CEE /* KMManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = KMManager.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; F273AB9A15641F0E00A47CEE /* CWLSynthesizeSingleton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CWLSynthesizeSingleton.h; sourceTree = ""; }; F273AB9B1564207600A47CEE /* KMManager+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "KMManager+Internal.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - F273ABA11564419700A47CEE /* KMTextFieldDelegateProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = KMTextFieldDelegateProxy.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - F273ABA21564419700A47CEE /* KMTextFieldDelegateProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = KMTextFieldDelegateProxy.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; F27FCA7F157FB0DB00FBBA20 /* KME-iphoneos-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KME-iphoneos-Prefix.pch"; sourceTree = ""; }; F27FCAC2157FD10A00FBBA20 /* KME-iphonesimulator-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KME-iphonesimulator-Prefix.pch"; sourceTree = ""; }; F27FCAEE157FD59100FBBA20 /* Keyman-iphoneos.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Keyman-iphoneos.xcconfig"; sourceTree = ""; }; @@ -560,9 +558,8 @@ F273AB9E156440CD00A47CEE /* UITextField */ = { isa = PBXGroup; children = ( - F273ABA11564419700A47CEE /* KMTextFieldDelegateProxy.h */, - F273ABA21564419700A47CEE /* KMTextFieldDelegateProxy.m */, C040E50F1F8606E300901EE4 /* KeymanTextField.swift */, + C0324B8C1F87480700AF3785 /* KeymanTextFieldDelegateProxy.swift */, ); name = UITextField; sourceTree = ""; @@ -630,7 +627,6 @@ C06D372F1F81F4E100F61AE0 /* KeymanEngine.h in Headers */, C06D374B1F81F5F400F61AE0 /* Keyman.h in Headers */, C06D374D1F81FFF900F61AE0 /* KMManager.h in Headers */, - C06D374F1F81FFF900F61AE0 /* KMTextFieldDelegateProxy.h in Headers */, C06D37521F82001100F61AE0 /* KMTextView.h in Headers */, C06D37531F82001100F61AE0 /* KMTextViewDelegateProxy.h in Headers */, C06D37541F82002700F61AE0 /* CWLSynthesizeSingleton.h in Headers */, @@ -863,10 +859,10 @@ C06D37431F81F5C400F61AE0 /* KeyboardPickerBarButtonItem.swift in Sources */, C06D37441F81F5C400F61AE0 /* KeyboardNameTableViewCell.swift in Sources */, C040E5101F8606E300901EE4 /* KeymanTextField.swift in Sources */, + C0324B8D1F87480700AF3785 /* KeymanTextFieldDelegateProxy.swift in Sources */, C06D37451F81F5C400F61AE0 /* KMManager.m in Sources */, C045148A1F85DF9100D88416 /* KeymanInputViewController.swift in Sources */, C06D37461F81F5C400F61AE0 /* PopoverView.swift in Sources */, - C06D37481F81F5C400F61AE0 /* KMTextFieldDelegateProxy.m in Sources */, C06D37491F81F5C400F61AE0 /* KMTextViewDelegateProxy.m in Sources */, C06D374A1F81F5C400F61AE0 /* KMTextView.m in Sources */, ); diff --git a/ios/engine/KMEI/KeymanEngine/Classes/KMTextFieldDelegateProxy.h b/ios/engine/KMEI/KeymanEngine/Classes/KMTextFieldDelegateProxy.h deleted file mode 100644 index 24c1828992..0000000000 --- a/ios/engine/KMEI/KeymanEngine/Classes/KMTextFieldDelegateProxy.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// KMTextFieldDelegateProxy.h -// Keyman Engine -// -// Copyright (c) 2017 SIL International. All rights reserved. -// -// -// Proxies delegate messages for a KMTextField. -// This allows the KMTextField to hook into these calls while allowing a developer to still -// use the delegate as normal (albeit with a different name: 'keymanDelegate') -// -// This class is required because at the time of writing, setting a UITextField as it's -// own delegate caused an infinite loop in Apple's code, repeatedly calling the selectionDidChange callback -// See: http://lists.apple.com/archives/cocoa-dev/2010/Feb/msg01391.html - -#import - -@protocol KMTextFieldDelegate; - -@interface KMTextFieldDelegateProxy : NSObject { - id __weak keymanDelegate_; -} - -@property (nonatomic, weak) id keymanDelegate; - -@end - -@protocol KMTextFieldDelegate - // Setting this protocol space aside in case we later want to add additional delegate methods for KMTextField -@end diff --git a/ios/engine/KMEI/KeymanEngine/Classes/KMTextFieldDelegateProxy.m b/ios/engine/KMEI/KeymanEngine/Classes/KMTextFieldDelegateProxy.m deleted file mode 100644 index 9c66d9171d..0000000000 --- a/ios/engine/KMEI/KeymanEngine/Classes/KMTextFieldDelegateProxy.m +++ /dev/null @@ -1,101 +0,0 @@ -// -// KMTextFieldDelegateProxy.m -// Keyman Engine -// -// Created by Patrick Weekes on 12-05-16. -// Copyright (c) 2017 SIL International. All rights reserved. -// - -#import "KMTextFieldDelegateProxy.h" -#import "KeymanEngine/KeymanEngine-Swift.h" - -@implementation KMTextFieldDelegateProxy - -@synthesize keymanDelegate = keymanDelegate_; - -#pragma mark - Object Admin - -- (void)dealloc { - self.keymanDelegate = nil; -} - -#pragma mark - UITextFieldDelegate - -// NOTE: the return value from the textField's hook is ignored -- (BOOL)textFieldShouldBeginEditing:(KeymanTextField *)textField { - if ([textField respondsToSelector:@selector(textFieldShouldBeginEditing:)]) { - [textField textFieldShouldBeginEditing:textField]; - } - if ([self.keymanDelegate respondsToSelector:@selector(textFieldShouldBeginEditing:)]) { - return [self.keymanDelegate textFieldShouldBeginEditing:textField]; - } - return YES; -} - -- (void)textFieldDidBeginEditing:(KeymanTextField *)textField { - if ([textField respondsToSelector:@selector(textFieldDidBeginEditing:)]) { - [textField textFieldDidBeginEditing:textField]; - } - if ([self.keymanDelegate respondsToSelector:@selector(textFieldDidBeginEditing:)]) { - [self.keymanDelegate textFieldDidBeginEditing:textField]; - } -} - -// NOTE: the return value from the textField's hook is ignored -- (BOOL)textFieldShouldEndEditing:(KeymanTextField *)textField { - if ([textField respondsToSelector:@selector(textFieldShouldEndEditing:)]) { - [textField textFieldShouldEndEditing:textField]; - } - if ([self.keymanDelegate respondsToSelector:@selector(textFieldShouldEndEditing:)]) { - return [self.keymanDelegate textFieldShouldEndEditing:textField]; - } - - return YES; -} - -- (void)textFieldDidEndEditing:(KeymanTextField *)textField { - if ([textField respondsToSelector:@selector(textFieldDidEndEditing:)]) { - [textField textFieldDidEndEditing:textField]; - } - if ([self.keymanDelegate respondsToSelector:@selector(textFieldDidEndEditing:)]) { - [self.keymanDelegate textFieldDidEndEditing:textField]; - } -} - -// NOTE: the return value from the textField's hook is ignored -- (BOOL)textField:(KeymanTextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { - if ([textField respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) { - [textField textField:textField shouldChangeCharactersInRange:range replacementString:string]; - } - if ([self.keymanDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) { - return [self.keymanDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string]; - } - - return YES; -} - -// NOTE: the return value from the textField's hook is ignored -- (BOOL)textFieldShouldClear:(KeymanTextField *)textField { - if ([textField respondsToSelector:@selector(textFieldShouldClear:)]) { - [textField textFieldShouldClear:textField]; - } - if ([self.keymanDelegate respondsToSelector:@selector(textFieldShouldClear:)]) { - return [self.keymanDelegate textFieldShouldClear:textField]; - } - - return YES; -} - -// NOTE: the return value from the textField's hook is ignored -- (BOOL)textFieldShouldReturn:(KeymanTextField *)textField { - if ([textField respondsToSelector:@selector(textFieldShouldReturn:)]) { - [textField textFieldShouldReturn:textField]; - } - if ([self.keymanDelegate respondsToSelector:@selector(textFieldShouldReturn:)]) { - return [self.keymanDelegate textFieldShouldReturn:textField]; - } - - return YES; -} - -@end diff --git a/ios/engine/KMEI/KeymanEngine/Classes/KeymanTextField.swift b/ios/engine/KMEI/KeymanEngine/Classes/KeymanTextField.swift index f3000f086a..55e97f6eaf 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/KeymanTextField.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/KeymanTextField.swift @@ -17,7 +17,7 @@ public class KeymanTextField: UITextField, UITextFieldDelegate { public var shouldSetCustomFontOnKeyboardChange = true public var isInputClickSoundEnabled = true - private var delegateProxy: KMTextFieldDelegateProxy? + private var delegateProxy: KeymanTextFieldDelegateProxy! private var shouldUpdateKMText = false // MARK: - Object Admin @@ -32,27 +32,16 @@ public class KeymanTextField: UITextField, UITextFieldDelegate { public override init(frame: CGRect) { super.init(frame: frame) - - delegateProxy = KMTextFieldDelegateProxy() - delegate = delegateProxy - - if #available(iOS 9.0, *) { - inputAssistantItem.leadingBarButtonGroups = [] - inputAssistantItem.trailingBarButtonGroups = [] - } - - KMManager.sharedInstance() // Preload webview keyboard - - NotificationCenter.default.addObserver(self, selector: #selector(self.textFieldTextDidChange), - name: .UITextFieldTextDidChange, object: self) - NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardChanged), - name: NSNotification.Name.keymanKeyboardChanged, object: nil) + performCommonInit() } public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) + performCommonInit() + } - delegateProxy = KMTextFieldDelegateProxy(self) + private func performCommonInit() { + delegateProxy = KeymanTextFieldDelegateProxy(self) delegate = delegateProxy if #available(iOS 9.0, *) { @@ -66,6 +55,7 @@ public class KeymanTextField: UITextField, UITextFieldDelegate { name: .UITextFieldTextDidChange, object: self) NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardChanged), name: NSNotification.Name.keymanKeyboardChanged, object: nil) + } // MARK: - Class Overrides @@ -104,10 +94,10 @@ public class KeymanTextField: UITextField, UITextFieldDelegate { // MARK: - Public Methods - // Use this KMTextFieldDelegate instead of the normal UITextFieldDelegate. + // Use this KeymanTextFieldDelegate instead of the normal UITextFieldDelegate. // All of the normal UITextFieldDelegate methods are supported. - @objc public func setKeymanDelegate(_ keymanDelegate: KMTextFieldDelegate?) { - delegateProxy?.keymanDelegate = keymanDelegate + public func setKeymanDelegate(_ keymanDelegate: KeymanTextFieldDelegate?) { + delegateProxy.keymanDelegate = keymanDelegate KMManager.sharedInstance().kmLog( "KeymanTextField: \(self.debugDescription) keymanDelegate set to: \(keymanDelegate.debugDescription)", checkDebugPrinting: true) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/KeymanTextFieldDelegateProxy.swift b/ios/engine/KMEI/KeymanEngine/Classes/KeymanTextFieldDelegateProxy.swift new file mode 100644 index 0000000000..8153559006 --- /dev/null +++ b/ios/engine/KMEI/KeymanEngine/Classes/KeymanTextFieldDelegateProxy.swift @@ -0,0 +1,73 @@ +// +// KeymanTextFieldDelegateProxy.swift +// KeymanEngine +// +// Created by Gabriel Wong on 2017-10-06. +// Copyright © 2017 SIL International. All rights reserved. +// +// Proxies delegate messages for a KeymanTextField. +// This allows the KeymanTextField to hook into these calls while allowing a developer to still +// use the delegate as normal (albeit with a different name: 'keymanDelegate') +// +// This class is required because at the time of writing, setting a UITextField as it's +// own delegate caused an infinite loop in Apple's code, repeatedly calling the selectionDidChange callback +// See: http://lists.apple.com/archives/cocoa-dev/2010/Feb/msg01391.html + +import UIKit + +public protocol KeymanTextFieldDelegate: UITextFieldDelegate { } + +class KeymanTextFieldDelegateProxy: NSObject, UITextFieldDelegate { + weak var keymanDelegate: KeymanTextFieldDelegate? + private unowned let textField: UITextFieldDelegate + + init(_ textField: KeymanTextField) { + self.textField = textField + super.init() + } + + // MARK: - UITextFieldDelegate + + // NOTE: Return values from the KeymanTextField hooks are ignored + func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { + _ = self.textField.textFieldShouldBeginEditing?(textField) + return keymanDelegate?.textFieldShouldBeginEditing?(textField) ?? true + } + + func textFieldDidBeginEditing(_ textField: UITextField) { + self.textField.textFieldDidBeginEditing?(textField) + keymanDelegate?.textFieldDidBeginEditing?(textField) + } + + func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { + _ = self.textField.textFieldShouldEndEditing?(textField) + return keymanDelegate?.textFieldShouldEndEditing?(textField) ?? true + } + + func textFieldDidEndEditing(_ textField: UITextField) { + self.textField.textFieldDidEndEditing?(textField) + keymanDelegate?.textFieldDidEndEditing?(textField) + } + + @available(iOS 10.0, *) + func textFieldDidEndEditing(_ textField: UITextField, reason: UITextFieldDidEndEditingReason) { + self.textField.textFieldDidEndEditing?(textField, reason: reason) + keymanDelegate?.textFieldDidEndEditing?(textField, reason: reason) + } + + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { + _ = self.textField.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) + return keymanDelegate?.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) ?? true + } + + func textFieldShouldClear(_ textField: UITextField) -> Bool { + _ = self.textField.textFieldShouldClear?(textField) + return keymanDelegate?.textFieldShouldClear?(textField) ?? true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + _ = self.textField.textFieldShouldReturn?(textField) + return keymanDelegate?.textFieldShouldReturn?(textField) ?? true + } +} diff --git a/ios/engine/KMEI/KeymanEngine/Keyman.h b/ios/engine/KMEI/KeymanEngine/Keyman.h index 7d3e0726a8..f102cff671 100644 --- a/ios/engine/KMEI/KeymanEngine/Keyman.h +++ b/ios/engine/KMEI/KeymanEngine/Keyman.h @@ -11,5 +11,3 @@ #import "KMTextView.h" #import "KMTextViewDelegateProxy.h" - -#import "KMTextFieldDelegateProxy.h" diff --git a/ios/engine/KMEI/KeymanEngineDemo/MainViewController.swift b/ios/engine/KMEI/KeymanEngineDemo/MainViewController.swift index fae5c040aa..43be80486a 100644 --- a/ios/engine/KMEI/KeymanEngineDemo/MainViewController.swift +++ b/ios/engine/KMEI/KeymanEngineDemo/MainViewController.swift @@ -10,7 +10,7 @@ import KeymanEngine import UIKit import QuartzCore -class MainViewController: UIViewController, UIAlertViewDelegate, KMTextViewDelegate, KMTextFieldDelegate { +class MainViewController: UIViewController, UIAlertViewDelegate, KMTextViewDelegate, KeymanTextFieldDelegate { var textView1: KMTextView! var textView2: KeymanTextField! var textView3: UITextView!