how to create a bootable macOS installer

If you are preparing to install macOS on multiple computers, one of the things that can make your life simpler (and the waiting shorter) is a bootable USB installer.

The idea of the installer is that you only need to download the macOS Installer.app from the App Store once. Usually, when you run the installer after downloading it, it’ll delete itself and you have to go through the whole download process again on each machine or disk that you want to install macOS onto. By making a bootable USB drive, you simply plug the drive in to your mac, launch the installer app and tell it where to install the OS. You can repeat this as many times as you like as the installer will remain safe on your USB.

There are various ways to make a bootable USB installer, but they all involve the same process:

1. Download the macOS Installer from the App Store.
2. Run the createinstallmedia command from the Terminal, an AppleScript or a helper app.
3. Reboot your mac, choosing the newly created USB as the startup disk.
4. Run the installer.app from the USB.

Step 2 is where the fun is. The createinstallmedia command can be tricky to get right, particularly if you’re not familiar with working on the command line. For those of you that are, follow Apple’s instructions here.

For a little more convenience, I wrapped all that inside an AppleScript which will first ask you for the location of the installer, then ask you to choose the USB target.

For maximum convenience, I also wrote a free little Swift app I’ve dubbed ‘Boot Buddy‘ (cos “Create bootable macOS Installer Drive.app” just didn’t quite have the right ring to it..!) that will present the whole thing in a neat little user interface. Three clicks, more or less, and you’re done.

Boot Buddy doesn’t require an admin password to install, but you do need to provide an admin password to actually create the bootable installer as the createinstallmedia process has to be run as root. Boot Buddy doesn’t see or use this in any way whatsoever other than to start the createinstallmedia process or to cancel it (if you choose to do so); authorisation is handed off to macOS to take care of.

Boot Buddy requires macOS 10.11 or higher and can create bootable USBs from Mavericks, Yosemite, El Capitan, Sierra and High Sierra installer apps.











Share and enjoy! 🙂


how to remove adware from your mac




Despite removing MacKeeper, I occasionally get reports from DetectX users who find that when they open their browser, MacKeeper is still haunting them. If your browser is popping open with images like the ones above, then like those users, you’ve got an adware infection.

It sounds nasty, but it’s more annoying and intrusive. It also may signal that your mac has been compromised in other ways by malware such as Pirrit, which has the capability to do more than just harrass you through your browser.

The easy solution to adware is to run my free app DetectX. If you find the problem isn’t solved, you can also send me the DetectX report and I’ll solve it for you, for free.

If you like rolling your sleeves up yourself, then follow this procedure:



1. Preparation
As you should always be running with a recent backup anyway (right, folks?) be sure to do a TM backup or clone before you start in case anything goes wrong. Do not ignore the necessity for a backup. If you don’t have one, stop now and get one.

You’re going to want to hunt down the adware in a few places. Be careful not to delete anything, but instead move suspicious items to a folder on your Desktop so that you can return them to where they came from if they are innocent. Create a new folder on your Desktop called ‘Quarantine’ for this purpose.

You’re going to want to keep a note of what you find and where you found it, so have a text editor like BBEdit or TextEdit open while you work. Save this file in your Quarantine folder, too.

When you find a suspicious item, an easy trick is to drag the suspect first into the editor to copy its path, and then drag it into your makeshift ‘Quarantine’ folder to move it. To copy the path in this way, use a plain text format in TextEdit. If you’re using BBEdit, command-drag the item. For moving to your Quarantine folder, you’re going to need to use ‘Command’-drag and supply an Admin password for the move if the item is outside of your Home folder.



2. Local and User Domain Libraries
Note these are two different libraries, but I’m assuming that if you’ve elected to follow this “roll your sleeves up” procedure, you already knew that. If you didn’t, I strongly suggest you reconsider trying to do this yourself. Messing under the hood requires a certain minimum level of experience and knowledge to avoid borking your entire system.

Assuming that all warnings and caveats so far have been heeded, you’re ready to inspect the /Library and ~/Library folders. Treat as suspicious anything at the root of /Library that begins with a lower case letter, particularly if it is an executable. Aside from the hidden .localized file, Apple don’t put anything at the root of /Library that begins with a lower case letter, and responsible 3rd party developers don’t either. If you find anything like that and you don’t know what it is, make a note of it (don’t move it yet).

At this point I’d love to be able to give you a list of file names to look out for, but I’m afraid we’re talking in the thousands if not more. A lot of this adware creates its own unique names on install by randomly choosing words from the /usr/share/dict/words file. Some of them disguise themselves as Apple files, like com.apple.morkim.plist and others disguise themselves by hiding themselves from the Finder (so ideally you want to be doing this on the command line, or at the very least use the Finder with invisible files showing).

The good news is that a lot of this adware is fairly obvious when you look at it. Move into the local (not user) Library’s LaunchAgents and LaunchDaemons folders and inspect the items in there. Move items that have random dictionary word names like ‘Bolshevik-remindful’ or gibberish concatenations of consonants and vowels like ‘com.xpbbptejonfy.plist’. If you’re not sure, open the plist (you can cat or sudo cat it if you’re in the Terminal) and see what executable it refers to. If that refers to a path to some similarly named binary you’ve never heard of, go check it out and see what it is. If in doubt, use Google your favourite search engine to search for that name on the web and see if its legit. Anything legitimate will be easy to find a reference to on the web. Anything that fails these tests should be moved to your Quarantine folder. If you find anything that refers to a folder or file you made a note of earlier in the root of /Library, then move both to your Quarantine folder.

After that, you’ll want to move on to your ~/Library/LaunchAgents folder, and follow the same procedure. Any items in here should refer to an app that you recognize and regularly use. Items with names that mispell words like ‘update’ and ‘download’ are dead giveaways as adware.

Adware plist files in here will typically refer to something funny sounding in your ~/Library/Application Support/ folder. Any apps found in the Application Support folder or subfolders should be treated as suspicious. Again, check the name through an internet search if you’re in any doubt, but since this is stuff in your user domain, really anything you don’t recognize shouldn’t be there anyway.



3. Browser Extensions
While you’re in the user Library, go check on what is in Safari/Extensions folder. You should see an Extensions.plist and only the safariextz files that refer to Extensions you use, if any. Fire up Safari, and check in the Preferences’ Extensions tab to uninstall any that you don’t use. If you use other browsers, use the Tools menu to inspect Extension or Add-ons, again removing any that you don’t use.



4. Restart and test
It’s time to restart your mac. After restarting, you’ll need to reset your browser to its default state. First, hold down the shift key while launching the browser from the Dock.

If you get redirected to an adware page or still get a pop up, clear your browser’s default settings. Although adware can no longer easily alter Safari’s defaults, you can check that your home page is correct in Safari’s Preferences. You can empty history and caches from the Safari menu and the Develop menu, respectively. For the latter, click ‘Advanced’ in Safari’s Preferences and check the ‘Show Develop menu in menu bar’ box at the bottom to enable the menu.

To reset Chrome and chromium based browsers to default settings, see:

https://support.google.com/chrome/answer/3296214

For Firefox, see

https://support.mozilla.org/en-US/kb/refresh-firefox-reset-add-ons-and-settings



Fixed it or not?
If you correctly identified and moved the adware, you should be all good. Depending on what you moved and from where, you might want to hang on to the items in your ‘Quarantine’ folder until you’re sure everything is working correctly. If you accidentally moved something you shouldn’t have, you’ll likely soon notice something isn’t working like it used to. Use your notes or your backup to undo the damage. When you’re sufficiently confident that everything in your Quarantine folder is definitely badware, move your notes to somewhere else if you wish to keep them for reference (I’d appreciate a copy of them, too :)) and delete your Quarantine folder.

If things didn’t work out, don’t despair or feel bad. Adware is complex, and the simple DIY guide above won’t cover all the cases. There are other places adware can hide, but it takes a lot of experience to track it all down. If you can’t solve the problem yourself, you can always check your mac with DetectX or contact me through DetectX’s Help menu item ‘Report a Problem to Sqwarq’ and have me do it for you (and no, I don’t charge for this service).



Good luck! 🙂

Related posts: Terminal tricks for defeating adware


how to display wifi name (ssid) in menu bar



If you’re one for visiting coffee shops and other places with public networks, you might have an interest in today’s Hammerspoon tip.

This little code added to your config file will display the name (SSID) of the currently connected Wifi network in your menu bar. Whenever the Wifi network changes, the name will automatically update so you can always see at a glance that you’re connected to the Wifi network that you think you are.

Playing around with that unusually long number (between 2147483644 and …647) will move the SSID name along the icon bar. Set it to the default ‘1000’ if you want macOS to decide where it should be.

wifiWatcher = nil
function ssidChanged()
local wifiName = hs.wifi.currentNetwork()
if wifiName then
wifiMenu:setTitle(wifiName)
else
wifiMenu:setTitle("Wifi OFF")
end
end

wifiMenu = hs.menubar.newWithPriority(2147483645)
ssidChanged()

wifiWatcher = hs.wifi.watcher.new(ssidChanged):start()







Enjoy! 🙂



Further Reading
More fun with Hammerspoon
Get automated with Hammerspoon

more fun with Hammerspoon

For anyone using Hammerspoon and folder ‘watchers’ to alert them to changes to a given folder, I’ve updated the watcher function I wrote about here

The problem with the simple alert I demonstrated last time is that it only hangs around for a second or two (much less than a Folder Action alert, which takes a couple of minutes to time out). In this updated function, it now also writes a list of the file changes to a (by default) file on the Desktop. The write is an append: if the file doesn’t exist it will create it before writing; if it does exist, it will append the latest changes and date to the file. This way, even if you miss the alert, you’ll always have a record of what files have been added, deleted or modified in your watched folder.

In this example, the folder being watched is ~/Library/LaunchAgents since we want to be aware of any adware, malware or other unsavoury processes being surreptitiously added by, for example, apps we download from the internet. Although there are, of course, many legitimate reasons for apps placing items in here, this folder is prime real estate for attackers as it is one of the locations that can launch processes at log in time without the user’s interaction (or knowledge).

Here’s the code, also available from my pastebin here. A code walkthrough follows.

function writeStringToFileWithMode(aString, aPath, aMode)
local this_file
this_file = io.open(aPath, aMode)
this_file:write(aString)
this_file:close()
end

function myFolderWatch(files)
local str = "Launch Agents folder was modified on " .. os.date() .. " :\n\t"
local this_path = os.getenv("HOME") .. "/Desktop/LaunchFolderModified.txt"
local ignore = "DS_Store"
local count = 0

for _,file in pairs (files) do
count = count + 1
i = string.find(file, ignore)
if not i then
str = str .. file .. "\n\t"
else
if count == 1 then
str = "\n"
end
end
end
str = str .. "\n"
writeStringToFileWithMode(str, this_path, "a")

if string.len(str) > 2 then
hs.alert.show("Launch Agents folder was modified.")
end
end

local aWatcher = hs.pathwatcher.new(os.getenv("HOME") .. "/Library/LaunchAgents/", myFolderWatch):start()



Code walkthrough
The first function, ‘writeStringToFileWithMode’ is just a convenience function. Hopefully the clue is in the name. The ‘aMode’ parameter is either “w” for write(over) or “a” for write(append).

The myFolderWatch function starts off by declaring some local variables.

‘str’ includes the initial line that we want to write to our output file and interpolates the time of the change by calling os.date().

‘this_path’ defines the path that we want to write our list of file names too.

The ‘ .. ‘ in both these assignments is a string concatenator (i.e., like ‘&’ in AppleScript or ‘stringByAppendingString’ in Obj-C).

‘ignore’ is a string that will help us to exclude .DS_Store files from triggering the alert or appearing in the list of file changes.

The ‘count’ variable is an internal var we need in order to eliminate .DS_Store changes when it’s the only change. Lua doesn’t have an easy way to count entries in tables, so we bascially iterate a variable each time through the loop to achieve the same effect.

After that, we have the ‘for’ loop. For loops in Lua are weird (at least for me), as you’ll see that they have this structure for a,b in pair (aPair). I won’t go into why, other than to say its a result of Lua’s table data structure. The '_' here is just a dummy variable for the first parameter. The ‘files’ in parentheses are the list of file names (not file specifiers, you AppleScripters!) that were added, deleted, or modified in the watched folder.

The loop begins by incrementing the count, then checks for the ignore file (.DS_Store). If the ignore file is not found, we then append the filename to the str variable.

If it is found, we check the count. If the count is ‘1’ (i.e., the only change was .DS_Store) we discard the entire str var and replace it with new line character. If the count is more than 1 we don’t do anything to ‘str’. We just ignore adding anything to it all.

At the end of the for loop we add another new line to the string just so our outputted text file looks nice and neat.

Then we call the write function mentioned above, passing ‘a’ (append) for the mode.

Finally, we fire the UI alert on the condition that the string has got more than 2 characters in it (if it didn’t it was just the “\n\n” string from ignoring the DS.Store file).

After the function definition, the aWatcher variable sets up the watcher on the path we want to observe and tells the watcher to start monitoring. It tells the watcher to call our myFolderWatch function when anything happens.

Deploying the code
After editing the config file, remember there’s two steps: i. save the file and ii. choose ‘Reload Config’ from the Hammerspoon menu.



Further Reading:
More details are available about Hammerspoon from the official site here.

My beginners guide with the original simple watcher function is here.


how to reveal hidden users


With malware big in the news again, and evidence that at least one malware variant that targets macOS creates hidden users on the victim’s system, here’s a timely tip on how to check for unwelcome guests.

For this tip, we’re going to use the Terminal, which you can find in the /Applications/Utilities folder. If you’re not a frequent visitor to the land of the command line, you might want to see my 3-part series “Learning the Terminal”.

Regardless, the first thing we’re going to do in Terminal is about the simplest command you’ll ever type: w. Yep, type a single ‘w’ at the prompt and press return.





The w utility is a very quick way to see who’s currently logged on to your system and to ensure that there’s no surprises. You should see a couple of entries for yourself: one as ‘console’ and one as ‘s***’. The first represents a login through the usual Desktop GUI login window; the second is there because you just logged into Terminal. Anybody else logged in either via the command line (like a potential remote user) or the GUI will show up here. Notice that on my machine, there’s another user called ‘Developer’ who hasn’t logged in using the GUI, but is logged in via a command line interface. Note that ‘w’ returns the full user name, not the short one.

While the w utility will tell you if a hidden user is currently logged on, what if there’s a hidden user that isn’t active at the particular time you check? To look for those, we have a couple of options. First, we can use the dscl utility to list all users, and you might be surprised at how many there are:

dscl . -list /Users

Look to the end of that list where the names that don’t begin with an underscore start. ‘Daemon’, ‘Nobody’, ‘Root’ and ‘Guest’ are all standard system accounts, as are all those entries that begin with an underscore. Don’t worry about those. However, aside from those, you should only see names that you recognise. To make things a little easier, we can add another command to the dscl command to filter that list. Try this

dscl . -list /Users | grep -vE ‘_|root|nobody|daemon|Guest’

That should now only return the names of real users. There shouldn’t be any names in there you don’t recognise. In my example, I know the last three, but the first one ‘dev’ isn’t familiar to me. Note that unlike ‘w’, this command returns short user names, and that ‘dev’ looks very much like it’s the same account as ‘Developer’ that I saw earlier.




However, what we have so far is a list of users, not a list of hidden users. To see specifically if any accounts are hidden, we need a longer command:

defaults read /Library/Preferences/com.apple.loginwindow

Normally, when there are no hidden users, this will return the contents of a property list file that may look something like this:

{
GuestEnabled = 1;
OptimizerLastRunForBuild = 31898816;
OptimizerLastRunForSystem = 168494592;
SHOWFULLNAME = 1;
lastUser = loggedIn;
lastUserName = imackim;
}




That tells us that there’s no hidden users on this mac. How so? Because if there were it would return something very different, like this:





We can see not only the list of hidden users, but also that the preference for hiding users has been set to ‘1’ (in plist syntax, ‘1’ means true and ‘0’ means false). Note again that unlike the dscl command above, this returns the account’s full name, not the short user name.

If we’d like to ‘unhide’ that user, so the account appears in the login window GUI and in System Preferences’ ‘Users & Groups’ pane, we’ll need admin privileges. To do that, cut and paste the following into Terminal:

sudo defaults write /Library/Preferences/com.apple.loginwindow Hide500Users -bool NO

Supply an admin user password at the prompt and hit ‘return’, but type slowly as the display doesn’t register your key presses, which makes it easy to fat finger your password.



For the more advanced
We can save ourselves some typing by putting much of this into a script so that we can run it whenever we want. If you’re not familiar with how to create and use bash scripts, take a look here.

Our script will basically do the same as all the commands we listed above (except changing the prefs for Hide500Users) in one fell swoop, and there’s a couple of little twists that I’ll leave as an exercise for the reader to figure out. To save on the typing, you can copy the whole script from my pastebin here.



The script’s output is illustrated in the shot at the top of this post.

Enjoy! 🙂

how to recover from OSX/Dok malware – updated





Last updated: May 10th, 2017 to include Dok.B variant.

There’s been a lot of drama the last few days over a new malware attack on macOS.

There’s FOUR steps to removing the malware.

1. Remove the installed files
Both my apps, DetectX and FastTasks 2 will detect this malware, and remove the appropriate files. For those of you that like to do things by hand, here’s the list of things to look for. You may find some and not others. Any you do find need to be removed:

~/Downloads/Dok.zip

~/Downloads/Dok/Dokument/Contents

~/Library/Containers/.bella/Bella

~/Library/Containers/.bella/bella.db

~/Library/LaunchAgents/com.apple.iTunes.plist

~/Library/LaunchAgents/com.apple.Safari.pac.plist

~/Library/LaunchAgents/com.apple.Safari.proxy.plist

/Library/Containers/.bella/Bella

/Library/Containers/.bella/bella.db

/usr/local/bin/SafariProxy

/Users/Shared/AppStore.app

You might also want to remove the dead ‘AppStore.app’ login item (if it’s still there) from System Preferences | Users & Groups | Login Items.


2. Remove the network proxy redirecting your internet traffic
Victims also need to remove the sneaky proxy that’s redirecting their internet traffic from System Preferences’ Network pane. While this can be done manually, it’s a lot of clicking, especially since you must do it for all services. Easier, then, to use this AppleScript. Note it will need an Admin password.

Get the script from my pastebin (if you copy and paste from a webpage like this and the script won’t compile, get the source from pastebin).


###########################################################
-->> ABOUT
###########################################################
(*

Phil Stokes -- 2017
applehelpwriter.com
sqwarq.com

*)
###########################################################
-->> DESCRIPTION
###########################################################
(*

Turn off the Automatic Proxy Configuration in Network System Preferences.

*)
###########################################################
-->> USAGE
###########################################################
(*

Requires Admin password.
This script was developed primarily as part of a remedy for victims of OSX/Dok malware.

*)
###########################################################
-->> COMMANDS
###########################################################

set services to paragraphs of (do shell script "networksetup -listallnetworkservices")
set autoproxyURL to " 0.0.0.0"
set autoproxySERVICE to ""
repeat with i from 2 to (count of services)
set autoproxySERVICE to item i of services as text
do shell script ("networksetup -setautoproxyurl " & (quoted form of autoproxySERVICE) & autoproxyURL) with administrator privileges
do shell script ("networksetup -setautoproxystate " & (quoted form of autoproxySERVICE) & " off") with administrator privileges
end repeat

###########################################################
#EOF

If you’re not comfortable running AppleScripts, you can do it manually as shown in the screenshot below, but remember you need to go through and do the procedure for every one of your services (Ethernet, Wi-Fi, Bluetooth Pan, etc) individually.






3. Remove the fake certificate
Thirdly, you’ll want to get rid of the fake certificate in the System keychain. In Terminal, search to see if the ‘cert.der’ certificate file still exists:

cd /tmp; ls -alF

If you see ‘cert.der’ listed, then issue the following command in the Terminal window:

security remove-trusted-cert -d /tmp/cert.der

Then, go back to Terminal and do

rm /tmp/cert.der

If not, then try both this

security remove-trusted-cert -D

and check in Keychain Access.app by searching for ‘Comodo’ and looking for a certificate that has the fake Comodo serial number:
00 EB 08 6A 4F 53 BE BA 4D.



4. Remove permissive admin access set by the malware
Back to Terminal for this one, and mind your typing. You don’t want to make any mistakes here…

At the command line prompt, type

sudo visudo

and provide an Admin user name. You won’t be able to see what you type, so type slowly, but at least you get 3 goes at it.

When you’ve got that in correctly, you should see the sudoers file, it’ll look something like this:





Use the arrow key to move the cursor down to the beginning of the line that says

%USER_NAME_HERE%  ALL=(ALL) NOPASSWD: ALL

On your keyboard hit the ‘d’ key twice (i.e, type dd). The line should magically disappear*.

Finally, type

:wq!

(that’s a semi-colon, a lowercase w, lowercase q and an exclamation mark) to save your changes and quit. That’s it!

And with that, you should be done with OSX/Dok malware! 🙂



*If anything went wrong in visudo, you can press the u key once to undo your last action (the ‘u’ key only undoes the last keyboard action, so if you press it twice it’ll undo the undo = redo, so beware!)


how to tell if your mac is too hot





The sound of the fans spinning up on your mac is never a welcome noise, but it’s usually completely normal. Determining the fan speed without 3rd party software isn’t easy, but not impossible:

do shell script "SD=~/.spindump.txt; rm $SD; spindump 1 1 -file $SD; grep 'Fan speed' $SD; rm $SD" with administrator privileges



Copy and paste the above into your (Apple)Script Editor and run it. You’ll need an Adminstrator password.





However, that doesn’t really tell you what you want to know: is my mac too hot or not? Should I do something about it?

Fortunately, we can get a better idea of the mac’s thermal state (and we don’t need admin privs to do it!), with this script:



The script not only reports the mac’s thermal state, but prints out Apple’s recommended advice, if any. Uncomment the last line of the script to get the result in a display dialog box; otherwise, you can just read the result in the results pane of your script editor.

Enjoy! 🙂


Featured Image: Flicker

BackupCam – a dash cam for your mac





The initial release of BackupCam has just gone live over on sqwarq.com.

The idea behind BackupCam is to keep a continuous, rolling video of the last few minutes of activity on your mac, in just the same way as dash cams in cars work.

There’s a couple of scenarios where this might be useful. If you’re working on a project where ‘undo’ doesn’t always work reliably or when you most need it to – Xcode, for example, can often let you get your project in a mess without offering you a clear path as to how you got there or how to get back, short of discarding all changes in a particular file – with BackupCam you’ll be able to see exactly how you got to where you are.

Similarly, BackupCam can also help you to review changes that you may not have noticed at the time – perhaps if you were distracted by something else happening, either on screen or off. This can help both as a security and a troubleshooting tool

BackupCam can record up to the previous 30 minutes activity, so may help you recover something that is missed even by Time Machine or other traditional file backup mechanism.

More details are over on the BackupCam webpage, but I’ll just note here that BackupCam can also be controlled by AppleScript, with all the flexibility that that offers. Here’s a sample script that checks whether the last recording was longer ago than the time interval set in BackupCam. If it is, it kicks off a new recording session:






BackupCam is still in the early stages of development (we’re calling v1 a beta), so please feel free to report any bugs or enhancments you’d like to see. At the moment, it requires 10.11.6 or higher and only records the main display. I plan to add support for multiple displays in a future update.

how to script with Objective-C



Is it me, or is AppleScript experiencing something of an Indian Summer? It seems everywhere I go, people are talking more about macOS automation, AppleScript and even Apple’s curious hybrid syntax AppleScriptObjC (ASObjC).

Of course, some people have suffered miserably at the hands of AppleScript in the past, and even though the thought of scripting with access to Cocoa APIs through Objective-C is tempting, they fear the AppleScript side of it.

If that’s you, bear in mind that AppleScriptObjC isn’t really “AppleScript + Objective-C” at all. It is actually just a dialect of Objective-C that will be accepted in the (Apple)Script Editor and can be run by an instance of the AppleScript component. In plainer English, you can use Objective-C in an AppleScript without any AppleScript whatsoever!

The point of doing so would be that one could package Objective-C code in a .scpt file (or scptd bundle or AppleScript .app), and also mix whatever scripting language you prefer with calls to Cocoa’s APIs.*

The problem that using ASObjC presents anyone familiar with Objective-C is how to translate ‘pure’ Objective-C into the dialect that Script Editor (and other applescript runners like FastScripts, Keyboard Maestro, Automator, etc) can understand. If you use LateNight Software’s Script Debugger for scripting, you’ll already know that the work is done for you by the app’s built-in code completion. If you’re battling on in Apple’s default Script Editor, you’ll need to do the translation manually.

By way of example, then, here’s some original Objective-C, and below it, a translation that would work in Script Editor:

Objective C
NSString *aString = @"hello";
NSString *bString = @" world";

aString = [aString stringByAppendingString:bString];

NSUserNotification *notif = [[NSUserNotification alloc] init];
notif.informativeText = aString;
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notif];


AppleScriptObjC
set aString to NSString's stringWithString:"hello"
set bString to NSString's stringWithString:" world"

set aString to aString's stringByAppendingString:bString

set notif to NSUserNotification's alloc's init
set notif's informativeText to aString
NSUserNotificationCenter's defaultUserNotificationCenter()'s deliverNotification:notif


As you can see, there’s a direct 1-to-1 correspondence, with the 6 statements in Objective-C paralleled by the 6 statements in AppleScriptObjC.

The main peculiarity is the use of possessive word forms and that variable attribution is done by using "set X to Y" rather than "X = Y". Type declaration is done via the idiom 'set <var> to <NSObject>'s <class init method>', which returns an instance of the object just as it would normally. You call instance methods by putting the instance in front of the method just as you would in regular Objective-C (e.g, see line 3 of the examples).

As you can see in the screenshot below showing Xcode and Script Editor, they work in the same way. You’ll notice in Script Editor there is a 'use' statement (equivalent to Objective-C’s ‘import’), and there’s also a whole load of property statements. These latter are peculiar to the ASObjC translation, and don’t have a counterpart in pure Objective-C. All you need to know about these is for each kind of Objective-C object you want to use (NSString, NSArray, whatever*), you’ll want a property statement for it at the beginning of the script. The statement always has the same form:

property <NSObject> : a reference to current application's < NSObject>

I think the best way to think of ASObjC was recently summed up by Sal Saghoian, when he said that ASObjC is “…the ultimate duct tape. You can do anything you want with ASObjC. You own the computer.”

Enjoy! 🙂

*not all Cocoa frameworks nor all Objective-C objects can be bridged to, but pretty much all the most useful ones are available.



Further reading:

– Applehelpwriter’s review of Script Debugger 6
how to quickly toggle Swift Compiler warnings



Picture credits: Top image adapted from MilleniumBirdge by lesogard

%d bloggers like this: