Quantcast
Channel: Kodeco | High quality programming tutorials: iOS, Android, Swift, Kotlin, Unity, and more
Viewing all articles
Browse latest Browse all 4370

Automator for Mac OS X: Tutorial and Examples

$
0
0
Learn how to automate common developer tasks with Automator!

Learn how to automate common developer tasks with Automator!

As a software developer, there are a bunch of repetitive and tedious tasks you have to do almost every day. Wouldn’t it be great if there was a way to automate them?

Well, there is – by using the app Automator that is built right into Mac OX X.

In this tutorial, you will learn how to use Automator through five examples, which show you how to automate five common developer tasks:

  1. Xcode -> Text Editor. Create a service that allows you to highlight text from Xcode, then instantly copy it into a new file in your favorite text editor.
  2. Auto-resize images. Create a folder action that automatically resizes, copies and renames images placed in that folder, which prepares them for iOS development.
  3. SQLite queries. Create a SQL query tool for a selected SQLite file.
  4. CSV -> database. Create an application which allows you to drag and drop one or more CSV files into a database. Like magic, the contents of the CSV will automatically populate the selected table. Doesn’t that sound like a nice feature?
  5. Running shell commands. Create a workflow to run shell commands using variables.

By the end of this tutorial, you’ll have learned how you can improve your workflow to save a lot of time. That way you’ll have time for more important things… like catching a nap! :]

What is Automator?

AutomatorIcon

Automator first became a part of OS X at Tiger (10.4). From the beginning, it has been a way for users to automate repetitive tasks with Apple software, such as Safari, iTunes and Calendar. A number of third-party products, like Photoshop, Microsoft Office and many text editors are also compatible with Automator.

Its design is more user-friendly than writing code or running shell scripts, as it presents the user with an array of built-in options to use, and all within a visual interface. The concept behind the design is to make automation accessible without the need to write code.

What You Need

Here are the things you’ll need for this tutorial:

  • An Apple Computer running OS X 10.4 or later: This tutorial was produced in OS X 10.9 Mavericks, and some of the actions listed in here will not be available in older versions. The UI has had many changes since the original release.
  • Automator: This should be installed by default in OS, and as long as you’ve not moved it you’ll find it in your Applications folder.
  • Sample Files: For the fourth Sample project, you’ll have access to two files you can use, so go ahead and download them now. The second sample application also requires some image files on your Mac in order to test. Any image files will do – yes, even LOLcats! :]
LOLcat

Attribution: michellelevine

Getting Started

Open Automator from your Applications folder on your computer.

You’ll be greeted by a screen that asks what type of document you wish to create:

Screen Shot 2013-12-11 at 2.05.42 pm

You can get a description of how each document type works by clicking on it and reading the description that shows below the box. Later on in this lesson, you’ll learn more some of these types, but for now, select Workflow and click Choose.

You should now see the Automator UI:
Automator UI

  1. The hide/show library button expands and retracts panel 2 and 3. This feature gives you more room to work.


    The Media button gives you access to media files on your hard drive that you may wish to work with, including audio, image and video data. The buttons on the right side of the display allow you to Record a series of actions, such as button clicks, within an application. You can also Run your action workflow from here.

  2. In this section, you can toggle between actions and variables and use the search bar to narrow down the options. You can add an action to the workflow by dragging from 2 to 4 or double clicking the option in 2.
  3. This section tells you additional information about the action or variable selected in section 2. It’s useful because you can see exactly what inputs, options and outputs are available.
  4. This section is your workflow, it allows you to order how you want actions to occur in a procedural, top-to-bottom fashion. You can click and drag an action to re-order the workflow.
  5. In this section you can see a log output and the current variables in use.

For your first example, you’re going to create an Automator workflow to help you export code snippets to your favorite text editor from right within Xcode.

Opening Selected Text in Text Editor

Open up Xcode, select some text, and right click. A pop-up menu will appear, and one of the options in this menu is Services, which has a number of interesting things you can do with that text.

For example, in the screenshot below, if you chose New TextWrangler Document with Selection from the list, it would instantly create a new TextWrangler document that contains the selected text:

Services

Note: If there is no text selected, then the services menu will likely be empty. If you don’t see any services, then you probably don’t have any text selected. Try again!

Now, let’s say you have a favorite text editor that doesn’t have a service created for you already, like the TextWrangler example here. Even if you don’t have access to the internal API, you can still automate the copy/open/paste process by creating your own service using Automator.

Let’s give this a shot! In Automator, close your current document and create a new document with File\New. Then select Service and click Choose.

Then look for this box, which should appear at the top of your workflow pane:

automator workflow input

Since you selected a service, it will look for a usable variable to pass into the workflow. If you have a look in the first dropdown box, you’ll see a list of all the types of media that a service can handle:

variable types

For this project, leave it on text. In the second box, choose the applications you want the service to be available. Leave Any Application checked to allow text from anywhere to display this service.

Note: For future reference, you can restrict which applications can use a service in this same dropdown menu.

To do this, Other… from the drop down list and then locate the app you want from the Applications Folder.

Screen Shot 2013-12-15 at 10.10.02 pm

Make sure the Library is visible on the far left and Actions is selected:

Screen Shot 2013-12-15 at 10.09.32 pm

Click Library from the left column to un-filter the list of actions.

Type Copy into the search box to narrow down the list:

actions library

Find Copy to Clipboard in the list, click down on it and drag it from the actions library to the workflow area on the right.
workflow with action

Notice the triangle just below the entire selection dropdown field?
Screen Shot 2013-12-14 at 7.10.44 pm

This represents an output and data passing from one action to the next. The text collected by the service is passed onto the Copy to Clipboard action. When this service runs, it will copy the selected text to the clipboard.

Go back to the search box for our library and type launch.

Select Launch Application from the list and drag it to the right under your Copy to Clipboard action.
Screen Shot 2013-12-15 at 10.13.21 pm

This action has configurable settings; you can select which application to launch by using the dropdown list. This example uses TextWrangler (download it for free), but feel free to choose your favorite text editor instead.

workflow shot 2

So now your text is on the clipboard, and you’ve launched the application. What’s next? Now you just need to paste the text into the application.

But not too fast! You have a problem. There is no action called Paste from Clipboard. What are you going to do?

One option is to record the events of pasting text into TextWrangler, but why would you do that when you can use AppleScript?

Search and drag Run AppleScript from the actions list to the current workflow below Launch Application.

Note: While it would be fun to take a deep dive into AppleScript, it’s outside the scope of the topic. So, this course will cover some basic code examples, which will hopefully whet your appetite and inspire you to learn more about this useful feature.

In the Run AppleScript box replace the code with the following:

tell application "System Events" to keystroke "v" using {command down}

Your workflow should now look like this:

Untitled

The above is not a paste function, you’re telling the system to press command-v (which has the result of pasting the copied text into your text editor).

Before you test this out, it’s a good idea to make it more reliable, and there are a few ways to do this. Modify the code to the following:

tell application "TextWrangler"
	activate
	delay 1
	tell application "System Events" to keystroke "v" using {command down}
end tell

Be sure to replace the text “TextWrangler” with the name of the text editor you chose.

This makes sure sure your chosen text editor is running and is the active window before pasting your text. Specifically:

  • If you want to give an application multiple commands, you can combine them in a tell statement, as shown in the above code.
  • First, you tell your text editor to activate (become the active window). If the application is closed this command will open it, so you may remove the Launch Application action if you wish.
  • Delay tells the action to wait before proceeding to the next line. The number after the word delay represents the number of seconds to wait.

Now go to File, Save and select the name you wish to appear in your services list. In this example you can use “Open in TextWrangler”.

As services run automated procedures over the selected item(s), so it’s important to name them in a way that describes the action they perform. You’ll see a lot of actions start with “Add to” or “Open In” — some even clarify further by adding “with selection” to the end.

Trying it Out

Open up Xcode, create a new project (or open an existing project) and select some text.

Next, either right-click on the text or go up to the menu bar, select Xcode. In the Services menu you should now see your new service. Go ahead and run it.

Screen Shot 2013-12-12 at 11.47.43 am

If it all goes right, you should see your selected text in your text editor:

Screen Shot 2013-12-12 at 11.48.08 am

Note: If you chose a different text editor, you might have to instruct the text editor to create a new document before pasting the code. Here’s what I had to do to get this script to work with TextEdit:
tell application "TextEdit"
	activate
	delay 0.5
	tell application "System Events" to keystroke "n" using {command down}
	delay 0.5
	tell application "System Events" to keystroke "v" using {command down}
end tell

This makes a new document with Command-N, waits half a second, then pastes the text into the new document. Experiment with what best suits your needs!

So that’s how you can automate copying and pasting into application. Next up, you’ll learn how to use Automator to rename and auto-resize a batch of images for iOS projects.

Batch Renaming and Resizing Images

Apple woke up to the fact that preparing images for iOS development can result in poor quality images, so they have included the asset catalog in iOS 7 to make it easier to track image assets.

Note: To learn more about the asset catalog in iOS 7, check out Chapter 9 in iOS 7 by Tutorials, “What’s New in Xcode 5.”

You still need to create all of the required images, and it’s still a best practice to follow the previous naming conventions. What’s cool about Automator is that you can delegate the tedious task of processing and renaming to an automated action. Imagine how much easier image processing will be!

If you’ve been thinking about getting an app to help you resize and rename files, don’t do it! You can easily make one yourself with Automator.

There are a few ways to do this, but try using Folder Actions first. They allow you to set up a folder that runs a specific workflow on every file placed within.

Folder actions can revolutionize your workflow. Here are some examples of how you can use them:

  • Drag and drop a single file into a folder set up with an action of your choosing, and the workflow will automatically apply to that file.
  • Select multiple images, drag and drop them onto the folder and the workflow will work through each file in a loop sequence.
  • Use this folder as your default save location for files. This way you have a “set and forget” solution, so your files will always be prepped and ready to use when you go looking for them.

Creating a Folder Action

Open Automator and select New to create a new project. Select Folder Action and click Choose. and you’ll see the input at the top of the workflow is different again:

Screen Shot 2013-12-12 at 4.59.40 pm

Here you can choose the folder to apply this folder action to.

From the dropdown menu select Other… and go to the location you want your folder. If you don’t have a location in mind, just create it on the desktop for now. To do this, select New Folder and call it Prepare Images for iOS.

Open this folder via finder and add two more folders in it, one called Processed the other called Processed @2x, this is where photos will go after processing.

Your folder structure should now look like:
Screen Shot 2013-12-12 at 12.25.37 pm

Go back to the Automator project and add the Copy Finder Items action from the library to the workflow. Remember to use the search box if you’re having trouble finding it.

In the To: dropdown list select Other… and locate the folder named Processed @2x.

Your workflow should now look like this:

Untitled3

This moves the files from the Prepare Images for iOS folder to the Processed @2x subfolder.

Next, you’ll rename the file so that it has @2x at the end of the file name but before the file extension.

From your library add the action called Rename Finder Items. Make sure the dropdown box at the top of the action is set to Add Text. In the Add: area type @2x and set it to After Name. Note that there is a small text label below this section which gives you an example of how the filename will look after this modification:

Screen Shot 2013-12-12 at 5.10.09 pm

Go to File then Save, call it Prepare for iOS.

This is all you need do for full resolution images, but you’ll also need half resolution versions with the original filename.

Note: You can create multiple workflows and assign them to the same folder, and even select which actions to do for a given batch.

To try this out, go to your desktop and right-click the Prepare Images for iOS folder, go down to Services and select Folder Actions Setup…

Below is an example of a folder set up to run 2 workflows:

Screen Shot 2013-12-12 at 6.35.42 pm

Use the checkboxes to enable or disable folder actions, as well as the individual scripts. How simple is that?

But don’t get ahead of yourself! Work through this next exercise to make it work with a single workflow, and focus on learning about variables.

Using Automator Variables

Have a look at your variables tab, and you’ll see a bunch of standard information which can be collected from the system: date and time, system information, random numbers etc. You can drag each of these onto the workflow so its value is accessed via the output.
Screen Shot 2013-12-12 at 6.42.43 pm

Next, you’re going use a variable to store filename of the original image passed into the workflow, so that you preserve the original file.

Back in Automator in your current folder action project, add the Set Value of Variable action to your workflow at the top above Copy Finder Items.

Click New Variable… from the dropdown list and name it Original Input. Your workflow should now look like this:

Screen Shot 2013-12-12 at 6.50.28 pm

Now that the original filename is stored in a variable, you need to retrieve it from the variable after finishing with the @2x version.

Find Get Value of Variable from the actions list, drag it onto the bottom of your workflow, and make sure the Variable selected is Original Input.

All actions on the workflow return an output. The output of the “Rename Finder Items” step is the array of renamed files. However, in this case you don’t care about those filenames and just want to work with the array of files you squirreled away in the Original Input variable earlier.

To fix this, you can disconnect an action from previous outputs. Simply expand the Options of the Get Value of Variable and select Ignore this action’s input. When you make this change you’ll notice that it’s no longer connected to the output of the above action.

Screen Shot 2013-12-12 at 6.57.24 pm

Now you can finish this up by adding another Copy Finder Items action under the Get Value of Variable action and setting it to your Processed folder.

Then add a Scale Images action to your workflow, set it to scale by percentage and adjust the value to 50%.

Screen Shot 2013-12-12 at 6.59.26 pm

Go to File, select Save. You’re done – let’s try this out!

Find some images you can try out (such as that LOLcat image from earlier) and drag and drop them into the Prepare Images for iOS folder.

In your Prepare Images for iOS folder you can see the file(s) you dragged in:

Screen Shot 2014-01-24 at 11.03.45 AM

Have a look in your Processed @2x folder you’ll find the same images, but renamed with @2x – indicating the kitty is ready for retina. Meow.

Screen Shot 2014-01-24 at 11.04.29 AM

In your Processed folder, file names are unchanged. If you look at the dimensions you’ll find they are half the original dimensions:

Screen Shot 2014-01-24 at 11.04.33 AM

Well done! You now have full control over your image assets. Besides working with Retina, you can use this same process to prep images for iPad, iPhone and iWhatever. To do this, all you need is the ration or change for each device, and a single high resolution image.

Beyond that, you can even automate actions for photo manipulation. For example, you can add filters, like posterize and vignette. If you’re working on an image-rich project, look into using Automator – it’ll probably save time and sanity!

Perform SQL queries on an SQLite file using Automator

If you need to use a database within your app, the most likely format is SQLite. It’s light and compact, and is commonly used by Core Data. When you’re developing cross-platform apps, SQLite works great on Android. Using Automator can make managing the database more efficient.

Normally, you’d probably need buy an app to do tasks like set up sample data in your SQLite file, run a query to get data out of your SQLite database, or perform table maintenance. But not after you learn to use Automator, which can make performing SQL functions and queries on your SQLite databases easy!

To start, you’ll make a simple workflow which will allow you to run any queries you want on a selected database.

Note: If your library doesn’t have a Developer Tools category, it’s likely you don’t have Xcode installed on your Mac. Please install Xcode before you proceed with this part of the tutorial, as it uses Developer Tools.

In Automator, select File from the menu bar and then New. This time, select Workflow as the type, as you’ll only be running it from Automator.

Screen Shot 2014-01-24 at 11.19.02 AM

Since there is no file passed into the workflow at the beginning, you’ll have to get the file. In this example, you’ll be using the DataStore file from a Core Data project. Note that one is included in the sample files for this tutorial.

Note: If you would like to view your own Core Data database file, one easy way to get it is to enable Application supports iTunes file sharing in your apps Info.plist file. Run the app on your device and you should then see your DataStore.sqlite file from your iTunes fileshare. Save it to your desktop and you’re ready to go.

Drag the Get Specified Finder Items action onto your workflow, select Add and find the DataStore.sqlite file.

Screen Shot 2013-12-13 at 8.14.55 am

Now that you have the file in your workflow, you can start working with it.

Drag a Execute SQL action onto your workflow. This can run any SQL you want on the database.

Note: If you’re unfamiliar with SQL (Structured Query Language) and plan on using SQLite files a lot, then I would recommend trying w3schools SQL tutorial and our .

In the SQL commands section, you can run as many SQL commands as you want, separated with ;. For now though, you’ll run a query which will work on any Core Data database.

SELECT * FROM Z_PRIMARYKEY;

When this action runs, its output will be the result of the query. In this case it should contain one line for each entity model you’ve set up.

Now what you need is to be able to see the results returned by the query.

The “View Results” Action

So far you’ve made a lot of assumptions based on what you believe the current variables being passed to the output to be. If you’re working on much bigger workflows, or need instant feedback of what the current output is then this action is useful.

Drag the View Results action from the library onto your workflow under Execute SQL. You don’t need to put anything into this box as just a place to display information.

Click the Run button at the top right to see what happens.
Screen Shot 2013-12-13 at 8.42.51 am

You can now see the results of the SQL query in plain text.

Feel free to experiment with the View Results action to fully understand what the output of each action is. For example if you were to drag it above Execute SQL, the result would be something like:

(
"/Users/northy/Desktop/DataStore.sqlite"
)

The output of the Get Specified Finder Items action will be the filepaths of all files included in the action.

Note: Use with care, as it’s not unusual for View Results to change the format of a string before it reaches output. It’s also possible to just use the Results section at the bottom of each action.

Making a standalone application to add data from CSV to Database

There may be occasions where you need to add sample data to a database or multiple databases — like when you’re making a demo or testing a new app. You could use a Folder Action to handle this, but the sample project requires you to work with multiple files of different natures, specifically a CSV file and a SQLite database. This can become confusing when using a Folder Action, so for this lesson you’re going to make an Application.

Applications are just like every other application in your applications folder. They are single files which can take an input by drag and dropping a file or folder onto them:

dragndrop

The application you’re going to make takes a CSV file as its input (found in the sample files provided), and adds the data to the SQLite database you were just working with.

You’ll start by creating a table in the database for your sample data. The idea is your app will be a names database for smart people, so you need a table to store names. You’ll create the table by running a SQL create table query in the workflow you just created.

Replace the SQL in the Execute SQL action with the following:

create table people(firstname varchar, lastname varchar);

This query will create your table with the name people and will contain two fields: first name and last name.

The feedback you get in your view results action won’t tell you much. The green tick means there wasn’t any errors, so you can assume the table was created correctly:
Screen Shot 2013-12-13 at 4.35.31 pm

Now that you have added the People table to your database, you can create an application to automate adding CSV data.

In Automator, go to File then New from the menu bar. This time, select Application.

The file you’re going to pass into the application is a CSV file (comma delimited data files). They are text files where each line represents a new row of data and a comma separates each field. The one located in the sample file looks something like this:
Screen Shot 2013-12-13 at 4.46.10 pm

The CSV file will pass in as the first output to connect to. Next, you need to add a few actions to format the text, convert it to SQL and store it in a variable.

The first action to add is Combine Text Files:
Screen Shot 2013-12-13 at 4.51.38 pm

This is necessary in case you drag multiple CSV files into the application; it will loop through the contents of each text file and combine everything into one. Also, the file you drag into the application passes in its file path, so you want to make sure you’re getting the file’s contents.

Next, drag onto the workflow a Convert CSV to SQL action. You’ll see a segmented control which allows you to edit the text before, per row and after. Enter the following SQL on each:

Before:

begin transaction;

Per Row:

INSERT INTO people (firstname, lastname) values ("%{1}@","%{2}@");

After:

end transaction;

You have now written SQL instructions to insert rows into your table for each line in the CSV file, or, combined CSV data.

If you were to run this action on the sample names.CSV file, the resulting SQL will be as follows:

{"begin transaction;
INSERT INTO people (firstname, lastname) values (\"Ray\",\"Wenderlich\");
INSERT INTO people (firstname, lastname) values (\"Adam\",\"Burkepile\");
INSERT INTO people (firstname, lastname) values (\"Charlie\",\"Fulton\");
INSERT INTO people (firstname, lastname) values (\"Matt\",\"Galloway\");
end transaction;
"}

Next, add a View Results action to your workflow. While you don’t need to see the results at this point, you should be aware that at the time of creating this tutorial, there is a bug in the current version of Automator (2.4) where the variables may react strangely to certain text files. Having a View Results action seems to mitigate the bug.

Now add a Set Value of Variable action, create a new variable called SQL Statements.

The workflow should now look like:
Screen Shot 2013-12-13 at 5.10.13 pm

Now what you need to do is set it up so the user (which will be you in a moment) picks a database for the SQL, then apply the SQL to the chosen database.

Add an Ask for Finder Items action to your workflow, this will allow you to select the database where you wish to run the SQL statements.

Change its options to ignore this action’s input, change the prompt to Choose a SQLite Database: and set Start at: to a default location where you save SQLite files or leave it on Desktop.

Screen Shot 2014-01-13 at 6.54.41 pm

Drag a Set Value of Variable action underneath it and don’t bother setting the variable now; you’ll come back to it later.

Add a Get Value of Variable action, set the variable to SQL Statements and options to Ignore this Action’s Inputs.

Add an Apply SQL action, select New Variable from the Database dropdown list. Name the new variable SQLite Database.

Screen Shot 2013-12-15 at 11.12.48 pm

Now you can go back to the Set Value of Variable action (third action from the bottom of the workflow) and change it to SQLite Database.
Screen Shot 2013-12-13 at 5.41.53 pm

Congratulations, you’ve now made an application! Save the file somewhere on your Desktop for easy access.

To recap the workflow you just created:

  • You first bring in all CSV files dropped onto the application.
  • You then combine them into a single text string, and convert it into SQL statements, and save it in a variable.
  • Next, you ask the user to supply a database file and save the path to a variable.
  • Finally, you pass your SQL statements into the Apply SQL action, which runs on the provided SQLite file.

To test it out, drag and drop your names.csv file on top of the application you just saved.

dragndrop

It will then ask you to supply an SQLite database:
Screen Shot 2013-12-13 at 5.51.16 pm

That’s it! The process is done. How can you check that it has worked?

Go back to the previous workflow (the one you used to create the table) and change the SQL to:

SELECT * FROM people;

Then run the workflow:

Screen Shot 2013-12-13 at 5.53.55 pm

Look at you! You now have experience with all of the available SQL actions. Is your mind overflowing with ideas on how to use them to automate your database related projects? It should be!

So far you’ve only scratched the surface of what you can do with Automator actions. In the next and final practical example you’ll have another look at AppleScript, and how you can use outputs from your other actions.

Using Variables from your Workflow in AppleScript

It’s very easy to use Automator to collect variables, files, text, etc. Combine that with the power of AppleScript and you can do some pretty nifty stuff.

If you take a look at the standard data added to a Run AppleScript you’ll see the following:

on run {input, parameters}
	return input
end run

The input at the end of the Run Applescript action is actually an array of all data collected prior to this action in the workflow. To use these inputs, you need to assign them to a variable in your AppleScript.

set documentsDirectory to item 1 of input

You can assign variables with either set or copy, followed by the name of the variable. You can assign it a value straight away, above where you assign the value of the first item in the array of inputs.

If you have multiple variables, they are available based on their position in the workflow:
Screen Shot 2013-12-13 at 11.22.11 pm

The variables could be assigned as follows:

set documentsDirectory to item 1 of input
set computerUptime to item 2 of input
set currentWeekday to item 3 of input

Let’s try this out. You’ll be making a simple workflow that takes a variable (in this case your computer’s documents directory) and runs a command in terminal, based on the variable.

In Automator start a new project and select Workflow as the project type.

Select Variables in your library and search for Documents and drag it onto your workflow.

Screen Shot 2014-01-13 at 8.11.43 pm

Go back to your Actions library and drag a Run AppleScript action onto the workflow:

Screen Shot 2014-01-13 at 8.13.08 pm

Enter the following into your AppleScript text box:

on run {input, parameters}
 
	set documentsDirectory to item 1 of input
 
	tell application "Terminal"
		activate
		do script "cd " & documentsDirectory
	end tell
 
	return input
end run

Run the workflow. The current directory will change to your documents directory:
Screen Shot 2013-12-13 at 11.35.47 pm

To recap, you first instantiate a new variable called documentsDirectory which is then assigned to the first item in the array of inputs. You then tell your terminal application to activate it. Once activated, it will run the text string script which is made up of text and the documentsDirectory variable.

This is a very simple example but will give you some ideas about how you can expand it, and how AppleScript can become even more useful to you.

If you plan on doing a lot of shell command automation, then there is an action called Run Shell Script to make this process even more efficient.

Where To Go From Here?

Congratulations! You’re now familiar enough with Automator to create your own workflows and automate some of those tedious tasks.

You also had an introduction to the lightweight — but powerful — language of AppleScript. If you want to learn more about AppleScript, have a look at the official Applescript Documentation, which dives much deeper into the language.

If you want to see more practical examples using Automator or AppleScript, be sure to let us know.

Also, I would also love to hear about your workflows and the creative ways you’ve managed to save time, so be sure to leave a comment or two about your discoveries. Happy automating!

Automator for Mac OS X: Tutorial and Examples is a post from: Ray Wenderlich

The post Automator for Mac OS X: Tutorial and Examples appeared first on Ray Wenderlich.


Viewing all articles
Browse latest Browse all 4370

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>