Introduction to Cycript and InfoStats 2

When building JavaScript based widgets, for any tweak that supports them, Cycript is always accessible to you immediately after installing InfoStats 2. This gives you as a developer a tremendous scope for building anything at all, whether it be a widget that controls the device's media, or perhaps a widget that allows users to create calendar entries. The possibilities are endless.

General syntax

To use Cycript (and therefore InfoStats 2) within your widgets, you will need to use the syntax for Objective-C to call functions. An explained example is below:

<script type="text/cycript">
 function getVariableFromAPI() {
  var currentBatteryPercent = [IS2System batteryPercent];
 }
</script>

The first line stating "text/cycript" is used to define a script that Cycript can process. Without this, your code will be processed as a standard JavaScript script, and will be seen as invalid as a result.

Next, we will focus upon [IS2System batteryPercent], as this is the syntax you will be using to call Objective-C functions.

The given example is calling a class function, that is, a function that does not require you to create an object to call it. InfoStats 2 has been built to avoid having to deal with objects where possible to make things easier for you.

A class function is always called in the same manner as the example. After the first [, you add in the class name where you want to call a given function from. The example above is using IS2System as its class name. Using InfoStats 2, a few other class names you can use are:

  • IS2Calendar
  • IS2Location
  • IS2Media
  • IS2Notifications
  • IS2System
  • IS2Telephony
  • IS2Weather

Please note this is a small subset of all class names available; InfoStats 2 has others, and you are free to use all that Apple uses too.

Say we choose to call a function from IS2Telephony. Looking at the above example, our code will now be like so:

[IS2Telephony

With the reference in hand for IS2Telephony, we can then see the class functions available. These are always denoted by a + prefix, whether for InfoStats 2, or any other code. If a reference like that isn't available, then you can usually search the class name online, and look at its header file.

Here, we'll use the +(NSString*)wifiName class function to get the current WiFi SSID. To call this, our code will now look like:

[IS2Telephony wifiName]

You should be able to see the similarity between this and the first example; all class functions are called in exactly the same manner.

Using InfoStats 2

In all classes provided in InfoStats 2, there are three types of functions you will be working with:

  • Data retrieval
  • Task performing
  • Callback listeners

Data retrieval has already been covered by the main example given in the General syntax section, whereupon the current battery level is set to a variable.

Task performing is a fancy way of saying "calling void functions". An example is shown below:

<script type="text/cycript">
 function performTask() {
  [IS2Media togglePlayPause];
 }
</script>

This will simply toggle the current playing state of any media; therefore, it has perfomed a task. Within Objective-C's syntax, you can safely assume that any function that has type void, eg:

+(void)togglePlayPause;

will be a function that enacts an action on the device.

Callback listeners are more interesting.

Some functions within InfoStats 2 will run asynchronously; they will run in the background. However, some will also return data to you or notify you when it has finished, so you will need a way of your code to be ran once this background operation completes. A callback function allows this to take place. Within Objective-C, you can pass code to a function using a feature known as blocks. This code will the be run once the function is finished doing its operation; it calls back to your code, hence the name callback. Below is an example of blocks in action:

<script type="text/cycript">
 function runFunctionWithCallback() {
  // Begin weather updating
  [IS2Weather registerForWeatherUpdatesWithIdentifier:"com.test.identifier" andCallback:^ void () {
   document.getElementById('location').innerHTML = "Location: " + [IS2Weather currentLocation];
   document.getElementById('temp').innerHTML = "Temp: " + [IS2Weather currentTemperature];
  }];
 }
</script>

Above, the code within ^ void () { } will be run whenever the API needs to notify you that new data is available.

Listeners can be said to be a subset of callback functions, and above is an example of this. The idea is that you register a block to be run automatically; say the current playing track changes, you'd want to be able to be notified when that occurs. This scenario is shown below:

<script type="text/cycript">
 // Setup being notified of media changes
 [IS2Media registerForNowPlayingNotificationsWithIdentifier:"com.matchstic.mediatest" andCallback:^ void () {
  updateMedia();
 }];

 window.onunload = function(){
  [IS2Media unregisterForNotificationsWithIdentifier:"com.matchstic.mediatest"];
  return null;
 };
</script>

To register a listener, come up with any arbitrary identifier, such as "com.test.identifier" as used above. Then, the next parameter will be a callback block. Internally, the identifier is used to keep track of your block. In this example, a function named updateMedia(); will be run on each time the callback is ran. It is necessary to de-register your listener when your widget is being removed from the display; this is achieved by the code in window.onunload

All listener functions in InfoStats 2 will always be prefixed with registerFor or unregisterFor, and all functions that take a callback will have the suffix withCallback.

Further reading

If you're wanting to do further reading into the internals of Cycript, see:

  • Saurik's manual here, which goes both using Cycript from the command line, and also more in-depth on the fundamentals covered in this page.

  • Further information on syntax here

  • Advanced tips and tricks here