Перенаправить действие кнопки на другую функцию в Swift

Это может быть простой вопрос, но я новичок в Swift и не знаю, для каких условий искать в Google.

Для приложения панели меню я реализовал пользовательскую функцию под названием doSomething это работает просто отлично, когда привязано к какой-то кнопке:

Class MainViewController:
{
    @IBAction func doSomething(sender: NSButton) 
    {
        // Do something when NSButton is pressed
    }
}

Тем не менее, мне нужно различать нажатие левой и правой кнопки на кнопке, которая в моем случае является NSStatusBarButton, Следуя предложению из этого ответа, я написал следующее в мой AppDelegate.swift:

@NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate {

    let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-2)
    var mainViewController: MainViewController?


    func applicationDidFinishLaunching(notification: NSNotification) 
    {
        if let button = statusItem.button 
        {
            button.action = #selector(customClickAction)
            button.sendActionOn(Int(NSEventMask.RightMouseDownMask.rawValue | NSEventMask.LeftMouseDownMask.rawValue))
        }
    }


    func customClickAction(sender: NSButton) 
    {
        let event:NSEvent! = NSApp.currentEvent!

        if (event.type == NSEventType.RightMouseDown) 
        {
            print("Right mouse button down")
        } 
        else if (event.type == NSEventType.LeftMouseDown)
        {
            print("Left mouse button down")
            mainViewController?.doSomething(_:) // THIS DOES NOT WORK
         }
    }
}

Приведенный выше фрагмент кода дает мне сообщение об ошибке "Выражение разрешается в неиспользуемую функцию" в XCode. Я не могу понять, как правильно вызвать функцию doSomething от MainViewController класс в пределах customClickAction или, что эквивалентно, как перенаправить действие statusItem.button с помощью customClickAction в doSomething, Я прошу прощения, если этот вопрос может показаться слишком тривиальным для экспертов Swift, но я действительно в отчаянии, пытаясь выяснить этот вопрос.

РЕДАКТИРОВАТЬ:

Если функция customClickAction не существовало, я бы просто написал button.action = #selector(mainViewController?.show(_:)) в applicationDidFinishLaunching вызвать функцию и все работает. Тем не менее, часть моей проблемы заключается в том, что выполнение того же в моей пользовательской функции перезапишет привязку после первого нажатия левой кнопки мыши.

1 ответ

Решение

Вот вопрос от кого-то, кто имел такой же Expression resolves to an unused function проблема. В его / ее случае проблема заключалась в том, что функции вызывались без () после функции, так stop вместо stop() (если это имеет смысл).

Хорошо, теперь, когда мы знаем, что компилятор пытается нам сказать, мы можем попытаться выяснить, что делать, чтобы решить эту проблему.

В вашем случае проблема в том, что вам нужно отправить sender параметр вашего doSomething метод, и этот параметр должен иметь тип NSButton как вы заявили о себе.

@IBAction func doSomething(sender: NSButton) 
{
    // Do something when NSButton is pressed
}

Итак, в вашем случае, если вы просто передадите sender который вы получаете в качестве параметра для вашего customClickAction а так вот:

func customClickAction(sender: NSButton)
{
    let event:NSEvent! = NSApp.currentEvent!

    if (event.type == NSEventType.RightMouseDown)
    {
        print("Right mouse button down")
    }
    else if (event.type == NSEventType.LeftMouseDown)
    {
        print("Left mouse button down")
        mainViewController?.doSomething(sender)
    }
}

Тогда компилятор кажется счастливым.

Вот весь AppDelegate

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-2)
    var mainViewController: MainViewController? = MainViewController() //initialized


    func applicationDidFinishLaunching(notification: NSNotification)
    {
        if let button = statusItem.button
        {
            button.action = #selector(customClickAction)
            button.sendActionOn(Int(NSEventMask.RightMouseDownMask.rawValue | NSEventMask.LeftMouseDownMask.rawValue))
        }
    }


    func customClickAction(sender: NSButton)
    {
        let event:NSEvent! = NSApp.currentEvent!

        if (event.type == NSEventType.RightMouseDown)
        {
            print("Right mouse button down")
        }
        else if (event.type == NSEventType.LeftMouseDown)
        {
            print("Left mouse button down")
            mainViewController?.doSomething(sender)
        }
    }
}

Надеюсь, это поможет вам.

Продолжение вашего редактирования

Ты пишешь

Если бы функция customClickAction не существовала, я просто написал бы button.action = #selector(mainViewController?.Show(_:)) в applicationDidFinishLaunching, чтобы вызвать функцию, и все работает.

Возможно, я здесь все неправильно понимаю, но почему бы вам тогда не "просто" назначить doSomething метод к вашему button.action а затем перемещает проверку для левой или правой кнопки в этот метод?

Так вы бы сказали:

button.action = #selector(mainViewController?.doSomething(_:))

и ваш doSomething будет выглядеть так:

    @IBAction func doSomething(sender: NSButton)
{
    // Do something when NSButton is pressed
    let event:NSEvent! = NSApp.currentEvent!

    if (event.type == NSEventType.RightMouseDown)
    {
        print("Right mouse button down")
    }
    else if (event.type == NSEventType.LeftMouseDown)
    {
        print("Left mouse button down")
    }
}

Если я это сделаю, в моей консоли появятся "Левая кнопка мыши вниз" и "Правая кнопка мыши вниз".

Swift 3 обновление

Как пишет @ixany в комментариях:

Это я или Swift 3?:) Кажется, ваше решение необходимо обновить до Swift 3, так как я не могу адаптировать его, используя текущую бета-версию Xcode

Я пытался обновить синтаксис до Swift 3.0, но, похоже, с этим есть некоторые проблемы.

Первая проблема заключается в том, что я не мог перейти непосредственно к doSomething метод MainViewController при назначении selectorПоэтому я добавил "локальный" шаг, так сказать.

AppDelegate теперь выглядит так:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!

    let statusItem = NSStatusBar.system().statusItem(withLength: -2)
    var mainViewController: MainViewController? = MainViewController()

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        if let button = statusItem.button
        {
            button.action = #selector(AppDelegate.localButtonAction(sender:))
            button.sendAction(on: [NSEventMask.leftMouseDown, NSEventMask.rightMouseDown])
        }
    }

    func localButtonAction(sender: NSStatusBarButton) {
        mainViewController?.doSomething(sender: sender)
    }
}

(Обратите внимание на метод "localButtonAction", я надеюсь, у кого-то есть более красивый способ сделать это)

И MainViewController выглядит так:

import Cocoa

class MainViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
    }

    @IBAction func doSomething(sender: NSStatusBarButton) {
        // Do something when NSButton is pressed
        let event:NSEvent! = NSApp.currentEvent!
        if (event.type == NSEventType.rightMouseDown)
        {
            print("Right mouse button down")
        }
        else if (event.type == NSEventType.leftMouseDown)
        {
            print("Left mouse button down")
        }
    }    
}

Проблема в том, что event никогда не бывает типа rightMouseDown насколько я вижу. Я, вероятно, делаю что-то не так, и я надеюсь, что кто-то еще может сделать эту работу, но теперь он компилируется по крайней мере и имеет синтаксис Swift 3.0 (с использованием Xcode 8.0 - бета 6:))

Надеюсь, это поможет вам @ixany

Другие вопросы по тегам