'#selector'는 Objective-C에 노출되지 않는 메소드를 나타냅니다.


105

addTarget을 통해 매개 변수를 전달하는 새로운 Xcode 7.3은 일반적으로 저에게 효과적이지만이 경우 제목에 오류가 발생합니다. 어떤 아이디어? @objc로 변경하려고 할 때 다른 것을 던집니다.

감사합니다!

cell.commentButton.addTarget(self, action: #selector(FeedViewController.didTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside)

호출하는 선택자

func didTapCommentButton(post: Post) {
}

3
FeedViewController의 클래스 선언 라인은 어떻게 생겼습니까? didTapCommentButton은 어떻게 선언됩니까? @objc를 추가하면 어떤 오류가 발생합니까?
vacawama

1
업데이트, 내 게시물을 편집했습니다. 나는 지금 컴퓨터에서 떨어져있어 정확한 오류 메시지를 잊어 버렸지 만 XCode가 추가하라고 지시 한 다음 자체 결정에 오류를 던지는 상황 중 하나였습니다.
Echizzle

2
클래스가 선언합니까 @objc, 아니면 하위 클래스 NSObject입니까?
NRitH

2
괄호를 제거 할 수 있습니까? 선택기에서 함수를 호출해서는 안된다는 점을 고려하면 드문 일입니다.
DanielEdrisian

답변:


173

제 경우에는 선택기의 기능이 private. 제거하면 private오류가 사라졌습니다. 동일은 간다 fileprivate.

Swift 4에서는 함수 선언
에 추가 @objc해야합니다. 신속한 4까지 이것은 암시 적으로 추론되었습니다.


2
뿐만 아니라 fileprivate.
hstdt

큰 캐치 @shaked
jbouaziz

@hstdt, 설정 fileprivate하면 해결됩니까?
Hemang 2017 년

2
아니, @Hemang, 둘 수단 @hstdt privatefileprivate작동하지 않습니다
Gobe

동적으로 func를 만드는 것이 private / fileprivate를 제거하는 것보다 더 적절합니다.
Boon

57

당신은 사용할 필요 @objc에 속성을 didTapCommentButton(_:)함께 사용하는을 #selector.

그렇게했다고 말했지만 또 다른 오류가 발생했습니다. 내 생각에 새로운 오류는 PostObjective-C와 호환되는 유형이 아니라는 것입니다. 모든 인수 형식과 반환 형식이 Objective-C와 호환되는 경우에만 메서드를 Objective-C에 노출 할 수 있습니다.

Post의 하위 클래스를 만들어서 고칠 수 NSObject있지만, 인수가 어쨌든 아니기 때문에 그것은 중요 didTapCommentButton(_:)하지 않습니다 Post. 행동 함수에 대한 인수는 인 송신기 동작 중, 그 송신기는 것이다 commentButton아마 인 UIButton. 다음 didTapCommentButton과 같이 선언해야 합니다.

@objc func didTapCommentButton(sender: UIButton) {
    // ...
}

그런 다음 Post탭한 버튼에 해당하는 문제에 직면하게 됩니다. 그것을 얻는 방법은 여러 가지가 있습니다. 여기 하나입니다.

나는 cell.commentButton당신이 테이블 뷰 (또는 컬렉션 뷰)를 설정하고 있다는 것을 수집합니다 (코드가라고 말했기 때문에 ). 그리고 셀에라는 비표준 속성 commentButton이 있으므로 사용자 지정 UITableViewCell하위 클래스 라고 가정합니다 . 따라서 셀 PostCell이 다음과 같이 선언 되었다고 가정 해 보겠습니다 .

class PostCell: UITableViewCell {
    @IBOutlet var commentButton: UIButton?
    var post: Post?

    // other stuff...
}

그런 다음 버튼에서 뷰 계층 구조로 올라가를 찾고 PostCell게시물을 가져올 수 있습니다.

@objc func didTapCommentButton(sender: UIButton) {
    var ancestor = sender.superview
    while ancestor != nil && !(ancestor! is PostCell) {
        ancestor = view.superview
    }
    guard let cell = ancestor as? PostCell,
        post = cell.post
        else { return }

    // Do something with post here
}

글로벌 기능과 함께 사용하고 싶다면? @objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
TomSawyer 2016-06-04

전역 함수와 함께 사용할 수 없습니다.
rob mayoff 2016-06-04

8

선택기가 래퍼 함수를 ​​가리 키도록하여 차례로 위임 함수를 호출합니다. 그것은 나를 위해 일했습니다.

cell.commentButton.addTarget(self, action: #selector(wrapperForDidTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside)

-

func wrapperForDidTapCommentButton(post: Post) {
     FeedViewController.didTapCommentButton(post)
}

1
나를 위해 일했습니다! 왜 이것이 필요한지 확실하지 않지만 내가 가져갈 것입니다!
Paul Lehn

0

아시다시피 selector[About]Objective-C런타임을 사용해야 한다고 말합니다 . 기본적으로 Objective-C 런타임 표시 private되거나 fileprivate노출되지 않는 선언입니다 . 이것이 두 가지 변형이있는 이유입니다.

  1. 귀하의 private또는 fileprivate선언을 [About]로 표시하십시오 @objc.
  2. 사용 internal, public, open액세스 수정 [소개]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.