trouble with scripting bridge

I've got iMac (Retina 4K, 21.5-inch, Late 2015) with Mojave installed and I have Xcode Version 10.1 (10B61) installed also. My application is for my own use and is developed to run on my iMac under Mojave Version 10.14.1 (18B75).


The program generates various reports at user request and it allows the user to send a copy of any report to a designated recipient. This is implemented by using scripting bridge to create an email message, fill in values for the sender, recipient, subject, and message content. In addition the user can supply an array of strings that, all appearances of any one of the strings that may appear in the text of the message will appear in BOLD.


The process requires creation a MailOutgoingMessage. Before calling methods to manipulate properties of the MailOutgoingMessage, it must be added to the outgoingMessages container of the mailApp. However

[[mailApp outgoingMessages] addObject: emailMessage];

followed by:

emailMessage.sender = [[NSUserDefaults standardUserDefaults] objectForKey:@"SNS_EmailSender"];

generates the error:

[General] *** -[SBProxyByCode setSender:]: object has not been added to a container yet; selector not recognized [self = 0x600000d3bd20]


In fact the following code:


NSLog(@"[mailApp outgoingMessages] <%ld>",[[mailApp outgoingMessages] count]);

[[mailApp outgoingMessages] addObject: emailMessage];

NSLog(@"[mailApp outgoingMessages] <%ld>",[[mailApp outgoingMessages] count]);

present the following output in the log:


[mailApp outgoingMessages] <0>


[mailApp outgoingMessages] <0>


With the following code:


NSLog(@"emailMessage <%ld>",emailMessage);

[[mailApp outgoingMessages] addObject: emailMessage];


NSLog(@"emailMessage <%ld>",emailMessage);

the log reads:

emailMessage <<future 'bcke' with properties…

emailMessage <<future 'bcke' with properties…


These results make me think that a failure has occurred for the call:

[[mailApp outgoingMessages] addObject: emailMessage];


Is this a reportable bug?

Accepted Reply

First up, I’m not sure what’s going on with your Scripting Bridge code. Alas, I don’t have time to look at it in the context of DevForums. If you want to pursue that angle, my recommendation is that you open a DTS tech support incident and I, or one of my colleagues, can help you out officially.

Note DTS is currently closed for the US Thanksgiving holiday, so you won’t hear back from us until next week.

However, in your shoes I’d use a different approach for this. In my experience Scripting Bridge is rather low-level, and it’s much easier to do this a job like this using AppleScript. Thus, I’d embed an AppleScript in my app and then call that AppleScript via

NSAppleScript
.

The tricky part in doing this is passing parameters to your AppleScript. I posted some snippets on how to do this in this thread.

Sorry it’s in Swift but that’s what the other developer was asking for. The good news is that this API is easier to use in Objective-C. If you have any questions about converting it over, post them here.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

First up, I’m not sure what’s going on with your Scripting Bridge code. Alas, I don’t have time to look at it in the context of DevForums. If you want to pursue that angle, my recommendation is that you open a DTS tech support incident and I, or one of my colleagues, can help you out officially.

Note DTS is currently closed for the US Thanksgiving holiday, so you won’t hear back from us until next week.

However, in your shoes I’d use a different approach for this. In my experience Scripting Bridge is rather low-level, and it’s much easier to do this a job like this using AppleScript. Thus, I’d embed an AppleScript in my app and then call that AppleScript via

NSAppleScript
.

The tricky part in doing this is passing parameters to your AppleScript. I posted some snippets on how to do this in this thread.

Sorry it’s in Swift but that’s what the other developer was asking for. The good news is that this API is easier to use in Objective-C. If you have any questions about converting it over, post them here.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

When I first implemented the emailing feature in 2011, using Scripting Bridge, it took me weeks to get it to work. At the time I also investigated doing it with AppleScript but found that inscrutable. I invested more weeks in 2015 to implement bolding in the email content; when I succeeded at that I wanted to award myself a PhD in computer science. It all fell apart with the new releases of macOS Mojave and Xcode.


I've spent two weeks trying to determine what caused the failure and it seems that '[mailApp outgoingMessages]' returns a proxy object that responds to 'addObject: emailMessage' but does not actually add the message to a container. During the search, I also re-investigated the AppleScript approach. I have resigned myself to following your advice...I guess I need the challenge. Thanks for your time and advice.


I also investigated Swift when it was first introduced and my reaction was: "WHAT is THAT?" In the meantime it is nearly impossible to find a helpful post in objective-C, so it is now more like: "What is that? hmmm."


By the way, my first 'computer' language was 'WiringBoard' for IBM's 407 Accounting Machine (Do not fold, bend, spindle or mutilate.) IBM https://en.wikipedia.org/wiki/IBM_407 if you like.


Share and Enjoy


let myEmail = "slowerlowerbob" + "@icloud.com"

Don't waste your time on ScriptingBridge—it's defective by design and embarrassingly unfit for purpose.


AppleScript is also a PITA to work with, due to well-intentioned but misleading syntactic obfuscations, but at least its Apple event support works right. Your best solution is to get call AppleScript handlers from ObjC/Swift via the AppleScript-ObjC bridge. Here's a quick HowTo:


appscript.sourceforge.net/asoc.html


I recommend you start by writing the AppleScript portion in Script Editor (or Script Debugger, which is a lot better), so you can easily develop and test it, then wrap that code in a script object handler for ASOC and save it as an .applescript file for inclusion in your Xcode project. For assistance in learning your way around Mail and getting your AppleScript to work, try the AppleScript Users mailing list or Late Night Software forums. While most AppleScript users are not professional developers, they do know their stuff where application automation is concerned and are always keen to help.


--


p.s. The key to understanding Apple event IPC is realizing that it is *not* OOP, it's RPC plus simple first-class relational *queries*. It has far more in common with SQL+RDBMSes than anything else. You aren't messaging individual objects as in ObjC+Cocoa, or JS+DOM. You're sending a remote procedure call, some of whose arguments are queries identifying the data to manipulate (represented by the app's CocoaScripting View-Controller layer as an idealized nominally tree-shaped relational graph, aka "Apple Event Object Model"), and it's up to the app to work out the rest.


How well this works in practice varies from app to app, depending on how well the app developer understood the concepts and how much work they were willing to put into it (as with building high-quality graphical UIs, building high-quality automation UIs is a lot of hard work). Alas, Apple's own documentation is vague and unhelpful at best, and horribly misleading at worst; still, that this technology's endured despite all the misconceptions and neglect says something for just how powerful and productive it really is when it does work right.