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
0
votes
1 answer

OSX10.9 App crashes: Symbol not found: ___strlcat_chk

I have an application that works perfectly with my MacBook (Mavericks). After trying it with a virtual machine (OSX Lion), it crashes with this Traceback: Mac-OS-X-Lion AppleFileServer[219]: _Assert:…
FBruynbroeck
  • 499
  • 3
  • 15
0
votes
2 answers

How do you use respondsToSelector & performSelector in PyObjc

I'm converting a Objective-C program to PyObjC and lack experience in both. Here is the Objective-C portion WebPreferences *p = [webview preferences]; if([p respondsToSelector:@selector(setWebGLEnabled:)]){ [p…
jitcoder
  • 41
  • 1
  • 2
0
votes
1 answer

Installing LightBlue (BlueTooth) for Python

I'm trying to import lightblue for Python. I have a brand new Mac (so 10.9 I believe), I have Xcode installed, and I am running... Python 2.7.6 :: Anaconda 1.8.0 (x86_64) I downloaded lightblue-0.4.tar.gz to my desktop and then ran $ python…
o-90
  • 17,045
  • 10
  • 39
  • 63
0
votes
0 answers

Python crashes with error vm_copy failed when calling CGDataProviderCopyData

I've got an issue where I'm unable to get the pixel data (via CGDataProviderCopyData) from the Image that gets returned when I call CGImageCreate. Any other call and I'm able to get the data from images with no problem, so obviously I'm doing…
Zack Yoshyaro
  • 2,056
  • 6
  • 24
  • 46
0
votes
2 answers

PyObjC - streaming music with NSSound

I tried to make a simple music streaming app using Python+PyObjC following this blog import Foundation from AppKit import NSSound sound = NSSound.alloc() url =…
est
  • 11,429
  • 14
  • 70
  • 118
0
votes
1 answer

py2app-installed app using pygame fails

I'm bundling a pygame app using py2app. The bundling works and the resulting bundle runs on my mac just fine. It also used to run on another person's mac just fine. However, recently I've started getting this error (from the console) when trying to…
Claudiu
  • 224,032
  • 165
  • 485
  • 680
0
votes
1 answer

How to make a status bar icon with retina support in Python?

I make an icon using these codes: self.statusbar = NSStatusBar.systemStatusBar() self.statusitem = self.statusbar.statusItemWithLength_(NSVariableStatusItemLength) self.image =…
afon
  • 31
  • 5
0
votes
2 answers

Is it possible to use iTunes events in Python via PyObjC?

I'm developing my first app on python for OS X (and also generally on python) and i faced the problem… My current script parses sounds from iTunes and prints it in to the window. It looks like this from Cocoa import * from Foundation import * from…
user1692333
  • 2,461
  • 5
  • 32
  • 64
0
votes
3 answers

Program that uses Mac status bar

I'm looking to make a program that would have an icon and drop-down menu on the status bar. Are there any resources on how to do this? I'd prefer building it in Ruby, but I also wouldn't mind doing it in Python, C++ or Bash (if possible).
JShoe
  • 3,186
  • 9
  • 38
  • 61
0
votes
2 answers

How can I call CGEventKeyboardSetUnicodeString from python?

The function CGEventKeyboardSetUnicodeString takes a UniCharCount and const UniChar unicodeString[]. I am having trouble figuring out how I can call this from python using pyobjc. Ideally, I'd like to be able to just pass in a python unicode string.…
Hesky Fisher
  • 1,145
  • 7
  • 14
0
votes
2 answers

Running PyObjC application (built in Xcode) on previous version of Mac OS?

I am using Xcode to build a PyObjC application. The app runs fine on the build machine (running 10.8) but crashes on startup on a machine running 10.6, because it fails to find the Python 2.7 installation. Fair enough -- the preinstalled Python on…
ekl
  • 1,052
  • 2
  • 9
  • 24
0
votes
1 answer

Setting up Info.plist file in Python and PyObjC, without Xcode

I am writing a relatively simple helper application in Python using PyObjC. Because of its simplicity (one main file with some helper functions in another file), I am not using Xcode for development. However, I would like to set some Info.plist…
ekl
  • 1,052
  • 2
  • 9
  • 24
0
votes
2 answers

Turning NSDictionary into a plist string, not writing it to a file, in PyObjC

Fair warning: I know absolutely no Objective-C. I am using the Foundation module for PyObjC. I have a dictionary which I use to create an NSDictionary. An example: from Foundation import NSDictionary d = {'a': 1, 'b': 2, 'c': 3} nsd =…
2rs2ts
  • 10,662
  • 10
  • 51
  • 95
0
votes
1 answer

How to correctly construct a main menu in PyObjC?

I am programmatically creating a menu in PyObjC with this hierarchy. NSMenu (setMainMenu on NSApplication) - NSMenuItem(1) - NSMenu: "App Name" - NSMenuItem(1) - NSMenuItem(2) ... - NSMenuItem(2) - NSMenu: "File" - NSMenuItem(1) …
Alex B
  • 82,554
  • 44
  • 203
  • 280
0
votes
1 answer

pyobjc as a subprocess communicating with main process via pipe doesn't work

I'm trying to send signals from my pyobjc gui (a menu in the osx status bar) to the main process of my app. Specifically, I'm running the gui wrapped in a class and this inside a process, and I'm trying to send messages from the gui to the main…
nflacco
  • 4,972
  • 8
  • 45
  • 78