@selector () trong Swift?


660

Tôi đang cố gắng để tạo ra một NSTimertrong Swiftnhưng tôi đang gặp một số rắc rối.

NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)

test() là một hàm trong cùng một lớp.


Tôi gặp lỗi trong trình chỉnh sửa:

Không thể tìm thấy quá tải cho 'init' chấp nhận các đối số được cung cấp

Khi tôi thay đổi selector: test()để selector: nillỗi biến mất.

Tôi đã thử:

  • selector: test()
  • selector: test
  • selector: Selector(test())

Nhưng không có gì hoạt động và tôi không thể tìm thấy một giải pháp trong tài liệu tham khảo.


11
selector: test()sẽ gọi testvà chuyển giá trị trả về của nó cho selectorđối số.
Michael Dorst

Câu trả lời:


930

Bản thân Swift không sử dụng các công cụ chọn - một số mẫu thiết kế trong Objective-C sử dụng các công cụ chọn hoạt động khác nhau trong Swift. (Ví dụ: sử dụng chuỗi tùy chọn trên các loại giao thức hoặc is/ askiểm tra thay vì respondsToSelector:và sử dụng các bao đóng bất cứ nơi nào bạn có thể thay vì performSelector:để đảm bảo an toàn cho loại / bộ nhớ tốt hơn.)

Nhưng vẫn còn một số API dựa trên ObjC quan trọng sử dụng các bộ chọn, bao gồm bộ định thời và mẫu mục tiêu / hành động. Swift cung cấp Selectorloại để làm việc với những thứ này. (Swift tự động sử dụng điều này thay cho SELloại ObjC .)

Trong Swift 2.2 (Xcode 7.3) trở lên (bao gồm Swift 3 / Xcode 8 và Swift 4 / Xcode 9):

Bạn có thể xây dựng một Selectorkiểu hàm Swift bằng #selectorbiểu thức.

let timer = Timer(timeInterval: 1, target: object,
                  selector: #selector(MyClass.test),
                  userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
                 for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
             with: button, with: otherButton)

Điều tuyệt vời về phương pháp này? Tham chiếu hàm được trình biên dịch Swift kiểm tra, do đó bạn chỉ có thể sử dụng #selectorbiểu thức với các cặp lớp / phương thức thực sự tồn tại và đủ điều kiện để sử dụng làm bộ chọn (xem "Tính khả dụng của bộ chọn" bên dưới). Bạn cũng có thể làm cho tham chiếu chức năng của mình chỉ cụ thể như bạn cần, theo quy tắc Swift 2.2+ để đặt tên loại chức năng .

(Đây thực sự là một cải tiến so với @selector()chỉ thị của ObjC , bởi vì -Wundeclared-selectorkiểm tra của trình biên dịch chỉ xác minh rằng bộ chọn có tên tồn tại. Tham chiếu hàm Swift mà bạn chuyển để #selectorkiểm tra sự tồn tại, tư cách thành viên trong một lớp và chữ ký loại.)

Có một vài cảnh báo bổ sung cho các tham chiếu hàm bạn chuyển đến #selectorbiểu thức:

  • Nhiều hàm có cùng tên cơ sở có thể được phân biệt bằng nhãn tham số của chúng bằng cú pháp đã nói ở trên để tham chiếu hàm (ví dụ insertSubview(_:at:)vs insertSubview(_:aboveSubview:)). Nhưng nếu một hàm không có tham số, cách duy nhất để phân tán hàm đó là sử dụng asép kiểu với chữ ký loại của hàm (ví dụ foo as () -> ()vs foo(_:)).
  • Có một cú pháp đặc biệt cho các cặp getter / setter thuộc tính trong Swift 3.0+. Ví dụ, cho một var foo: Int, bạn có thể sử dụng #selector(getter: MyClass.foo)hoặc #selector(setter: MyClass.foo).

Ghi chú chung:

Các trường hợp #selectorkhông hoạt động và đặt tên: Đôi khi, bạn không có tham chiếu chức năng để tạo bộ chọn với (ví dụ: với các phương thức được đăng ký động trong thời gian chạy ObjC). Trong trường hợp đó, bạn có thể xây dựng một Selectorchuỗi từ: vd Selector("dynamicMethod:")- mặc dù bạn mất kiểm tra tính hợp lệ của trình biên dịch. Khi bạn làm điều đó, bạn cần tuân theo các quy tắc đặt tên ObjC, bao gồm cả dấu hai chấm ( :) cho mỗi tham số.

Tính khả dụng của bộ chọn: Phương thức được tham chiếu bởi bộ chọn phải được hiển thị với thời gian chạy ObjC. Trong Swift 4, mọi phương thức được hiển thị với ObjC phải được khai báo trước bằng @objcthuộc tính. (Trong các phiên bản trước, bạn đã có thuộc tính đó miễn phí trong một số trường hợp, nhưng bây giờ bạn phải khai báo rõ ràng.)

Hãy nhớ rằng privatecác biểu tượng không được tiếp xúc với thời gian chạy, quá - phương pháp của bạn cần phải có ít nhất internalkhả năng hiển thị.

Đường dẫn chính: Chúng có liên quan đến nhưng không hoàn toàn giống như bộ chọn. Cũng có một cú pháp đặc biệt cho những điều này trong Swift 3: vd chris.valueForKeyPath(#keyPath(Person.friends.firstName)). Xem SE-0062 để biết chi tiết. Và thậm chí nhiều KeyPaththứ khác trong Swift 4 , vì vậy hãy đảm bảo bạn đang sử dụng API dựa trên KeyPath phù hợp thay vì bộ chọn nếu thích hợp.

Bạn có thể đọc thêm về các công cụ chọn trong Tương tác với API Objective-C khi sử dụng Swift với Ca cao và Objective-C .

Lưu ý: Trước Swift 2.2, Selectortuân thủ StringLiteralConvertible, do đó bạn có thể tìm thấy mã cũ trong đó các chuỗi trần được chuyển đến các API có bộ chọn. Bạn sẽ muốn chạy "Chuyển đổi sang Cú pháp Swift hiện tại" trong Xcode để có được những người sử dụng #selector.


8
Đặt một chuỗi với tên hàm làm việc, NSSelectorFromString () cũng hoạt động.
Arbitur

7
Tôi muốn đề cập rằng trong khi "Tương tác với API khách quan-C" có trên trang web, thì nó KHÔNG có trong cuốn sách 'Ngôn ngữ lập trình Swift'.

10
Điều này có lẽ nên đề cập rằng bộ chọn cần một dấu ":" ở cuối nếu nó cần một đối số. (Ví dụ: kiểm tra () -> "kiểm tra" & kiểm tra (này: Chuỗi) -> "kiểm tra:")
Daniel Schlaug

2
Cũng cần chỉ ra rằng các khung công tác Cacao mong đợi một tên phương thức kiểu Objective-C. Nếu phương thức của bạn có một đối số, bạn sẽ cần một ':' nếu cần 2 đối số size:andShape:, nếu đối số đầu tiên được đặt tên, bạn có thể cần một With, tức là initWithData:chofunc init(Data data: NSData)
JMFR

6
Có cách nào để thêm xác nhận xung quanh việc chuyển "bộ chọn" dưới dạng chuỗi không? Trình biên dịch IE cảnh báo chúng tôi khi chúng tôi viết sai chính tả, v.v.
yo.ian.g

86

Dưới đây là một ví dụ nhanh về cách sử dụng Selectorlớp trên Swift:

override func viewDidLoad() {
    super.viewDidLoad()

    var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
    self.navigationItem.rightBarButtonItem = rightButton
}

func method() {
    // Something cool here   
}

Lưu ý rằng nếu phương thức được truyền dưới dạng chuỗi không hoạt động, nó sẽ thất bại khi chạy, không biên dịch thời gian và làm hỏng ứng dụng của bạn. Hãy cẩn thận


13
thật là kinh khủng ... có loại "NSStringFromSelector" không?
Lena Bru

11
không thể tin rằng họ đã thiết kế cho các bộ chọn không được kiểm tra vì objc có cái này
malhal

4
@malcomhall: @selectortiện dụng, nhưng nó không được thi hành chính thức như bạn nghĩ. "Bộ chọn không khai báo" chỉ đơn thuần là một cảnh báo từ trình biên dịch, bởi vì bộ chọn mới luôn có thể được giới thiệu trong thời gian chạy. Mặc dù vậy, các tham chiếu bộ chọn có thể xác minh / tái cấu trúc trong Swift sẽ là một yêu cầu tính năng tốt để thực hiện .
còi xương

2
Câu trả lời này hữu ích nhưng câu trả lời dưới đây với @objc thì phù hợp hơn.
cynistersix

Khi bạn truyền chuỗi bộ chọn dưới dạng một biến hoặc tham số, bạn sẽ cần cho trình biên dịch biết bộ chọn của nó bằng hàm Selector (). cảm ơn
thuế

46

Ngoài ra, nếu lớp (Swift) của bạn không xuất phát từ lớp Objective-C, thì bạn phải có dấu hai chấm ở cuối chuỗi tên phương thức đích và bạn phải sử dụng thuộc tính @objc với phương thức đích của mình, vd

var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))

@objc func method() {
    // Something cool here   
} 

nếu không, bạn sẽ gặp lỗi "Bộ nhận dạng không nhận dạng" khi chạy.


3
1. bộ chọn w / dấu hai chấm phải lấy đối số 2. theo hành động của bộ định thời tài liệu của Apple nên lấy đối số NSTimer 3. Selectortừ khóa không bắt buộc. Vì vậy, trong trường hợp này, chữ ký phải là@objc func method(timer: NSTimer) {/*code*/}
Yevhen Dubinin

@objcđã làm cho tôi. Tôi không cần đưa timer: NSTimervào chữ ký phương thức của mình để được gọi.
Mike Cheesne

32

Cập nhật Swift 2.2+ và Swift 3

Sử dụng #selectorbiểu thức mới , loại bỏ nhu cầu sử dụng chuỗi ký tự chuỗi làm cho việc sử dụng ít bị lỗi hơn. Để tham khảo:

Selector("keyboardDidHide:")

trở thành

#selector(keyboardDidHide(_:))

Xem thêm: Đề xuất tiến hóa Swift

Lưu ý (Swift 4.0):

Nếu sử dụng, #selectorbạn cần đánh dấu chức năng là@objc

Thí dụ:

@objc func something(_ sender: UIButton)


26

Swift 4.0

bạn tạo Selector như bên dưới.

1. thêm sự kiện vào một nút như:

button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)

và chức năng sẽ như dưới đây:

@objc func clickedButton(sender: AnyObject) {

}

4
Bạn đã quên đặt @objctrước funcđó là bắt buộc trong Swift 4.
Vahid Amiri

24

Đối với những độc giả tương lai, tôi thấy rằng tôi đã gặp phải sự cố và đã gặp phải unrecognised selector sent to instancelỗi do đánh dấu mục tiêufunc là riêng tư.

Các func PHẢI được hiển thị công khai để được gọi bằng một đối tượng với một tham chiếu đến một selector.


13
không cần phải công khai, bạn vẫn có thể giữ phương thức riêng tư nhưng thêm objctrước khi khai báo. Ví dụ: @objc private func foo() { ...sau đó bạn có thể sử dụng "foo"làm công cụ chọn bao nhiêu tùy thích
apouche

Do đó, nó cũng có thể internalkhông chỉ định bất kỳ công cụ sửa đổi truy cập nào. Tôi thường sử dụng mẫu này://MARK: - Selector Methods\n extension MyController {\n func buttonPressed(_ button: UIButton) {
Sajjon

19

Chỉ trong trường hợp ai đó có cùng vấn đề với tôi với NSTimer, trong đó không có câu trả lời nào khác khắc phục được vấn đề, thực sự quan trọng để đề cập rằng, nếu bạn đang sử dụng một lớp không kế thừa từ NSObject trực tiếp hoặc sâu trong hệ thống phân cấp ( ví dụ: các tệp swift được tạo thủ công), không có câu trả lời nào khác sẽ hoạt động ngay cả khi được chỉ định như sau:

let timer = NSTimer(timeInterval: 1, target: self, selector: "test", 
                    userInfo: nil, repeats: false)
func test () {}

Không thay đổi bất cứ điều gì khác ngoài việc làm cho lớp kế thừa từ NSObject, tôi đã ngừng nhận lỗi "Bộ chọn không nhận dạng" và làm cho logic của tôi hoạt động như mong đợi.


Vấn đề với giải pháp thay thế này là bạn có thể thay đổi một lớp (hãy nói rằng ViewContoder) để kế thừa từ NSObject, với điều kiện là bạn cần lớp ViewContoder được triển khai (ví dụ: viewDidLoad ()). Bạn có biết cách gọi hàm Swift trong ViewContoder bằng NSTimer không? ... e
eharo2 22/07/14

1
UIViewControll đã kế thừa từ NSObject, hầu hết các lớp được SDK trưng bày, ví dụ này dành cho các lớp được tạo riêng của bạn yêu cầu chức năng NSTimer ...
Martin Cazares

14

Nếu bạn muốn truyền tham số cho hàm từ NSTimer thì đây là giải pháp của bạn:

var somethingToPass = "It worked"

let timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "tester:", userInfo: somethingToPass, repeats: false)

func tester(timer: NSTimer)
{
    let theStringToPrint = timer.userInfo as String
    println(theStringToPrint)
}

Bao gồm dấu hai chấm trong văn bản chọn (người kiểm tra :) và (các) tham số của bạn đi trong userInfo.

Hàm của bạn sẽ lấy NSTimer làm tham số. Sau đó, chỉ cần giải nén userInfo để có được tham số đã truyền.


3
Tôi đã sử dụng NSTimer (0,01, đích: tự, ...) mà KHÔNG hoạt động, trong khi sử dụng NSTimer.schediatedTimerWithTimeInterval (0,01, ..) DID hoạt động!? Lạ nhưng cảm ơn @Scooter đã trả lời cho bạn!
iOS

1
@ iOS-Coder chỉ tạo một bộ đếm thời gian với trình khởi tạo không thêm nó vào runloop, trong khi scheduledTimerWith...tự động thêm nó vào runloop hiện tại - vì vậy không có hành vi lạ nào ở đây cả;)
David Ganster

1
@David cảm ơn lời đề nghị của bạn. Tôi đoán sự hiểu lầm của tôi nên thuộc về loại STFW hoặc RTFA (Đọc API F ... ing)?
iOS

1
Đừng lo lắng về điều đó, không ai có thể mong đợi đọc tài liệu về mọi phương thức trong mỗi API;)
David Ganster

10

Các bộ chọn là một biểu diễn bên trong của một tên phương thức trong Objective-C. Trong Objective-C "@selector (methodName)" sẽ chuyển đổi một phương thức mã nguồn thành một kiểu dữ liệu của SEL. Vì bạn không thể sử dụng cú pháp @selector trong Swift (rickster đang ở điểm đó), bạn phải trực tiếp chỉ định tên phương thức là một đối tượng Chuỗi hoặc bằng cách chuyển một đối tượng Chuỗi sang loại Selector. Đây là một ví dụ:

var rightBarButton = UIBarButtonItem(
    title: "Logout", 
    style: UIBarButtonItemStyle.Plain, 
    target: self, 
    action:"logout"
)

hoặc là

var rightBarButton = UIBarButtonItem(
    title: "Logout", 
    style: UIBarButtonItemStyle.Plain, 
    target: self, 
    action:Selector("logout")
)

8

Swift 4.1
Với mẫu cử chỉ nhấn

let gestureRecognizer = UITapGestureRecognizer()
self.view.addGestureRecognizer(gestureRecognizer)
gestureRecognizer.addTarget(self, action: #selector(self.dismiss(completion:)))

// Use destination 'Class Name' directly, if you selector (function) is not in same class.
//gestureRecognizer.addTarget(self, action: #selector(DestinationClass.dismiss(completion:)))


@objc func dismiss(completion: (() -> Void)?) {
      self.dismiss(animated: true, completion: completion)
}

Xem tài liệu của Apple để biết thêm chi tiết về: Biểu thức chọn


Hãy ngừng làm điều này. Nó không giúp được ai. Điều này khác với Swift 3.1 như thế nào? Và tại sao bạn nghĩ cần phải thêm một câu trả lời cho điều này khi nó đã có khoảng 20 câu trả lời?
Fogmeister

gọi bộ chọn là khác nhau trong swift 4. Hãy thử những câu trả lời trong swift 4 và xem. Không có cái này sẽ làm việc mà không cần chỉnh sửa. Vui lòng không đánh dấu bất kỳ tuyên bố nào là thư rác mà không đảm bảo sự bất lực của nó
Krunal

Vì vậy, có bất kỳ lý do bạn không thể chỉnh sửa câu trả lời hiện có, được chấp nhận? Nó sẽ làm cho nó thực sự hữu ích thay vì thêm vào cuối danh sách dài các câu trả lời. Nút "Chỉnh sửa" là có lý do.
Fogmeister

Ngoài ra, phần nào khác với Swift 3?
Fogmeister

2
Bạn phải thêm thẻ objc vào bất kỳ bộ chọn nào cho Swift 4. Đây là câu trả lời đúng. Và bạn không cần phải chỉnh sửa câu trả lời của người khác để thay đổi ý nghĩa của chúng. @Krunal hoàn toàn đúng.
Unome

6
// for swift 2.2
// version 1
buttton.addTarget(self, action: #selector(ViewController.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(ViewController.tappedButton2(_:)), forControlEvents: .TouchUpInside)

// version 2
buttton.addTarget(self, action: #selector(self.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(self.tappedButton2(_:)), forControlEvents: .TouchUpInside)

// version 3
buttton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(tappedButton2(_:)), forControlEvents: .TouchUpInside)

func tappedButton() {
  print("tapped")
}

func tappedButton2(sender: UIButton) {
  print("tapped 2")
}

// swift 3.x
button.addTarget(self, action: #selector(tappedButton(_:)), for: .touchUpInside)

func tappedButton(_ sender: UIButton) {
  // tapped
}

button.addTarget(self, action: #selector(tappedButton(_:_:)), for: .touchUpInside)

func tappedButton(_ sender: UIButton, _ event: UIEvent) {
  // tapped
}

nó sẽ đẹp hơn và có tính giáo dục hơn nếu bạn có một ví dụ lấy hai hoặc ba đối số cho Swift3 hoặc Swift4. Cảm ơn.
nyxee

5
Create Refresh control using Selector method.   
    var refreshCntrl : UIRefreshControl!
    refreshCntrl = UIRefreshControl()
    refreshCntrl.tintColor = UIColor.whiteColor()
    refreshCntrl.attributedTitle = NSAttributedString(string: "Please Wait...")
    refreshCntrl.addTarget(self, action:"refreshControlValueChanged", forControlEvents: UIControlEvents.ValueChanged)
    atableView.addSubview(refreshCntrl)

// Làm mới phương thức điều khiển

func refreshControlValueChanged(){
    atableView.reloadData()
    refreshCntrl.endRefreshing()

}

5

Kể từ khi Swift 3.0 được xuất bản, việc khai báo một TargetAction phù hợp thậm chí còn tinh tế hơn một chút

class MyCustomView : UIView {

    func addTapGestureRecognizer() {

        // the "_" is important
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyCustomView.handleTapGesture(_:)))
        tapGestureRecognizer.numberOfTapsRequired = 1
        addGestureRecognizer(tapGestureRecognizer)
    }

    // since Swift 3.0 this "_" in the method implementation is very important to 
    // let the selector understand the targetAction
    func handleTapGesture(_ tapGesture : UITapGestureRecognizer) {

        if tapGesture.state == .ended {
            print("TapGesture detected")
        }
    }
}

4

Khi đang sử dụng performSelector()

/addtarget()/NStimer.scheduledTimerWithInterval() phương thức của bạn (khớp với bộ chọn) phải được đánh dấu là

@objc
For Swift 2.0:
    {  
        //...
        self.performSelector(“performMethod”, withObject: nil , afterDelay: 0.5)
        //...


    //...
    btnHome.addTarget(self, action: “buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
    //...

    //...
     NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector : “timerMethod”, userInfo: nil, repeats: false)
    //...

}

@objc private func performMethod() {}
@objc private func buttonPressed(sender:UIButton){.
}
@objc private func timerMethod () {.
}

Đối với Swift 2.2, bạn cần viết '#selector ()' thay vì tên chuỗi và tên bộ chọn để các khả năng lỗi chính tả và lỗi do điều đó sẽ không còn nữa. Dưới đây là ví dụ

self.performSelector(#selector(MyClass.performMethod), withObject: nil , afterDelay: 0.5)

3

bạn tạo Selector như bên dưới.
1.

UIBarButtonItem(
    title: "Some Title",
    style: UIBarButtonItemStyle.Done,
    target: self,
    action: "flatButtonPressed"
)

2.

flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)

Hãy lưu ý rằng cú pháp @selector đã biến mất và được thay thế bằng một Chuỗi đơn giản đặt tên phương thức để gọi. Có một lĩnh vực mà tất cả chúng ta đều có thể đồng ý về tính dài dòng gây cản trở. Tất nhiên, nếu chúng ta tuyên bố rằng có một phương thức đích gọi là FlatButtonPression: chúng ta nên viết một phương thức:

func flatButtonPressed(sender: AnyObject) {
  NSLog("flatButtonPressed")
}

đặt thời gian:

    var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, 
                    target: self, 
                    selector: Selector("flatButtonPressed"), 
                    userInfo: userInfo, 
                    repeats: true)
    let mainLoop = NSRunLoop.mainRunLoop()  //1
    mainLoop.addTimer(timer, forMode: NSDefaultRunLoopMode) //2 this two line is optinal

Để hoàn thành, đây là FlatButtonPression

func flatButtonPressed(timer: NSTimer) {
}

Bạn có nguồn nào cho " Lưu ý rằng cú pháp @selector đã biến mất " không?
winklerrr

3

Tôi thấy nhiều câu trả lời này hữu ích nhưng không rõ làm thế nào để làm điều này với thứ không phải là nút. Tôi đã thêm một trình nhận dạng cử chỉ vào một UILabel nhanh chóng và vật lộn vì vậy đây là những gì tôi thấy có hiệu quả với tôi sau khi đọc mọi thứ ở trên:

let tapRecognizer = UITapGestureRecognizer(
            target: self,
            action: "labelTapped:")

Trường hợp "Bộ chọn" được khai báo là:

func labelTapped(sender: UILabel) { }

Lưu ý rằng nó là công khai và tôi không sử dụng cú pháp Selector () nhưng cũng có thể làm điều này.

let tapRecognizer = UITapGestureRecognizer(
            target: self,
            action: Selector("labelTapped:"))

3

Sử dụng #selector sẽ kiểm tra mã của bạn tại thời điểm biên dịch để đảm bảo phương thức bạn muốn gọi thực sự tồn tại. Thậm chí tốt hơn, nếu phương thức không tồn tại, bạn sẽ gặp lỗi biên dịch: Xcode sẽ từ chối xây dựng ứng dụng của bạn, do đó cấm để quên đi một nguồn lỗi khác có thể xảy ra.

override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.rightBarButtonItem =
            UIBarButtonItem(barButtonSystemItem: .Add, target: self,
                            action: #selector(addNewFireflyRefernce))
    }

    func addNewFireflyReference() {
        gratuitousReferences.append("Curse your sudden but inevitable betrayal!")
    }

2

Nó có thể hữu ích để lưu ý nơi bạn thiết lập điều khiển kích hoạt các vấn đề hành động.

Ví dụ, tôi đã thấy rằng khi thiết lập UIBarButtonItem, tôi phải tạo nút trong viewDidLoad nếu không tôi sẽ nhận được một ngoại lệ bộ chọn không được nhận dạng.

override func viewDidLoad() {
    super.viewDidLoad() 

    // add button
    let addButton = UIBarButtonItem(image: UIImage(named: "746-plus-circle.png"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("addAction:"))
    self.navigationItem.rightBarButtonItem = addButton
}

func addAction(send: AnyObject?) {     
    NSLog("addAction")
}

1

Thay đổi như một cách đặt tên chuỗi đơn giản trong phương thức gọi cú pháp bộ chọn

var timer1 : NSTimer? = nil
timer1= NSTimer(timeInterval: 0.1, target: self, selector: Selector("test"), userInfo: nil, repeats: true)

Sau đó, gõ func test ().


1

selectorlà một từ từ Objective-Cthế giới và bạn có thể sử dụng nó từ Swiftđể có khả năng gọi Objective-Ctừ Swift Nó cho phép bạn thực thi một số mã khi chạy

Trước Swift 2.2cú pháp là:

Selector("foo:")

Vì một tên hàm được truyền vào Selectordưới dạng tham số String ("foo"), không thể kiểm tra tên trong thời gian biên dịch . Kết quả là bạn có thể gặp lỗi thời gian chạy:

unrecognized selector sent to instance

Sau Swift 2.2+cú pháp là:

#selector(foo(_:))

Tự động hoàn tất của Xcode giúp bạn gọi đúng phương thức


0

Dành cho Swift 3

// Mã mẫu để tạo bộ đếm thời gian

Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)

WHERE
timeInterval:- Interval in which timer should fire like 1s, 10s, 100s etc. [Its value is in secs]
target:- function which pointed to class. So here I am pointing to current class.
selector:- function that will execute when timer fires.

func updateTimer(){
    //Implemetation 
} 

repeats:- true/false specifies that timer should call again n again.

0

Công cụ chọn trong Swift 4:

button.addTarget(self, action: #selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)

-1

Dành cho 3

let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.test), userInfo: nil, repeats: true)

Khai báo hàm Trong cùng một lớp:

@objc func test()
{
    // my function
} 

Nếu mục tiêu là tự, thì không cần phải có selftrong bộ chọn. Điều này là đủ:let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(test), userInfo: nil, repeats: true)
Mithra Singam
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.