मैंने अभी XIB में बटनों का एक गुच्छा रखकर एक इन-ऐप कस्टम कीबोर्ड बनाया है (ताकि मैं इसे विभिन्न नियंत्रकों में पुन: उपयोग कर सकूं) लेकिन मैं स्टम्प्ड हूं (शायद मामूली क्या है):

XIB के बटनों को कैसे कनेक्ट करें ताकि जब मैं एक दबाऊं तो एक दृश्य नियंत्रक पर UITextView में कर्सर स्थान पर उपयुक्त टेक्स्ट दर्ज किया जाए। (उदाहरण के लिए, यदि 5 दबाया जाता है, तो UITextView में वर्तमान कर्सर स्थान पर 5 दर्ज किया जाना चाहिए।)

सब कुछ पूरी तरह से काम करता है - कुंजी से दृश्य तक डेटा प्राप्त करने के अलावा।

मैं ऐसा कोई एक्सटेंशन नहीं बनाना चाहता जिसके लिए उपयोगकर्ता को सेटिंग में इसे सक्षम करने की आवश्यकता होगी। मैं उस कीबोर्ड को भी रखना चाहता हूं जहां मैं चाहता हूं, विशेष रूप से इसे आधे स्क्रीन तक सीमित करने के लिए जब फोन लैंडस्केप में घुमाया जाता है।

यही सब कुछ मेरे पास है:

class ViewController: UIViewController, UITextViewDelegate {

    @IBOutlet weak var inputField: UITextView!
    @IBOutlet weak var customKeyboard: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        dataInputField.delegate = self        
    }
}

class CustomKeyboard: UIView {

    @IBOutlet var contentView: UIView!
    
    @IBOutlet weak var key1: UIButton!
    @IBOutlet weak var key2: UIButton!
    // etc.
    @IBOutlet weak var keyReturn: UIButton!
    @IBOutlet weak var keyDelete: UIButton!
    
    
    override init(frame: CGRect) {
        // for using the custom view in code
        super.init(frame: frame)
        commonInit()
    }
    
    required init?(coder aDecoder: NSCoder) {
        // for using the custom view in IB
        super.init(coder: aDecoder)
        commonInit()
    }
    
    
    private func commonInit() {
        Bundle.main.loadNibNamed("CustomKeyboard", owner: self, options: nil)
        contentView.frame = self.bounds
        contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        contentView.translatesAutoresizingMaskIntoConstraints = true
        addSubview(contentView)
    }
    
    
    @IBAction func key1(_ sender: UIButton) {
    }
    
    @IBAction func key2(_ sender: UIButton) {
    }

    // etc.

    @IBAction func keyReturn(_ sender: UIButton) {
    }
    
    @IBAction func keyDelete(_ sender: UIButton) {
    }
}

कस्टमकीबोर्ड कक्षा के अंदर मैंने कोशिश की:

@IBAction func key1(_ sender: UIButton) {
    if let selectedRange: UITextRange = inputField.selectedTextRange {
        inputField.replace(selectedRange, withText: "1")
    }
}

@IBAction func keyDelete(_ sender: UIButton) {
    inputField.deleteBackward()
}

लेकिन जाहिर है, इनपुटफिल्ड व्यू कंट्रोलर से संबंधित है, न कि कस्टमकेबोर्ड क्लास, इसलिए मुझे एक त्रुटि मिलती है।

तो, मैं एक व्यू कंट्रोलर में टेक्स्ट व्यू में दर्ज कस्टमकेबोर्ड एक्सआईबी/कक्षा पर क्लिक किए गए पात्रों को कैसे प्राप्त करूं?

वैकल्पिक रूप से, मैं इस पद्धति का उपयोग करना पसंद करूंगा यदि मैं फोन को घुमाने पर कीबोर्ड की चौड़ाई को आधी स्क्रीन तक सीमित कर सकता हूं:

https://stackoverflow.com/a/57275689/8635708

(लेकिन मैं अभी भी जानना चाहता हूं कि वीसी में यूआईटीएक्स्टफिल्ड में एक्सआईबी बटन कैसे कनेक्ट करें!)

-1
Greg 8 अक्टूबर 2020, 20:21

1 उत्तर

सबसे बढ़िया उत्तर

आप इसे प्रोटोकॉल/प्रतिनिधि पैटर्न के साथ कर सकते हैं।

एक प्रोटोकॉल को परिभाषित करें - जैसे कि:

protocol CustomKeyboardDelegate: class {
    func keyTapped(_ sender: UIButton)
}

अपने कस्टम कीबोर्ड वर्ग में एक प्रतिनिधि var / संपत्ति को परिभाषित करें:

class CustomKeyboard: UIView {

    weak var delegate: CustomKeyboardDelegate?

    // etc...
}

अपने व्यू कंट्रोलर को उस प्रोटोकॉल के अनुरूप बनाएं:

class CustomKeyboardTestViewController: UIViewController,
                                        UITextViewDelegate,
                                        CustomKeyboardDelegate {

    func keyTapped(_ sender: UIButton) -> Void {
        // do something based on the key tapped in the custom keyboard view
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // prevent iOS keyboard from showing
        textView.inputView = UIView()
        textView.inputAccessoryView = UIView()
    
        textView.delegate = self
    
        // assign self as custom keyboard delegate
        customKeyboard.delegate = self
    }
}

यहां एक पूर्ण कार्यान्वयन है:

protocol CustomKeyboardDelegate: class {
    func keyTapped(_ sender: UIButton)
}
class CustomKeyboardTestViewController: UIViewController,
                                        UITextViewDelegate,
                                        CustomKeyboardDelegate {
    
    @IBOutlet var textView: UITextView!
    @IBOutlet var customKeyboard: CustomKeyboard!

    override func viewDidLoad() {
        super.viewDidLoad()

        // prevent iOS keyboard from showing
        textView.inputView = UIView()
        textView.inputAccessoryView = UIView()
        
        textView.delegate = self
        
        // assign self as custom keyboard delegate
        customKeyboard.delegate = self
        
        // hide custom keyboard view
        customKeyboard.isHidden = true

        // add a tap gesture to end editing
        // for testing, add a tap recognizer to the view
        let t = UITapGestureRecognizer(target: self, action: #selector(self.stopEditing))
        view.addGestureRecognizer(t)

    }
    
    @objc func stopEditing() {
        view.endEditing(true)
    }
    
    func textViewDidBeginEditing(_ textView: UITextView) {
        // show the custom keyboard
        customKeyboard.isHidden = false
    }
    func textViewDidEndEditing(_ textView: UITextView) {
        // hide the custom keyboard
        customKeyboard.isHidden = true
    }
    
    func keyTapped(_ sender: UIButton) -> Void {
        guard let t = sender.currentTitle else { return }
        switch t {
        
        case "Del":
            textView.deleteBackward()
            
        //case "Return":
            // do something if Return tapped?
        
        default:
            if let selectedRange: UITextRange = textView.selectedTextRange {
                textView.replace(selectedRange, withText: t)
            }

        }
    }

}

class CustomKeyboard: UIView {
    
    weak var delegate: CustomKeyboardDelegate?
    
    @IBOutlet var contentView: UIView!

    override init(frame: CGRect) {
        // for using the custom view in code
        super.init(frame: frame)
        commonInit()
    }
    
    required init?(coder aDecoder: NSCoder) {
        // for using the custom view in IB
        super.init(coder: aDecoder)
        commonInit()
    }
    
    private func commonInit() {
        Bundle.main.loadNibNamed("CustomKeyboard", owner: self, options: nil)
        contentView.frame = self.bounds
        contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        contentView.translatesAutoresizingMaskIntoConstraints = true
        addSubview(contentView)
    }
    
    @IBAction func keyTapped(_ sender: UIButton) {
        delegate?.keyTapped(sender)
    }

}

इस CustomKeyboard.xib फ़ाइल का उपयोग करना:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina3_5" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CustomKeyboard" customModule="Temp" customModuleProvider="target">
            <connections>
                <outlet property="contentView" destination="iN0-l3-epB" id="OzP-Z2-a2s"/>
            </connections>
        </placeholder>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <view contentMode="scaleToFill" id="iN0-l3-epB">
            <rect key="frame" x="0.0" y="0.0" width="160" height="160"/>
            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
            <subviews>
                <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="1Xr-Mt-hHY">
                    <rect key="frame" x="4" y="4" width="152" height="152"/>
                    <subviews>
                        <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="mUr-M7-k2c">
                            <rect key="frame" x="0.0" y="0.0" width="152" height="74"/>
                            <subviews>
                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="lBn-nn-G8k">
                                    <rect key="frame" x="0.0" y="0.0" width="74" height="74"/>
                                    <color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <constraints>
                                        <constraint firstAttribute="width" secondItem="lBn-nn-G8k" secondAttribute="height" multiplier="1:1" id="mXR-oo-7pJ"/>
                                    </constraints>
                                    <fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
                                    <inset key="contentEdgeInsets" minX="4" minY="0.0" maxX="4" maxY="0.0"/>
                                    <state key="normal" title="1"/>
                                    <state key="highlighted">
                                        <color key="titleColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                    </state>
                                    <connections>
                                        <action selector="keyTapped:" destination="-1" eventType="touchUpInside" id="6eb-Ie-brj"/>
                                    </connections>
                                </button>
                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Qh6-FT-V5i">
                                    <rect key="frame" x="78" y="0.0" width="74" height="74"/>
                                    <color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
                                    <inset key="contentEdgeInsets" minX="4" minY="0.0" maxX="4" maxY="0.0"/>
                                    <state key="normal" title="2"/>
                                    <state key="highlighted">
                                        <color key="titleColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                    </state>
                                    <connections>
                                        <action selector="keyTapped:" destination="-1" eventType="touchUpInside" id="1Bw-Cs-Wj6"/>
                                    </connections>
                                </button>
                            </subviews>
                        </stackView>
                        <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="mwd-u9-TCg">
                            <rect key="frame" x="0.0" y="78" width="152" height="74"/>
                            <subviews>
                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Yi0-cq-GXr">
                                    <rect key="frame" x="0.0" y="0.0" width="74" height="74"/>
                                    <color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
                                    <inset key="contentEdgeInsets" minX="4" minY="0.0" maxX="4" maxY="0.0"/>
                                    <state key="normal" title="Del"/>
                                    <state key="highlighted">
                                        <color key="titleColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                    </state>
                                    <connections>
                                        <action selector="keyTapped:" destination="-1" eventType="touchUpInside" id="WKj-X2-bIH"/>
                                    </connections>
                                </button>
                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pc3-dn-xJd">
                                    <rect key="frame" x="78" y="0.0" width="74" height="74"/>
                                    <color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
                                    <inset key="contentEdgeInsets" minX="4" minY="0.0" maxX="4" maxY="0.0"/>
                                    <state key="normal" title="Return"/>
                                    <state key="highlighted">
                                        <color key="titleColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                    </state>
                                    <connections>
                                        <action selector="keyTapped:" destination="-1" eventType="touchUpInside" id="6W4-cI-pLC"/>
                                    </connections>
                                </button>
                            </subviews>
                        </stackView>
                    </subviews>
                </stackView>
            </subviews>
            <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
            <color key="backgroundColor" red="0.0" green="0.58980089430000004" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
            <constraints>
                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="1Xr-Mt-hHY" secondAttribute="trailing" constant="4" id="PFP-8c-wD6"/>
                <constraint firstItem="1Xr-Mt-hHY" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" constant="4" id="TAk-fq-r6N"/>
                <constraint firstItem="1Xr-Mt-hHY" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="4" id="hxq-es-MLF"/>
                <constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="1Xr-Mt-hHY" secondAttribute="bottom" constant="4" id="lzS-zG-Uv0"/>
            </constraints>
            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
            <point key="canvasLocation" x="253" y="6"/>
        </view>
    </objects>
</document>

और यह स्टोरीबोर्ड:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Mv0-Rq-40F">
    <device id="retina3_5" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Custom Keyboard Test View Controller-->
        <scene sceneID="brw-Oy-kLF">
            <objects>
                <viewController id="Mv0-Rq-40F" customClass="CustomKeyboardTestViewController" customModule="Temp" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="OIY-KH-aNL">
                        <rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GtP-Jl-pI2" customClass="CustomKeyboard" customModule="Temp" customModuleProvider="target">
                                <rect key="frame" x="152" y="312" width="160" height="160"/>
                                <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                                <constraints>
                                    <constraint firstAttribute="width" constant="160" id="VCs-W2-wrc"/>
                                    <constraint firstAttribute="width" secondItem="GtP-Jl-pI2" secondAttribute="height" multiplier="1:1" id="ovH-4S-GhV"/>
                                </constraints>
                            </view>
                            <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" text="The Text View" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="ZdO-d6-Sm2">
                                <rect key="frame" x="40" y="40" width="240" height="128"/>
                                <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="128" id="eJU-OY-Qy2"/>
                                </constraints>
                                <color key="textColor" systemColor="labelColor"/>
                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
                            </textView>
                        </subviews>
                        <viewLayoutGuide key="safeArea" id="l0u-Nt-wuE"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                        <constraints>
                            <constraint firstItem="ZdO-d6-Sm2" firstAttribute="leading" secondItem="l0u-Nt-wuE" secondAttribute="leading" constant="40" id="0mc-NI-Djr"/>
                            <constraint firstItem="l0u-Nt-wuE" firstAttribute="bottom" secondItem="GtP-Jl-pI2" secondAttribute="bottom" constant="8" id="aSc-dc-5c5"/>
                            <constraint firstItem="l0u-Nt-wuE" firstAttribute="trailing" secondItem="ZdO-d6-Sm2" secondAttribute="trailing" constant="40" id="cMA-YS-gar"/>
                            <constraint firstItem="ZdO-d6-Sm2" firstAttribute="top" secondItem="l0u-Nt-wuE" secondAttribute="top" constant="40" id="kiZ-2E-DkL"/>
                            <constraint firstItem="l0u-Nt-wuE" firstAttribute="trailing" secondItem="GtP-Jl-pI2" secondAttribute="trailing" constant="8" id="xVp-5Y-YW4"/>
                        </constraints>
                    </view>
                    <connections>
                        <outlet property="customKeyboard" destination="GtP-Jl-pI2" id="gbe-nn-hN6"/>
                        <outlet property="textView" destination="ZdO-d6-Sm2" id="EyK-5a-ndF"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="zof-dI-A2X" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="212" y="85"/>
        </scene>
    </scenes>
    <resources>
        <systemColor name="labelColor">
            <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>

परिणाम (पाठ दृश्य "द टेक्स्ट व्यू" के साथ पहले से ही शुरू हो चुका है):

enter image description here

1
DonMag 9 अक्टूबर 2020, 00:41