วิธีตั้งค่าการดำเนินการสำหรับ UIBarButtonItem ใน Swift


89

การดำเนินการสำหรับ UIBarButtonItem แบบกำหนดเองใน Swift สามารถตั้งค่าได้อย่างไร

รหัสต่อไปนี้วางปุ่มในแถบนำทางได้สำเร็จ:

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:nil)
self.navigationItem.rightBarButtonItem = b

ตอนนี้ฉันต้องการโทรfunc sayHello() { println("Hello") }เมื่อสัมผัสปุ่ม ความพยายามของฉันจนถึงตอนนี้:

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:sayHello:)
// also with `sayHello` `sayHello()`, and `sayHello():`

และ..

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:@selector(sayHello:))
// also with `sayHello` `sayHello()`, and `sayHello():`

และ..

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:@selector(self.sayHello:))
// also with `self.sayHello` `self.sayHello()`, and `self.sayHello():`

หมายเหตุที่sayHello()ปรากฏใน Intellisense แต่ไม่ทำงาน

ขอบคุณสำหรับความช่วยเหลือของคุณ.

แก้ไข: สำหรับลูกหลานผลงานต่อไปนี้:

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:"sayHello")

4
คุณผ่านตัวเลือกได้อย่างรวดเร็วเพียงแค่ใส่ตัวเลือกในสตริงaction: "sayHello"
Jiaaro

ขอบคุณมาก. ฉันอยู่ภายใต้แรงกดดันที่จะเอาสิ่งนี้ออกไปและรู้สึกหงุดหงิด
kmiklas

1
คำถามนี้เคยถูกทำเครื่องหมายว่าซ้ำกับ@selector () ใน Swift? . อย่างไรก็ตามคำถามนี้ถามเป็นพิเศษUIBarButtonItemในขณะที่คำถามอื่นไม่ทำ การกำหนดให้ผู้เริ่มต้นอธิบายการใช้งานทั้งหมดselectorอาจเป็นเรื่องยากสำหรับพวกเขาดังนั้นฉันจึงลบสถานะที่ซ้ำกันออกเพื่อให้ทุกคนสามารถติดตามคำถามนี้ได้
Suragch

คำตอบ:


157

สำหรับ Swift 2.2 มีไวยากรณ์พิเศษสำหรับตัวเลือกที่ตรวจสอบเวลาคอมไพเลอร์ มันใช้ไวยากรณ์: #selector(methodName).

Swift 3 และใหม่กว่า:

var b = UIBarButtonItem(
    title: "Continue",
    style: .plain,
    target: self,
    action: #selector(sayHello(sender:))
)

func sayHello(sender: UIBarButtonItem) {
}

หากคุณไม่แน่ใจว่าชื่อวิธีการควรมีลักษณะอย่างไรมีคำสั่งคัดลอกเวอร์ชันพิเศษที่มีประโยชน์มาก ใส่ที่ไหนสักแห่งเคอร์เซอร์ของคุณในชื่อวิธีพื้นฐาน (เช่น sayHello) และกด Shift+ Control+ +Option Cนั่นทำให้ 'Symbol Name' บนแป้นพิมพ์ของคุณถูกวาง หากคุณถือไว้Commandด้วยจะคัดลอก 'ชื่อสัญลักษณ์ที่ผ่านการรับรอง' ซึ่งจะรวมถึงประเภทด้วย

Swift 2.3:

var b = UIBarButtonItem(
    title: "Continue",
    style: .Plain,
    target: self,
    action: #selector(sayHello(_:))
)

func sayHello(sender: UIBarButtonItem) {
}

เนื่องจากไม่จำเป็นต้องใช้ชื่อพารามิเตอร์แรกใน Swift 2.3 เมื่อทำการเรียกใช้เมธอด

คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับไวยากรณ์บน swift.org ได้ที่นี่: https://swift.org/blog/swift-2-2-new-features/#compile-time-checked-selectors


11
เพียงแค่พูดถึงว่าฟังก์ชันการทำงานไม่สามารถเป็นส่วนตัวได้ ! ฉันไม่แน่ใจจริงๆว่าทำไม แต่ฉันมักจะได้รับข้อผิดพลาดในกรณีที่ฉันระบุชื่อของฟังก์ชันส่วนตัว
maddob

ฉันได้รับสิ่งนี้: "ไม่ใช้ methodSignatureForSelector"
AlamoPS

1
@AlamoPS หากคุณใช้เวอร์ชันที่ 2 กับโคลอนคุณจะต้องตรวจสอบให้แน่ใจว่าประเภทพารามิเตอร์ของฟังก์ชันตรงกับสิ่งที่คุณจัดการ
Jason

1
@RyanForsyth สตริงได้รับการแปลเป็นSelector("sayHello")เบื้องหลังโดย Swift อยู่แล้ว
fatuhoku

2
คำตอบนี้ล้าสมัย
Dan Loewenherz

34

ตัวอย่าง Swift 4/5

button.target = self
button.action = #selector(buttonClicked(sender:))

@objc func buttonClicked(sender: UIBarButtonItem) {
        
}

5
นี่ถูกต้องสำหรับ Swift 4 คุณต้องเพิ่ม@objcการประกาศฟังก์ชัน จนถึง Swift 4 สิ่งนี้ถูกอนุมานโดยปริยาย
Jonathan Cabrera

1
button.target = self
Mahesh

@Mahesh ไม่จำเป็นต้องตั้งเป้าหมาย
norbDEV

ต้องการเป้าหมาย @norbDEV สำหรับ Swift 5
Biasi Wiga

3

ตัวอย่างโปรแกรม Swift 5 และ iOS 13+

  1. คุณต้องทำเครื่องหมายฟังก์ชันของคุณด้วย@objcดูตัวอย่างด้านล่าง!
  2. ไม่มีวงเล็บต่อท้ายชื่อฟังก์ชัน! เพียงแค่ใช้#selector(name) .
  3. private หรือ publicไม่สำคัญ; คุณสามารถใช้ส่วนตัว

ตัวอย่างรหัส

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    let menuButtonImage = UIImage(systemName: "flame")
    let menuButton = UIBarButtonItem(image: menuButtonImage, style: .plain, target: self, action: #selector(didTapMenuButton))
    navigationItem.rightBarButtonItem = menuButton
}

@objc public func didTapMenuButton() {
    print("Hello World")
}

0

ขออันนี้ช่วยอีกนิด

สมมติว่าคุณต้องการสร้างปุ่มแถบในไฟล์แยกต่างหาก (สำหรับวิธีการแบบแยกส่วน) และต้องการให้ตัวเลือกกลับไปที่ตัวควบคุมมุมมองของคุณคุณสามารถทำได้ดังนี้: -

ไฟล์ยูทิลิตี้ของคุณ

class GeneralUtility {

    class func customeNavigationBar(viewController: UIViewController,title:String){
        let add = UIBarButtonItem(title: "Play", style: .plain, target: viewController, action: #selector(SuperViewController.buttonClicked(sender:)));  
      viewController.navigationController?.navigationBar.topItem?.rightBarButtonItems = [add];
    }
}

จากนั้นสร้างคลาส SuperviewController และกำหนดฟังก์ชันเดียวกันกับมัน

class SuperViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
            // Do any additional setup after loading the view.
    }
    @objc func buttonClicked(sender: UIBarButtonItem) {

    }
}

และใน base viewController ของเรา (ซึ่งสืบทอดคลาส SuperviewController ของคุณ) จะแทนที่ฟังก์ชันเดียวกัน

import UIKit

class HomeViewController: SuperViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func viewWillAppear(_ animated: Bool) {
        GeneralUtility.customeNavigationBar(viewController: self,title:"Event");
    }

    @objc override func buttonClicked(sender: UIBarButtonItem) {
      print("button clicked")    
    } 
}

ตอนนี้เพียงแค่สืบทอด SuperViewController ในคลาสใดก็ตามที่คุณต้องการปุ่มบาร์นี้

ขอบคุณสำหรับการอ่าน


0

สวิฟต์ 5

ถ้าคุณได้สร้าง UIBarButtonItemใน Interface Builder และคุณเชื่อมต่อเต้าเสียบกับรายการและต้องการผูกตัวเลือกโดยใช้โปรแกรม

อย่าลืมกำหนดเป้าหมายและตัวเลือก

addAppointmentButton.action = #selector(moveToAddAppointment)
addAppointmentButton.target = self

@objc private func moveToAddAppointment() {
     self.presenter.goToCreateNewAppointment()
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.