问题
I'm trying to load a .xib
file to act as a custom keyboard when a textField is tapped. I'm able to show the .xib
file (view) when the textField is tapped but I'm not sure how to communicate the buttons in the .xib
file with the a textField in the ViewController.swift.
This is what I have done so far.
Created a single project.
Added a
UITextField
and created an outlet for it.@IBOutlet weak var myField: MyTextField!
Created a new
.xib
file and called itCustomView.xib
.Created a new class and called it
CustomView.swift
.Assigned class
CustomView.swift
to theCustomView.xib
file.Added some
UIButtons
in theCustomView.xib
file. These will be acting as a custom-keyboard, they will show when the textField is tapped and hide when theresignFirstResponder
method is called.In the
viewDidLoad
method of theViewController.swift
I assignedinputView
as follow.import UIKit class ViewController: UIViewController { @IBOutlet weak var myField: MyTextField! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let myView = NSBundle.mainBundle().loadNibNamed("CustomView", owner: self, options: nil).first as? CustomView myField.inputView = myView } }
Done
When I run the app and tap on the textField the .xib file shows (see picture below), my problem is, how do I communicate the buttons with the textField in the ViewController.swif
. In other words what I want is to show the numbers in the inputField when they are tapped.
Any suggestions? Is this how this is usually done.
Here is an image that shows the view shown when the inputField was tapped.
回答1:
Let's say you have 9 UIButton
s, then consider ctrl + dragging an IBAction
from all these buttons in storyboard to a single method such as:
- (IBAction)tapped:(id)sender
{
textView.text = [NSString stringWithFormat:@"%@%li", textView.text, (long)((UIButton*)sender).tag];
NSLog(@"%@", textView.text);
}
given that textField
is your text field, you could then append each corresponding number from your keypad (that is to say, the buttons) using the tag
property of these buttons and the aforementioned method.
You could set the tag number for each single button in storyboard (I.e., 1 - 9, respectively).
I didn't test it using 9 buttons but did with only 2, with tag numbers 1 and 2, respectively for each buttons. The result was displaying fine in UITextField
(I.e., 1
, 12
, 122
and so forth).
Update (Post-comment):
I was able to re-create this using a nib
file containing a few buttons and a UITextField
in storyboard.
The process proceeds as follows:
1. Create a nib with all the buttons (which you already have done).
2. Create a view; and under "Custom Class", re-name the class to this view (I.e., "Custom Class" -> "Class" -> "view-that-holds-the-buttons").
3. Wire the IBAction
s (a total of 9 corresponding to the number of your buttons) to one single method as described above.
4. In your other view controller whose view hold the UITextField
, load the nib using your existing method.
5. Add this view (from nib) as subview.
The following concerns with communication between the view (that holds the buttons along with the IBAction
method) and the controller in which you load the nib
:
6. create a delegate
(weak
) property.
7. Before you add the view (from nib
), assign this delegate
with the view controller (the control that loads the nib
).
8. Create a protocol:
For instance:
protocol keypadProtocol : class
{
func displayKeys(keystrokeObject: AnyObject)
}
Have the view controller that loads the nib
conform to this protocol and implement the required method (displayKeys
):
//The one that loads the nib, which also holds the UITextField
class mainViewController: UIViewController, keypadProtocol
So, once the buttons are tapped, the IBAction
would be called; but instead of displaying it, we send the sender
to our delegate
, which is the view controller that implements the displayKeys
method and holds the UITextField
.
The IBAction
would be implemented as follows:
@IBAction func tapped(sender: AnyObject)
{
delegate!.displayKeys(sender)
}
displayKeys
would be implemented like the following:
func displayKeys(keystrokeObject: AnyObject)
{
textView.text = NSString(format: "%@%li", textView.text! ?? "", (keystrokeObject as! UIButton).tag) as String
}
Declaration of the delegate
in the controller where you load the nib
file:
weak var delegate : keypadProtocol?
Assigning the delegate
from within the view controller where you load the nib
:
keyPadView.delegate = self //keyPadView is the nib file loaded
In reply to your second comment:
Assumption:
We have 2 classes.
The first one is a subclass of UIView
, which is the xib
, that holds the buttons.
Let’s call this „KeypadView“.
The second one is the main view controller, which is associated to the controller that holds
the UITextField
in your storyboard.
Let’s call this „MainViewController“.
Step 2:
Firstly, please create a new UIView
and name it, for the sake of consistency, „KeypadView“.
Then, click on your .xib file; on the right panel, click on the third tab from the left, which is called „Identity Inspector“; you would see „Custom Class -> Class“, where you would associate this xib
to the class you created (you need this class, in order to connect the IBAction
for the buttons from the xib
file to it). It would be the „KeypadView“, which is a subclass of UIView
.
Step 6:
You declare this in the class („KeypadView“) that holds the buttons.
Step 8:
You connect this method (IBAction
) to the aforementioned class (I.e., „KeypadView“).
Once you load the xib
(„KeypadView“) from within the „mainViewController“, set the delegate
in „KeypadView“ to self
(self
is the „MainViewController“):
let keyPadView = NSBundle.mainBundle().loadNibNamed("CustomView", owner: self, options: nil).first as? KeyPadView
keyPadView.delegate = self
self.view.addSubview(keypadView)
//you may need to re-adjust the position of the views; I will leave that to you
In your „KeyPadView“ class, there should be an IBAction
that gets called from each of the buttons:
I.e.,
@IBAction func tapped(sender: AnyObject)
{
delegate!.displayKeys(sender)
}
Our delegate
is the „mainViewController“, if you recall.
Since displayKeys
is implemented in „mainViewController“, the following method would be called therein:
func displayKeys(keystrokeObject: AnyObject)
{
textView.text = NSString(format: "%@%li", textView.text! ?? "", (keystrokeObject as! UIButton).tag) as String
}
„mainViewController“ would then display the keystrokes in its UITextField
(I.e., textView
).
来源:https://stackoverflow.com/questions/35518517/load-a-nib-file-to-act-as-a-custom-keyboard-when-a-uitextfield-is-tapped