iOS 8 : انشاء لوحة مفاتيح custom باستخدام Swift |
نبدأ مع iOS 8, يمكن لتطبيقاتك أن توسيع خاصية custom و المحتويات الى غير تطبيقك و تجعله متاحا للمستخدمين بينما يقومون باستخدام تطبيقات أخرى أو النظام العامل. احدى الطرق المستخدمة لتوسيع النظام العامل هي بانشاء لوحة مفاتيح custom.
سنعرض لك في هذا الدرس كيفية انشاء لوحة المفاتيح custom باستخدام Swift و اضافة التطبيق الجديد APIs. قبل أن نقوم بذلك, سنبحث ما الذي يمكن للوحة المفاتيح الاضافية ان تفعل, و ما الذي لا يمكنها أن تفعله, و ما الذي يجب أن تحصل عليه لتأخذ موافقة App Store.
1. نظرة عامة
تستبدل لوحة المفاتيح custom لوحة مفاتيح النظام للمستخدمين الذين يرغبون بقدرات مثل طريقة ادخال نص جديد أو القدرة على ادخال نص في لغة ليس بطريقة أخرى مدعوم من قبل النظام العامل.
الوظيفة الأساسية للوحة المفاتيح custom بسيطة, الاستجابة الى النقرات أو الاشارات أو احداث مدخلة جديدة و تزويد نص على شكل كائن NSString بلا لواحق عند نقطة ادخال النص لكائن النص المدخل الحالي.
بعد أن يختار المستخدم لوحة مفاتيح, تبقى كاللوحة الافتراضية في أي وقت يفتح فيه المستخدم تطبيقا. و لهذا السبب يجب على لوحة المفاتيح أن تسمح للمستخدم بالانتقال الى لوحة مفاتيح أخرى.
هنالك عنصران أساسيان للتطوير لكل لوحة مفاتيح custom: الثقة. تمنحك لوحة المفاتيح custom الوصول الى ما يطبعه المستخدم, لذا فالثقة بينك و بين المستخدم هامة جدا. مفتاح "لوحة المفاتيح التالية". التقديم الذي يسمح للمستخدم بالانتقال الى لوحة مفاتيح أخرى هو جزء من واجهة لوحة مفاتيح المستخدم, يجب أن تزود لوحة مفاتيحك بواحد. –دليل برمجة اضافة تطبيق.
في حال أردت فقط اضافة بضعة أزرار للوحة مفاتيح النظام, حينها عليك ان تتفحص وجهات نظر custom عن مدخلات البيانات.
2. المتطلبات و التقييدات
ما الذي لا يمكن للوحة مفاتيح custom أن تفعله
هنالك كائنات ادخال نصية تعد لوحة مفاتيح custom غير مؤهلة لطباعتها. يتضمن ذلك حقول النص المؤمنة لادخال كلمات السر و كائنات الهاتف, مثل حقول رقم الهاتف و تطبيق جهات الاتصال.
ليس لدى لوحة مفاتيح custom وصولا الى المدخلات التي تعرض بشكل هرمي, لا يمكنها التحكم بالمؤشر, و انها غير قادرة على اختيار نص. بالاضافة الى ذلك, لا يمكنها عرض أي شيء فوق الصف الأعلى. لا تعد لوحة مفاتيح النظام محدودة بهذه القيود. على سبيل المثال, فهي تعرض اضافة عندما تنقر مفتاحا لتري المستخدم ما هو المفتاح الذي نقر.
يظهر الخط الأحمر أعلى قيد للوحة مفاتيح custom.
Sandboxing
من خلال الافتراضي, ليس لدى لوحة المفاتيح وصولا للشبكة و لا يمكنها مشاركة ملفات مع تطبيقها المحتوي. من أجل تفعيل هذه القدرات, ضع قيمة مفتاح RequestsOpenAccess في ملف Info.plist الى نعم. من خلال القيام بذلك يتم مد sandbox للوحة المفاتيح كما هو موصوف في دليل برمجة اضافة التطبيق Apple.
اذا طلبت وصولا مفتوحا, تحصل لوحة مفاتيحك على القدرات التالية, كل واحدة مع مسؤولية مرتبطة بها:
· الولوج الى خدمات المواقع و قاعة بيانات العناوين, كل واحدة تتطلب اذن المستخدم عند أول دخول
· خيار استخدام حاوي مشترك مع تطبيق لوحة المفاتيح المحتوي, الذي سيفعل ميزات, مثل التزويد بواجهة مستخدم لادارة مفردات custom في التطبيق المحتوي
· القدرة على ارسال keystrokes و احداث ادخالات أخرى من أجل معالجة server-side.
· الوصول الى iCloud, الذي يمكنك استخدمه مثلا لضمان أن اعدادات لوحة المفاتيح و مفردات custom حديثة على كل الاجهزة التي يملكها المستخدم
· الولوج الى مركز الالعاب و شراء in-app من خلال التطبيق المحتوى.
· القدرة على العمل بتطبيقات مدارة في حال صممت لوحة مفاتيحك لتدعم ادارة جهاز الموبايل (MDM)
احرص على قراءة وثيقة Apple تصميم لثقة المستخدم, التي تصف مسؤولياتك احترام و حماية بيانات المستخدم في حال طلبت ولوجا مفتوحا.
3. كيف تعمل
لدينا في الشكل الأساسي تطبيقا يحوي على اضافة لوحة مفاتيح و UIInputViewController تتحكم بلوحة المفاتيح و تستجيب لأحداث المستخدم.
يحوي قالب لوحة مفاتيح Custom على أصناف فرعية لـ UIInputViewController, و التي تعد متحكم المشهد الاولي للوحة مفاتيحك. دعنا نلقي نظرة على الواجهة لنعرف كيف تعمل.
class UIInputViewController : UIViewController, UITextInputDelegate, NSObjectProtocol {
var inputView: UIInputView!
var textDocumentProxy: NSObject! { get }
func dismissKeyboard()
func advanceToNextInputMode()
// This will not provide a complete repository of a language's vocabulary.
// It is solely intended to supplement existing lexicons.
func requestSupplementaryLexiconWithCompletion(completionHandler: ((UILexicon!) -> Void)!)
}
inputView هو المشهد المستخدم للوحة المفاتيح, و هي نفس خاصية المشهد
طريقة dismissKeyboard يمكن أن تستدعى فصل لوحة المفاتيح
advanceToNextInputMode تستخدم للتغيير بين لوحات المفاتيح
textDocumentProxy هو الكائن الذي ستستخدمه للتفاعل مع المدخلات النصية الحالية
self.textDocumentProxy.insertText("Tuts+") // inserts the string "Tuts+" at the insertion point
self.textDocumentProxy.deleteBackward() // Deletes the character to the left of the insertion point
تتطابق UIInputViewController مع بروتوكول UITextInputDelegate, مخبرا اياك عندما يتغير النص أو اختيار النص خلال selectionWillChange, selectionDidChange , textWillChange و textDidChangeevents
4. انشاء لوحة مفاتيح حاسبة
دعونا ننشئ لوحة مفاتيح custom لنجعل ذلك محسوسا أكثر الى حد ما. سننشئ لوحة مفاتيح بسيطة يمكنها التعامل مع المدخلات الرقمية و العمليات البسيطة. سنقوم باستخدام ملف XIB من أجل واجهة تطبيق المستخدم.
خطوة 1: انشاء مشروع جديد
قم بفتح Xcode 6, قم بانشاء تطبيق ذات مشهد فردي و اختر Swift كلغة البرمجة. قم بتسميته CalculatorKeyboard.
خطوة 2: أضف حقل نصي
قم بفتح Main.storyboard و اسحب حقل نصي من مكتبة الكائنات. سنستخدم هذا لفحص لوحة المفاتيح لاحقا. ضع حقل النص في المنتصف و أضف حدود الشكل الضرورية كما هو موضح بالاسفل.
اذا استدعيت textField.becomeFirstResponder() في viewDidLoad فان لوحة المفاتيح ستنفتح عندما تبدأ التطبيق.
خطوة 3: أضف اضافة لوحة المفاتيح
اختر ملف المشروع من Project Navigator (ملاح المشروع) و أضف الهدف الجديد من خلال النقر على زر الاضافة في الاسفل.
اختر اضافة التطبيق على اليسار و اختر عارض لوحة مفاتيح custom و سمه حاسبة (Calculator).
هذا سينشئ مجموعة اسمها حاسبة (Calculator), تحوي على ملفين KeyboardViewController.swift و Info.plist.
خطوة 4: التنظيف
افتح KeyboardViewController.swift. لدى عارض لوحة المفاتيح زر واحد مهمته اتاحة المجال للمستخدم التنقل بين لوحات المفاتيح. استبعد الكود من طريقة viewDidLoad.
خطوة 5: انشاء واجهة التطبيق
انقر مباشرة على مجموعة الحاسبة و اختر ملفا جديدا.... اختر قسم واجهة التطبيق على اليسار, و اختر عارض المشهد و الذي يدعى بـ .Calculator.xib
افتح ملف XIB, في متحري اللواحق على اليسار, ضع الحجم شكل حر و حالة اللوح لا شيء.
قم بوضع عرض المشهد 320 و الارتفاع 160 في متحري الحجم.
اسحب زرا من مكتبة الكائنات للمشهد. في متحري اللواحق, ضع العنوان 1. في متحري الحجم, ضع ارتفاع و عرض الزر 30. حرك الزر الى اعلى الزاوية اليمنى للمشهد حتى تصبح على نفس الخط مع الهوامش.
انسخ الزر من خلال نقر و سحب الزر بينما تضغط على مفتاح الاختيارات. ضع الزر الثاني اسفل الاول.
اختر الازرار من خلال الضغط على Command-A و نسخ المفاتيح. ضع الازرار الجديدة أسفل الزر الاول و الثاني.
قم بتكرير العملية لانشاء عامود اخر من الازرار حتى يصبح لديك أربعة عواميد من الازرار.
ثم اختر العامود الذي على اليسار و قم بانشاء نسخة تكون على نفس مسار الجهة الحدودية اليسرى للمشهد.
ضع عرض الازرار 140 نقطة. استبدل الزر الذي في اعلى اليسار بتصنيف لديه نفس حجم الزر. أعد تسمية الازرار كما هو موضح بالصورة التي في الاسفل.
أضفي على الخلفية لون مائل للزرقة و عين لون خلفية الازرار أبيض مع نسبة لا نفاذية تقدر بـ15%. و من أجل عرض التصنيف, اجعلها سوداء مع نسبة لا نفاذية تقدر بـ15%. ضع حجم النص 18 نقطة لكل كائن واجهة التطبيق و ضع لون النص أبيض. يجب على واجهة التطبيق ان تبدو كهذا:
خطوة 6: تحميل واجهة التطبيق
سنحتاج أولا لانشاء خاصية من أجل تخزين واجهة التطبيق.
class KeyboardViewController: UIInputViewController {
var calculatorView: UIView!
...
}
قم بانشاء طريقة تدعى loadInterface و سمها طريقة viewDidLoad لـ KeyboardViewController.
class KeyboardViewController: UIInputViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
loadInterface()
}
func loadInterface() {
// load the nib file
var calculatorNib = UINib(nibName: "Calculator", bundle: nil)
// instantiate the view
calculatorView = calculatorNib.instantiateWithOwner(self, options: nil)[0] as UIView
// add the interface to the main view
view.addSubview(calculatorView)
// copy the background color
view.backgroundColor = calculatorView.backgroundColor
}
...
}
خطوة 7: اختبار لوحة المفاتيح
عند هذه المرحلة سيكون بمقدورك أن تفحص لوحة مفاتيحك الجديدة. مع اختيار تخطيط الـ CalculatorKeyboard, قم ببناء و ادارة التطبيق على جهازك. هذا سيضيف لوحة مفاتيح جديدة لجهازك. و لكن قبل ان يمكنك استخدامها, ستحتاج اولا الى تنصيبها.
اذهب الى اعدادات < عام < لوحة مفاتيح < لوحات مفاتيح و اختر أضف لوحة مفاتيح جديدة. ستجد هناك لوحة مفاتيح الحاسبة في قائمة لوحات مفاتيح ذات الاطراف الثلاثية. اختر و نصب لوحة المفاتيح. عندما تفتح لوحة المفاتيح في المرة القادمة سيكون بمقدورك أن ترى لوحة مفاتيحك الجديدة من خلال الضغط على رز لوحة المفاتيح التالي.
في حال كنت تستخدم محفز iOS, فان لوحة مفاتيح custom يمكن ألا تعمل داخل تطبيقك. لكي ترى لوحة المفاتيح اضغط على الصفحة الرئيسية و افتح Spotlight.
الخطوة 8: لوحة المفاتيح التالية
قم بانشاء خاصية لزر لوحة المفاتيح التالية في صنف KeyboardViewController.
class KeyboardViewController: UIInputViewController {
@IBOutlet var nextKeyboardButton: UIButton!
...
}
افتح Calculator.xib , اختر مالك الملف ((File's Owner, و قم بتغيير صنفها لـ KeyboardViewController في متحري الهوية.
انقر مباشرة على زر لوحة المفاتيح التالية و اربط منفذ للارجاع لمالك الملف.
في طريقة loadInterface, سنضيف نشاط لزر nextKeyboard كما هو موضح بالاسفل.
class KeyboardViewController: UIInputViewController {
...
func loadInterface() {
...
// This will make the button call advanceToNextInputMode() when tapped
nextKeyboardButton.addTarget(self, action: "advanceToNextInputMode", forControlEvents: .TouchUpInside)
}
}
الخطوة 9: عرض الرقم
قم بانشاء خاصية للعرض و اربط منفذ الارجاع في واجهة التطبيق.
class KeyboardViewController: UIInputViewController {
@IBOutlet var display: UILabel!
...
}
قم بانشاء طريقة تدعى clearDisplay و استدعها في طريقة viewDidLoad بعد استدعاء loadInterface. يجب على العرض أن يظهر 0 عندما تفتح لوحة المفاتيح.
class KeyboardViewController: UIInputViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
loadInterface()
clearDisplay()
}
...
@IBAction func clearDisplay() {
display.text = "0"
}
}
اربط زر C حدث touch up inside مع طريقة clearDisplay في باني الواجهة.
الخطوة 10: مدخلال الارقام
حان الوقت للتعامل مع مدخلات الارقام. عندما تفتح لوحة المفاتيح ستظهر 0 على العارض. اذا نقرت على مفتاح رقم ما, يجب أن تستبدل العارض بذلك الرقم. قم بانشاء خاصية تدعى shouldClearDisplayBeforeInserting لانشاء هذا الازرار الارقام لوك.
قم بانشاء طريقة تدعى didTapNumber و اربطها في باني الواجهة بكل أزرار الارقام لحدث touch up inside. تستخدم الطريقة titleLabel للزر لتحدد أي رقم تم نقره.
class KeyboardViewController: UIInputViewController {
var shouldClearDisplayBeforeInserting = true
...
@IBAction func didTapNumber(number: UIButton) {
if shouldClearDisplayBeforeInserting {
display.text = ""
shouldClearDisplayBeforeInserting = false
}
if var numberAsString = number.titleLabel?.text {
var numberAsNSString = numberAsString as NSString
if var oldDisplay = display?.text! {
display.text = "\(oldDisplay)\(numberAsNSString.intValue)"
} else {
display.text = "\(numberAsNSString.intValue)"
}
}
}
}
قم بتحديث طريقة clearDisplay كما هو موضح بالاسفل.
class KeyboardViewController: UIInputViewController {
...
@IBAction func clearDisplay() {
display.text = "0"
shouldClearDisplayBeforeInserting = true
}
}
تعد كود لوحة المفاتيح هدفا مختلفا عن تطبيقك. و لذلك فان السجلات الصحيحة لا تعد مرئية. لرؤية جذور هدف الحاسبة, افتح جذر النظام من محفز Ios.
الخطوة 11: مدخلات النقطة
يجب على الزر الذي عليه ادخال النقطة ان يضيف نقطة الى العارض, و لكن هذا فقط اذا لم يكن هنالك نقطة موجودة بعد.
class KeyboardViewController: UIInputViewController {
...
@IBAction func didTapDot() {
if let input = display?.text {
var hasDot = false
for ch in input.unicodeScalars {
if ch == "." {
hasDot = true
break
}
}
if hasDot == false {
display.text = "\(input)."
}
}
}
}
الخطوة 12: ادخال نص
يجب على النص الذي عليه ادخال نص أن يضيف نص عرض الحاسبة الى نقطة الادخال. لفعل ذلك سنستخدم خاصية textDocumentProxy كما هو موضح بالاسفل.
class KeyboardViewController: UIInputViewController {
...
@IBAction func didTapInsert() {
var proxy = textDocumentProxy as UITextDocumentProxy
if let input = display?.text as String? {
proxy.insertText(input)
}
}
}
الخطوة 13: التعامل مع العمليات
لاننا نقوم بانشاء لوحة مفاتيح بسيطة لا تدعم أشجار التعبير, 1 + 2 * 3ستساوي 9, فاننا سوف نستخدم نموذج أبسط حيث يكون لدى الحاسبة فتحة ذاكرة داخلية نقوم بتطبيق العمليات عليها.
دعونا نأخذ مدخلا بسيطا كم أجل فهم كيفيو عمل نظام الحاسبة:
ينقر المستخدم 1, يري العارض تغييرا من 0 الى 1
ينقر المستخدم +, يجب على الحاسبة أن تتذكر أن تضيف الرقم المدخل التالي الى 1
ينقر المستخدم 2, يجب على العارض أن يتغير من 1 الى 2
ينقر المستخدم *, يجب أن تتغير كلا من العارض و الذاكرة الداخلية الى 3, يجب على الحاسبة ان تتذكر أن تضاعف الذاكرة الداخلية مع الرقم المدخل التالي
ينقر المستخدم 3, يجب أن يبقى العارض 3
ينقر المستخدم =, يجب على الحاسبة أن تطبق العملية الاخيرة و يجب على العارض أن يتغير الى 9
ملا حظات:
يجب على الحاسبة أن تتذكر العملية التالية التي يجب تطبيقها
بعد ادخال رقم اذا تم تنفيذ عملية أو يساوي, فانه يجب على الحاسبة أن تطبق اخر عملية تذكرها
اذا نفذ المستخدم عمليتان أو اكثر من دون ادخال رقم, يجب على الحاسبة أن تتذكر اخر واحدة
بعد أن يتم تطبيق عملية, يجب على العارض أن يحدث النتيجة
يعد أن يتم عرض النتيجة, يجب على العارض أن يوضح قبل كتابة رقم اخر
من أجل انشاء الحاسبة, سنحتاج ما يلي:
خاصية internalMemory التي تخزن النتيجة الؤقتة
خاصية تخزن nextOperation
واحدة أخرى لتذكر فيما اذا يجب أن تطبق nextOperation بعد ان يتم تنفيذ العملية
enum Operation {
case Addition
case Multiplication
case Subtraction
case Division
case None
}
class KeyboardViewController: UIInputViewController {
var internalMemory = 0.0
var nextOperation = Operation.None
var shouldCompute = false
...
}
قم بانشاء طريقة تدعى didTapOperation و اربطها بأزرار عملية حدث touch up inside في باني الواجهة. ستستخدم الطريقة عنوان الزر لتحديد اي عملية يجب تنفيذها.
class KeyboardViewController: UIInputViewController {
...
@IBAction func didTapOperation(operation: UIButton) {
if shouldCompute {
computeLastOperation()
}
if var op = operation.titleLabel?.text {
switch op {
case "+":
nextOperation = Operation.Addition
case "-":
nextOperation = Operation.Subtraction
case "X":
nextOperation = Operation.Multiplication
case "%":
nextOperation = Operation.Division
default:
nextOperation = Operation.None
}
}
}
}
قم بانشاء طريقة computeLastOperation .
class KeyboardViewController: UIInputViewController {
...
@IBAction func computeLastOperation() {
// remember not to compute if another operation is pressed without inputing another number first
shouldCompute = false
if var input = display?.text {
var inputAsDouble = (input as NSString).doubleValue
var result = 0.0
// apply the operation
switch nextOperation {
case .Addition:
result = internalMemory + inputAsDouble
case .Subtraction:
result = internalMemory - inputAsDouble
case .Multiplication:
result = internalMemory * inputAsDouble
case .Division:
result = internalMemory / inputAsDouble
default:
result = 0.0
}
nextOperation = Operation.None
var output = "\(result)"
// if the result is an integer don't show the decimal point
if output.hasSuffix(".0") {
output = "\(Int(result))"
}
// truncatingg to last five digits
var components = output.componentsSeparatedByString(".")
if components.count >= 2 {
var beforePoint = components[0]
var afterPoint = components[1]
if afterPoint.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) > 5 {
let index: String.Index = advance(afterPoint.startIndex, 5)
afterPoint = afterPoint.substringToIndex(index)
}
output = beforePoint + "." + afterPoint
}
// update the display
display.text = output
// save the result
internalMemory = result
// remember to clear the display before inserting a new number
shouldClearDisplayBeforeInserting = true
}
}
}
قم بتحديث clearDisplayMethod كما هو موضح بالاسفل. عندما يبدأ المستخدم بكتابة أن تعين 0 و يجب أن تكون nextOperationd اضافة. بتلك الطريقة, و بعد أن يدخل المستخدم الرقم الاول و ينفذ على عملية ما, ستتذكر الحاسبة الرقم المدخل.
class KeyboardViewController: UIInputViewController {
...
@IBAction func clearDisplay() {
display.text = "0"
internalMemory = 0
nextOperation = Operation.Addition
shouldClearDisplayBeforeInserting = true
}
}
الخطوة 14: اللمسات الاخيرة
دعونا نستخدم لاحقة الاعلان IBInspectable لاضافة زاوية نصف قطر الى الزرار و العرض. اولا, قم بانشاء صنف فرعي لـ UIButton و UILabel.
class RoundButton: UIButton {
@IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
}
class RoundLabel: UILabel {
@IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
}
في باني الواجهة, اختر لازرار و غير صنفهم الى صنف RoundButton في متحري الهوية. في متحري اللواحق, يجب أن ترى لاحقة نصف قطر الزاوية الجديدة.
قم بفعل نفس الشيء لصنف العرض. يجب على لوحة مفاتيحك الان أن تبدو كهذا.
الخاتمة
يجب أن تكون قادرا الان على انشاء لوحة مفاتيح custom في iOS باستخدام اضافة التطبيق APIs. تذكر أن على كل لوحة مفاتيح custom أن يكون لديها طريقة للتنقل الى لوحة المفاتيح التالية و ان لوحة المفاتيح الخاصة بك غير قادرة على الاتصال بالانترنت, الولوج الى خدمات المواقع, أو التحدث مع تطبيقها المحتوي من قبل الافتراضي و لكن يجب أن تطلب هذه الامكانيات.
سيستخدم النظام لوحة مفاتيح افتراضية من أجل تأمين الحقول, مثل كلمة الرقم و حقول أرقتم الهاتف. لا تنس ان كود لوحة مفاتيح custom تعيش في هدف منفصل. و بسبب ذلك فان السجلات الصحيحة غير مرئية. من أجل رؤيتهم, افتح سجل النظام من محفز iOS.
ليست هناك تعليقات: