Search code examples
pythonappkit

Difference between app.activateWithOptions() and app.activateWithOptions_()


Recently I use AppKit to write a program which aims to automatically click inside an application window. When I want to activate the window first, I go through the NSRunningApplication documentation, and found a function called "activateWithOptions", and I wrote a simple program like the following.

Apps = NSWorkspace.sharedWorkspace().runningApplications()
for app in Apps:
    print(app.localizedName())
    app.activateWithOptions(NSApplicationActivateAllWindows)

Here are my questions.

  1. The first question is that, inside the documentation, the localizedName attribute is a variable, but in Python, you must use it as a function such that you can get the name. Why is the difference?
  2. If you run the program, it just throws an error in the following. But if you changed it to app.activateWithOptions_(NSApplicationActivateAllWindows), the code can be passed. Why is the documentation inconsistent with my usage?

    AttributeError: 'NSRunningApplication' object has no attribute 'activateWithOptions'


Solution

  • Localized name

    It's not a variable, it's a property declared as:

    @property(readonly, copy) NSString *localizedName;
    

    It's synthesized into the _localizedName instance variable and this function:

    - (NSString *)localizedName {
      return _localizedName;
    }
    

    Underscore

    PyObjC documentation - Underscores, and lots of them:

    An Objective-C message looks like this:

    [someObject doSomething:arg1 withSomethingElse:arg2];
    

    The selector (message name) for the above snippet is this (note the colons):

    doSomething:withSomethingElse:
    

    In order to have a lossless and unambiguous translation between Objective-C messages and Python methods, the Python method name equivalent is simply the selector with colons replaced by underscores. Since each colon in an Objective-C selector is a placeholder for an argument, the number of underscores in the PyObjC-ified method name is the number of arguments that should be given.

    The PyObjC translation of the above selector is (note the underscores):

    doSomething_withSomethingElse_
    

    activateWithOptions: -> activateWithOptions_