5

I have read this question and I believe my problem is different.

I have a swift class SwiftUtils.swift that is already making calls to objective c code in my project and I have some objective c code making calls back to swift.

So I've got the bridging header stuff all working as it should.

My issue is I am building a system menu in swift and am trying to call a method in my AppDelegate like this:

@objc func createMenuItem() {
    let appDelegate = NSApplication.shared.delegate as? AppDelegate
    let status = NSMenuItem(title: "System Status",
                            action: #selector(appDelegate.showSystemStatus(_:)),
                            keyEquivalent: "s")
    status.target=appDelegate.self
    statusItem.menu?.insertItem(status, at: 0)
}

I can't get the compiler to resolve AppDelegate on the first line of the func.

Xcode keeps telling me "Cannot find type 'AppDelegate' in scope"

enter image description here

My bridging header:

#ifndef Foo_Bridging_Header_h
#define Foo_Bridging_Header_h

#import <Foundation/Foundation.h>
#import "uiframework/Utils.h"
#import "AppDelegate.h"

#endif /* Foo_Bridging_Header_h */

My AppDelegate.h:

#import <Cocoa/Cocoa.h>
#import "Foo-Swift.h"

@interface AppDelegate : NSObject <NSApplicationDelegate>

@property SwiftUtils *utils;

- (void) checkForUpdates;
+ (void) showSystemStatus;

@end
spartygw
  • 3,289
  • 2
  • 27
  • 51
  • convert AppDelegate to Swift, that will make the whole problem go away – timbre timbre Apr 08 '21 at 17:16
  • Also I believe in Objective C, it's not `NSApplication.shared.delegate`, but rather `NSApplication.sharedApplication().delegate`. And don't forget to `import UIKit`, cos this is where it's defined – timbre timbre Apr 08 '21 at 17:20
  • @KirilS. It is `NSApplication.shared.delegate`. `sharedApplication` is the Objective-C property. `NSApplication` is AppKit. – Willeke Apr 09 '21 at 09:55
  • @Willeke I might be wrong about accessing AppDelegate written in Objective-C - being a while. But your argument doesn't make much sense either. Of course it's an objective-c property (as `NSApplication` is written in objective C), but it has nothing to do with accessing it from Swift. – timbre timbre Apr 09 '21 at 12:50
  • @KirilS. In Objective-C the property is called `sharedApplication`, in Swift the same property is called `shared`. – Willeke Apr 09 '21 at 20:22

1 Answers1

1

As far as I can understand, showSystemStatus method is a class method (e.g. static) and you are trying to call this method from instance. Maybe it can be the root of your issue.

Following example should work for you:

let status = NSMenuItem(title: "System Status",
                action: #selector(AppDelegate.showSystemStatus),
                keyEquivalent: "s")

For preventing the cycling, you can move your implementation to another class and give it a try.

Burak Akkaş
  • 486
  • 3
  • 8
  • Thank you for your answer, unfortunately that just moves the "Cannot find AppDelegate in scope" to the `action` line – spartygw Apr 08 '21 at 16:04
  • Is it possible that you have created a cycle between AppDelegate and the Swift class that you are trying to make a call from? – Burak Akkaş Apr 08 '21 at 16:23
  • Yes, I am confident that I do have that cycle. My AppDelegate calls this swift helper class to construct a menu on startup, but I want that menu to have an item that calls a static func in my AppDelegate – spartygw Apr 08 '21 at 16:28
  • Best way to try this out is breaking the cycle first, basically two ways came to my mind; move out the implementation to another class or try using NSNotificationCenter. – Burak Akkaş Apr 08 '21 at 21:43
  • 1
    @BurakAkkaş Why is the cycle a problem? – Willeke Apr 09 '21 at 09:49
  • I don't understand the issue of the cycle being a problem but moving the code worked. It's fuglier this way but I get paid for making it work and not how pretty it is. So I did this: AppDelegate calls a swift guy who builds the menu and does other stuff I need. The menu's selector now goes to an `AppUtils.m` class which does the stuff I originally had in the AppDelegate. It works, just don't understand why I couldn't keep that code inside the AppDelegate without making my AppDelegate swift. @BurakAkkaş if you'll add `move implementation to another class` to your answer I'll mark it accepted. – spartygw Apr 09 '21 at 15:03
  • Well basically I tried to implement your solution and Xcode gave me an error about the cycle. That's basically what I have tried to inform you about. Glad to know at least your problem solved. I have edited my answer. – Burak Akkaş Apr 10 '21 at 16:22