Questions tagged [pyobjc]

PyObjC is a bridge between the Python and Objective-C programming languages. It allows code written in either one of those languages to interact more or less directly with code written in the other. Its primary use is in the creation of software for Mac OS X. The PyObjC package includes wrappers for Apple's Objective-C frameworks, and most of their C language APIs. It also includes project templates and file templates for use with Apple's IDE, Xcode.

PyObjC's about page explains potential advantages the bridge offers to developers in either language. The bridge allows custom Objective-C and Python code to be co-mingled (nearly) painlessly, so that each can be used where its strengths are greatest.

The most obvious advantage for Python developers is that it allows them to write applications for Mac OS X with native appearance and behaviors. The use of Apple's frameworks facilitates the creation of the expected user experience, while familiar Python modules are always available when needed. A Python class can be a subclass of any framework class.

Objective-C users may find some of their models and application logic to be easier to express succinctly in Python. In particular, the setup and access of NSArray and NSDictionary objects can be cumbersome. The bridge makes a Python list or dictionary able to be used any place that its Cocoa counterpart is expected. Python's literal lists and dictionaries, list comprehensions, iteration, and dictionary lookup syntax make sometimes awkward Objective-C constructions into elegant and readable code. Python code that uses the bridge will also manage the memory of any Cocoa object it uses.

An excellent five-part tutorial, written by Will Larson, can be found on his website, titled "An Epic Introduction to PyObjC and Cocoa". Like the bridge itself, the tutorial serves more as an introduction for Python users to Cocoa than the reverse, but is nonetheless worth reading for anyone who wants to use PyObjC.

The PyObjC Introduction goes through the basics of using the bridge. Where syntax differs, the bridge tends towards making Python code more like Objective-C code. Two syntax differences are worth singling out here: method calls and instance variable access, which can cause confusion for users of the bridge.

Objective-C's message-call syntax uses positional arguments, but the name of the method is actually interleaved with the arguments:

// The name of this method is "actOnArg:usingOtherArg:andThisOneToo:"
[anInstance actOnArg:arg1 usingOtherArg:arg2 andThisOneToo:arg3];

It seems obvious, then, to use Python's keyword argument feature to emulate this:

// The name of this method is "actOnArg", and it has keyword arguments
anInstance.actOnArg(arg1, usingOtherArg=arg2, andThisOneToo=arg3) 

However, because keyword arguments ignore position, it is not feasible to make this kind of translation. To Python, the following call is equivalent to the preceding one:

anInstance.actOnArg(arg1, andThisOneToo=arg3, usingOtherArg=arg2)

while the Objective-C call:

// The name of this method is "actOnArg:andThisOneToo:usingAnotherArg:"
[anInstance actOnArg:arg1 andThisOneToo:arg3 usingOtherArg:arg2];

refers to an entirely different method than the original example.

PyObjC's solution is to use underscores in place of colons in method names:

anInstance.actOnArg_usingOtherArg_andThisOneToo_(arg1, arg2, arg3)

which unambiguously represents the name of the Objective-C method. This, unavoidably, is one of the main warts of the bridge -- the verbosity of Cocoa method names sometimes causes unwieldy Python calls:

NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(1.0, self, objc.selector(self.actOnTimer_, signature='v@:@'), timerInfoDict, False)

As for instance variables, Objective-C has a separate namespace in each class for instance variables and method names, where Python has only one. A class in Objective-C can, and by convention does, have a method with the same name as an instance variable, which is a getter for that variable:

@interface MyObject : NSObject {
    int someIvar;
}
- (int)someIvar;
- (void)setSomeIvar:(int)newVal;   // The setter method for this ivar

Whereas this is impossible in Python. Python convention is to access instance variables directly, using the dot syntax:

anInstance.someIvar
anInstance.someIvar = 10

This especially causes confusion with the Objective-C 2.0 dot syntax, which is sugar for the standard accessor method:

anInstance.someIvar;         // Equivalent to [anInstance someIvar];
anInstance.someIvar = 10;    // Equivalent to [anInstance setSomeIvar:10];

PyObjC is forced to have its own convention, which is to give the ivar the name of the setter method, but prefixed with a single underscore. The convenience function objc.synthesize("someIvar") will create the ivar, the setter method, and the getter method with the expected names.

The PyObjC source is available and well worth a perusal; it especially repays investigation when getting into the trickier areas of the bridge, such as Objective-C methods which use out or plain-C parameters. In addition, the default Apple installation of PyObjC lags behind the latest version. On Snow Leopard particularly, this means that the bridge does not include some information needed to use new features of Apple's frameworks. (See "Problem with openPanelDidEnd" here on SO for an example.) That information is fortunately easily updated.

378 questions
3
votes
1 answer

PyQT/PySide vs PyObjC: worth it?

I'm thinking of creating a cross platform app, but I want it to look as natively as possible on OS X, is PyObjC a good choice? How easy is it? In contrast, how good is QT when it comes to looking native?
FLX
  • 4,634
  • 14
  • 47
  • 60
3
votes
2 answers

How do I represent a void pointer in a PyObjC selector?

I'm wanting to use an NSOpenPanel for an application I'm designing. Here's what I have so far: @objc.IBAction def ShowOpenPanel_(self, sender): self.panel = NSOpenPanel.openPanel() self.panel.setCanChooseFiles_(False) …
Jason Baker
  • 192,085
  • 135
  • 376
  • 510
3
votes
1 answer

PyObjC "Notifications are not allowed for this application"

I'm trying to test a simple Python script to send out a macOS notification: import UserNotifications def notif_callback(err): print("Error in notification callback:",err) def auth_callback(granted, err): print("Granted: ",granted,) …
Mia
  • 2,466
  • 22
  • 38
3
votes
1 answer

error installing PyObjC osX

I am new to Python and I am desperately trying to install PyObjC via spyder. The command pip install PyObjC returns an error: Command "python setup.py egg_info" failed with error code 1 in …
roberta
  • 131
  • 1
  • 12
3
votes
3 answers

Issue with Installing PyObjC for Python

I was attempting to install PyObjC on my Mac OS X El Capitan, and about 40 minutes into the download, I received an error and it stopped. I tried installing using the following code in my terminal: pip install pyobjc The error says: Command python…
djl
  • 267
  • 1
  • 3
  • 13
3
votes
1 answer

How to disable App Transport Security for a script?

I am writing an application which is a python script that uses the pyobjc bindings to use the objc/cocoa runtime on the mac. The application (Présentation.app, a pdf presentation tool for the mac) uses a WebView to display arbitrary web pages. Since…
rndblnch
  • 183
  • 1
  • 10
3
votes
1 answer

Where is objc.signature documented?

I am trying to implement a delegate for an NSWebView, however when I run it, I get this error: TypeError: Error when calling the metaclass bases class Delegate does not correctly implement protocol WebScripting: the signature for method…
Arafangion
  • 11,517
  • 1
  • 40
  • 72
3
votes
2 answers

How to spawn threads in pyobjc

I am learning how to use pyobjc for some basic prototyping. Right now I have a main UI set up and a python script that runs the main application. The only issue is when the script runs, the script runs on the main thread thus blocking the UI. So…
mjl007
  • 735
  • 2
  • 11
  • 27
3
votes
1 answer

NSUserNotificationCenter.defaultUserNotificationCenter() returning None using PyInstaller

I am trying to put notification to notification centre (Mac OSX) I am using PyObjC bindings to use cocoa api's from our python application. I am using following code snippet : import Foundation¬ import objc¬ NSUserNotification =…
Sameer
  • 61
  • 4
3
votes
1 answer

'if' statement, not protecting against AttributeError: 'NoneType' object has no attribute

I have some python (v2.7) code that uses OS X's built in PyObjC bindings to get the executable's path from a bundle via NSBundle bundleWithPath: #bundlePath is a string/path to a .app or .kext mainBundle =…
patrick
  • 380
  • 2
  • 14
3
votes
2 answers

installing pyobjc on mac osx 10.9

I'm trying to download pyobjc on my mac, which runs on 10.9.3. I've tried using easy_install, pip, and manual install. I have setuptools installed with Xcode 5. When I use easy_install, pip, or manual install I get the error: AttributeError:…
mepstein1218
  • 331
  • 5
  • 14
3
votes
2 answers

Trying to write to binary plist format from Python (w/PyObjC) to be fetch and read in by Cocoa Touch

I'm trying to serve a property list of search results to my iPhone app. The server is a prototype, written in Python. First I found Python's built-in plistlib, which is awesome. I want to give search-as-you-type a shot, so I need it to be as small…
zekel
  • 9,227
  • 10
  • 65
  • 96
3
votes
1 answer

PyObjC app not allowed to access the accessibility API

On OSX Maverick, I have this PyObjC(python3.3) based simple APP test.py class MyDelegate(NSObject): def applicationDidFinishLaunching_(self, sender): NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSKeyDownMask, lambda event:…
Shawn
  • 32,509
  • 17
  • 45
  • 74
3
votes
4 answers

Calculating first and last days of current week

Reference to pre-answered question at: Getting first and last days of current week There are two answers in the above link. One of them is theoretical and the other is in a language called as PyObjC (Python-Objective C bridge language), and a quick…
Dot
  • 439
  • 5
  • 17
3
votes
2 answers

Downgrading to pyobjc 2.0 from pyobjc 2.2

I accidentally installed pyobjc 2.2 with easy-install pyobjc, and it's causing problems: When I try to import it I get the error Incompatible library version: _objc.so requires version 10.0.0 or later, but libxml2.2.dylib provides version…
maxdj
  • 427
  • 2
  • 5
  • 15