TweetFollow Us on Twitter

Writing Cocoa Applications in Java

Volume Number: 19 (2003)
Issue Number: 12
Column Tag: Programming

Writing Cocoa Applications in Java

by Steve Klingsporn

Mac OS X is a great platform for software development. The combination of the Mac's elegant user experience, signature design and media tools, breakthroughs in mobile computing and UNIX-based underpinnings continues to lure developers away from other platforms. Apple has done a great deal of performance tuning in version 10.3 "Panther," optimizing the Carbon and Cocoa application frameworks while upgrading the underlying Mach kernel and BSD environment. Developers have a diverse choice of programming languages, from traditional assembly, C, and C++ to more dynamic languages like Objective-C, Java, JavaScript and Python. Apple ships Panther with "Xcode," its integrated development environment, which includes comprehensive documentation, sample code and the usual compilers and command-line tools. Xcode is an evolution of Project Builder, and adds neat features like code completion, fix and continue, predictive compilation, zero-link, distributed builds and a graphical debugger. Developers can choose between graphical tools like Xcode and Metrowerks CodeWarrior or more traditional command-line text editors and utilities. Apple rounds off its UNIX offerings with an X11 environment, which makes it extremely attractive to developers coming from Linux and FreeBSD camps. Apple is now the top vendor of high-volume UNIX systems, and Mac users can finally enjoy a truly remarkable, stable, and secure operating system.

Java has surpassed C and C++ as the world's most popular programming language, and is standard fare at most colleges and universities. Sun describes Java as "simple, object-oriented, distributed, interpreted, robust, secure, architecture neutral, portable, high-performance, multithreaded, and dynamic." Developers compile Java source into platform-independent byte code that executes identically across host platforms in a virtual machine (VM) environment. Sun's "Hotspot" VM dynamically compiles this byte code into native object code at runtime, and its performance often equals or exceeds that of compiled C and C++. Apple realized this when moving its WebObjects application server to Java, as did Netscape when it profiled the performance of its Java ("Rhino") and C-based ("SeaMonkey") JavaScript engines. The performance problems that plagued Java in the early days have been addressed, and in most cases, the only noticeable tradeoffs are slightly longer application launch times and the memory overhead incurred by the VM. This environment offers an additional level of stability and security that C and C++ can't match, protecting applications from crashing and unauthorized resource access through the use of exceptions and a policy-based security model. Java has taken off in the server space due to many of these advantages, where stability and security are critical. Server-side Java development is pure joy on Mac OS X, as you can run any of the popular J2EE-compliant application servers, most popular relational databases, and you can easily deploy on Mac OS X Server or any other Enterprise-class UNIX servers while developing on your PowerBook and listening to iTunes.

Apple ships Java 2 Standard Edition (J2SE) versions 1.3.1 and 1.4.1 with Panther, and these releases are available to developers still using Jaguar via the Software Update service. Apple includes a number of notable improvements and innovations in its J2SE implementations, including the sharing of commonly used classes across VM instances, and using the Cocoa framework as the basis for its AWT and Java2D implementations. The net result is arguably the best and most tightly integrated implementation of Java 2 available on any platform. In addition to the standard tools from Sun, Apple includes a "Jar Bundler" utility that assists in generating double-clickable applications from JAR files, and "JavaBrowser," a quick and useful class browser that allows the browsing of Java package hierarchies and their associated class definitions, source code and documentation without switching back and forth between Xcode and multiple pages in a web browser. These two applications live in /Developer/Applications/Java Tools, and are installed by the Xcode installer. Figure 1 depicts JavaBrowser displaying the source code for the java.util.StringTokenizer platform class.


Figure 1: JavaBrowser displaying the source code to the StringTokenizer class.

Cocoa Java

Cocoa is the evolution of the object-oriented application frameworks developed in the early 90's at NeXT, and was instrumental in the transition to Mac OS X at Apple. Developers who are interested in writing new applications for the Mac will probably choose Cocoa over Carbon because of its modern, object-oriented nature and award-winning rapid user interface design tool, "Interface Builder." With Interface Builder, you visually construct your application's user interface, dragging, dropping, configuring and tying components to "outlets" and "actions" which map directly to properties and methods implemented in your source code. Interface Builder generates "NIB files" containing frozen objects, which are packaged in directories that correspond to the various human languages your application is localized into. Organizing NIB files this way together with localized program strings gives developers a simple and powerful mechanism for providing their applications in many different languages and markets simultaneously.

Cocoa is written in the Objective-C language, which consists of a small number of extensions to ANSI C that enable object-oriented programming and dynamic runtime features. Objective-C is a more elegant and concise language than C++, lacks many of its drawbacks and pitfalls, and has a unique syntax for defining classes, categories, protocols and message passing between objects. Despite the power and simplicity of this language, C++ won the language war in the mid 90's, and Java's popular syntax more closely resembles C++, while borrowing many of Objective-C's features. James Gosling, Java's mastermind, credits Objective-C for inspiring many of the language's dynamic features, and today uses his PowerBook for most of his research and development work. While Objective-C may be the language that Apple would like to see developers using, it acknowledges Java's popularity and utilizes the "Java Bridge" technology the WebObjects team developed to facilitate building fully native Cocoa applications in pure Java. While you can continue to develop platform-independent Java applications using "Swing" and AWT, only Cocoa offers a true Aqua user experience and access to platform-specific features that Mac users have come to expect. Cocoa Java is a very attractive option for new and existing developers, leveraging the best aspects of these technologies without requiring the additional learning curve of mastering an unfamiliar programming language. You can freely mix Objective-C and Java code in your applications, and can design your classes so Cocoa-dependent code is separate from more generic code, which can continue to run unmodified on other host platforms.

Creating Your Project

To create a new Cocoa Java project, launch Xcode (in /Developer/Applications), and select "New Project..." from the "File" menu. Select "Cocoa Java Application," click "Next," and tell Xcode the name and location of your new project. If you are planning on developing a document-based application utilizing the NSDocument class, you may want to select "Cocoa Java Document-based Application" instead.


Figure 2: Using Xcode to create a new Cocoa Java project.

Xcode will create a new project directory for you based on its template for a Cocoa Java application, and will put some placeholder files into this directory, including a "MainMenu.nib" file for editing in Interface Builder, links to the AppKit, Cocoa and Foundation frameworks, and a "main.m" Objective-C stub file that is called only to launch your application, and is actually optional. Figure 3 shows what a new Cocoa Java project window should look like. The name of your project, of course, will be different from the one used in this article. If you are using Project Builder on Jaguar, things will be arranged differently. A considerable number of articles have been written about Cocoa development in Project Builder.


Figure 3: A new Cocoa Java application project window.

At this point, you will begin to follow the usual iterative Cocoa development patterns. Much has been written in previous articles and tutorials about this process, which generally consists of using Interface Builder to design classes in the "Classes" tab of your NIB file window, specifying instances of these classes in the "Instances" tab by dragging or manually creating them, and drawing out the connections between them. You then either auto-generate or edit your source code files, implementing the various member variables and methods associated with the outlets and actions you define in the "Classes" tab. You should keep all of your program strings in a text file called "Localizable.strings," and use NSBundle.localizedString to retrieve them instead of hard-coding them in your source. You can generate different language bundles for other localizations containing this file and any NIB files that have localization-specific changes. "MainMenu.nib" is the default NIB file that Xcode generates from its Cocoa Java project template, and should be double-clicked to launch Interface Builder when you are ready to begin specifying the menus and windows for your application. You can break your application's user interface up into multiple NIB files to decrease your application's launch time and provide your localizers with files that are easier to manage and edit.

Differences From Objective-C

The obvious difference from programming in Objective-C is that you will be using Java to implement your source files. The Cocoa AppKit and Foundation Kit frameworks are implemented in the com.apple.cocoa.application and com.apple.cocoa.foundation packages. You should import these packages in full, or at least the classes from them you plan on using, in each of your source files that depends on Cocoa. You are simply using Cocoa for your user interface and platform integration instead of AWT or JFC ("Swing"). Everything else more or less remains familiar, and you can use any of the tried and true Java platform classes you like mixed in with your use of Cocoa. You can add the paths to your class, source and documentation files for your application to JavaBrowser if you wish, and conveniently browse them in conjunction with the Java and Cocoa platform classes. You can even use "Ant" to build portions or the entirety of your project, though this will require you to manually write a "build.xml" file and do a bit of extra work. You will find that most of the Cocoa sample code on the web and most of the mailing lists, books and other resources listed at the end of this article are written in Objective-C, so a rudimentary understanding of the language and its message passing syntax will prove useful. Converting between Objective-C and Java will become second-nature as soon as you get the hang of its syntax peculiarities, and you will begin to appreciate the conventions Apple took in converting the API to Java, often using familiar interfaces instead of protocols and the like. In most cases, there is no penalty (or "toll") for subclassing or calling back and forth between the two languages across the Java Bridge, and Apple's documentation describes cases in which you should pay special attention to performance or memory management issues.

One key difference between Objective-C and Java Cocoa is that Apple has not provided Java equivalents for many of the I/O, string manipulation and other such classes in the Foundation Kit, including NSFileHandle, NSThread, NSValue and NSScanner, expecting developers to instead use standard Java platform counterparts like java.io.File, java.lang.Thread, java.lang.Object and java.util.StringTokenizer. Use java.lang.String instead of NSString; NSAttributedString and other Cocoa classes that take strings accept them. Java's network and file I/O classes are not only familiar to seasoned Java developers, but often offer more elegant solutions than their Objective-C counterparts. Java's platform advantages really start to become self-evident when using features like reflection, serialization, and remote method invocation (RMI), not to mention libraries like JDBC, which enables a Cocoa developer to easily write a vendor-neutral relational database application with a native Cocoa user experience in an afternoon. Any of the countless Java packages and libraries available can be leveraged by your Cocoa Java applications, saving you time and allowing you to concentrate on implementing application-specific functionality. This truly powerful combination of technologies should not be overlooked by anyone considering using Objective-C for their next killer Cocoa app.

Mixing Java and Cocoa

For the purposes of this article, we will be examining some of the code from "Aquataxx," a Cocoa Java implementation of the classic arcade strategy game, "Ataxx," shown in Figure 4. Aquataxx is a comprehensive example of using Cocoa features like brushed metal windows, drawers, sheets, bouncing Dock icons, text editing, tab views, user defaults, localized strings, drag and drop, sound, animation and drawing in custom NSView subclasses. In addition, it sports a game engine with impressive AI, networked game play and messaging, a standalone network "roster server" for finding other online players, and some advanced threading techniques, all written in portable, platform-agnostic Java. The result is a portable implementation of Ataxx with a challenging computer player, a rich, themable Cocoa user experience, network play and chat, and more. Writing the same game in Objective-C would have taken longer than the two weeks it took to write Aquataxx.


Figure 4: Aquataxx, a Cocoa Java game used as an example in this article.

Listing 1 depicts using Cocoa and Java platform classes together to implement the action method that is invoked by the "About Aquataxx" item in the "Aquataxx" application menu. Note that the method is public and a regular java.lang.Object is used for the sender parameter. We splice the Java version from java.lang.System into the version NSTextField and display the game's about sheet.

Listing 1:

A simple Cocoa "action" method, linked from the NIB file in Interface Builder.

/**
      Shows the about sheet 
      @param sender the sender of the message
   **/
   public void showAboutSheet(Object sender)
{        
      /* Set the version string, if need be */
      NSTextField versionField =    
         (NSTextField)mAboutPanel.contentView().
         viewWithTag(1);
         
      String versionString = versionField.stringValue();
   if (versionString.indexOf("{0}") > -1)
   {
      StringBuffer buffy = new 
         StringBuffer(AtaxxApplication.APPLICATION_VERSION);
         buffy.append(" - Java ");
         buffy.append(System.getProperty("java.version"));
         versionString = MessageFormat.format(versionString,
            new Object[] { buffy.toString() });
         versionField.setStringValue(versionString);
   }
        
/* Show the sheet */
   NSApplication.sharedApplication().beginSheet(
      mAboutPanel, mGameWindow, this, null, null);
}

Memory Management and Thread Safety

In most cases, you will not have to explicitly worry about memory management in your Cocoa Java applications. The usual warnings regarding hanging onto references and what not still apply, and Apple has a document that is referenced at the end of this article that explains the exceptions to these general rules. In some cases, to get around complicated interactions between Cocoa and Java objects, you will need to wrap objects in an NSArray; in others, you may have to catch possible NSExceptions that can be thrown by Cocoa object constructors. For the most part, the tricky retain and release memory management conventions used in Objective-C can be avoided; another one of Java's advantages improves the Cocoa development experience!

Java developers are used to satisfying the needs of most modern applications, especially those that use network I/O, with multiple threads. Java encourages the use of multithreading, and Java threads (java.lang.Thread) on Mac OS X are implemented as native Mach threads, so they have excellent performance. One of the inherent pitfalls of multithreaded programming is thread safety, and many aspects of the Cocoa frameworks are not yet guaranteed to be thread safe, meaning you cannot safely call many aspects of Cocoa, including your user interface, from background threads such as one that blocks on incoming network I/O. Since network socket I/O blocks in J2SE 1.3.1, and holding up the main thread in which many aspects of Cocoa including your user interface run in can result in unacceptable performance, a mechanism is needed to enable background threads to tell the main thread to execute code that interacts with Cocoa. NSObject in Objective-C has a method, performSelectorInMainThread, but unfortunately this functionality is not available in Cocoa Java. To get around this, the most popular strategy is to subclass NSApplication and implement sendEvent to handle application-defined events that correspond to blocks of code that need to be called in the main thread. Code that is called from your sendEvent implementation is guaranteed run in the main thread. Failing to observe the fact that many aspects of Cocoa are not thread safe will result in unexpected, random crashes (not exceptions) that can be hard to reproduce and debug and appear to be in Cocoa's Objective-C code. These types of crash logs can be confusing to developers programming in pure Java, yet can often help in tracking down sections of code that should be run in the main thread. Listing 2 is the full source for AtaxxApplication, the custom NSApplication subclass used in Aquataxx to handle events posted by background threads. Listing 3 depicts an example of posting such an event. The full source for Aquataxx is referenced at the end of this article, and can be examined for further examples of using this technique to assure your application plays by proper threading rules.

Listing 2:

AtaxxApplication, an NSApplication subclass that handles application-defined events.

/* AtaxxApplication.java */

import com.apple.cocoa.foundation.*;
import com.apple.cocoa.application.*;

/**
   A NSApplication subclass to add the ability to respond to application-defined events.
 **/

public class AtaxxApplication
   extends NSApplication
{
   /** Application version string **/
   public static final String APPLICATION_VERSION = "1.8";
    
/* Application-defined event types */
   protected static final short NEW_MATCH_EVENT = 0;
   protected static final short SCROLL_CONVERSATION_EVENT = 1;
   protected static final short CONFIRM_CONNECTION_EVENT = 2;
   protected static final short UPDATE_ROSTER_EVENT = 3;
   protected static final short INCOMING_DROPPED_EVENT = 4;
    
/**
   Overridden to respond to custom events.
   @param event the event being processed.
 **/
   public void sendEvent(NSEvent event)
   {
      /* Only worry about application-defined events */
      if (event.type() == NSEvent.ApplicationDefined)
      {
         switch (event.subtype())
         {                
   /* Create a new match */
            case NEW_MATCH_EVENT:
            {
               AtaxxController.sharedController().
                  startNewMatch(event.data1(),
                     event.data2());
               break;
            }
                
   /* Scroll the conversation view */
            case SCROLL_CONVERSATION_EVENT:
            {
               AtaxxController.sharedController().
                  scrollConversationView();
               break;
            }
                    
   /* Confirm a connection request */
            case CONFIRM_CONNECTION_EVENT:
            {
               AtaxxController.sharedController().
                  confirmConnectionRequest();
               break;
            }
                    
   /* Update roster data source */
            case UPDATE_ROSTER_EVENT:
            {
               AtaxxController.sharedController().
                  updateRosterDataSource();
               break;
            }
                    
   /* Close the connection request sheet */
            case INCOMING_DROPPED_EVENT:
            {
               AtaxxController.sharedController().
                  closeAnySheet(null);
               break;
            }
         }
      }
      else
      {
         super.sendEvent(event);
      }
   }
}

Listing 3:

A wrapper method that posts an application-defined event.
      
      /**
         Posts an application-defined event to the current application.
         @param code the event code
         @param data1 the first parameter
         @param data2 the second parameter
         @param front post to the front of the queue?
      **/
      public void postApplicationDefinedEvent(short code,
                                                      int data1,
                                                      int data2,
                                                      boolean front)
      {
         NSEvent event = NSEvent.otherEvent(NSEvent.ApplicationDefined,
            new NSPoint(0, 0), 0, System.currentTimeMillis() / 1000.0, 0,
            null, code, data1, data2);
         NSApplication.sharedApplication().postEvent(event, front);
      }

Implementing Custom Views

One of the more rewarding aspects of Cocoa programming is implementing your own NSView subclasses. NSView is the base class in the Cocoa user interface class hierarchy, and all of the user interface components you see and interact with inevitably inherit from it. If one of Apple's standard views does not suit the type of data or interaction you are trying to represent, as is the case with the game board and player score views in Aquataxx, you should implement a custom NSView subclass. You subclass NSView in the "Classes" tab of your NIB file window in Interface Builder, and create a corresponding Java source file just as you would if you were using Objective-C. Listing 4 is the complete source code for AtaxxScoreView, a custom view that draws both players' names and scores and highlights the active player with an etched appearance that looks similar to iTunes. For a more comprehensive and exciting example of a custom view that handles events and uses optimized drawing and drag and drop, take a look at the source for AtaxxView, which draws the game board and is found in the full source code distribution. Cocoa user interface programming is a lot more fun, intuitive, and rewarding than using "Swing!"

Listing 4:

The complete source for AtaxxScoreView, a custom NSView subclass.
/* AtaxxScoreView.java */
import com.apple.cocoa.foundation.*;
import com.apple.cocoa.application.*;
/**
   A custom NSView subclass that displays an etched
   metallic scoreboard for two players, and highlights
   the player whose turn it is.
 **/
public class AtaxxScoreView
    extends NSView
{
   /* The colors for drawing the scoreboard */
   public static final NSColor FOREGROUND_COLOR =
      NSColor.colorWithCalibratedRGB(.20f, .20f, .20f, 1.0f);
   public static final NSColor BACKGROUND_COLOR = NSColor.whiteColor();
   public static final NSColor FOREGROUND_UP_COLOR = NSColor.blackColor();
   public static final NSColor BACKGROUND_UP_COLOR = NSColor.grayColor();
/* The (four) attributed score strings ((back, front) * 2) */
   private NSMutableAttributedString mScoreStrings[] = null;
    
/**
   Constructor
   @param frame the frame rectangle
 **/
   public AtaxxScoreView(NSRect frame)
   {
      super(frame);
      mScoreStrings = new NSMutableAttributedString[4];
   }
/**
   Tells the window server that we are not opaque (we are transparent).
   @returns false, as we are transparent.
 **/
   public boolean isOpaque()
   {
      return false;
   }
    
/**
   Draws the view
   @param rect the update rectangle
 **/
   public void drawRect(NSRect rect)
   {
      if (mScoreStrings != null)
      {
         NSMutableRect stencil = new NSMutableRect(bounds());
         stencil.insetRect(0.5f, 1.0f);
         stencil.setOrigin(new NSPoint(1.0f, 0.0f));
         NSGraphics.drawAttributedString(mScoreStrings[0], stencil);
         NSGraphics.drawAttributedString(mScoreStrings[2], stencil);
         stencil.setOrigin(new NSPoint(0.0f, 1.0f));
         NSGraphics.drawAttributedString(mScoreStrings[1], stencil);
         NSGraphics.drawAttributedString(mScoreStrings[3], stencil);
      }
   }
/**
   Creates the 4 attributed score strings, based on
   the current score strings and player that is up.
   @param player1 the string for the first player
   @param player2 the string for the second player
   @param up the player that is up (hilighted)
   (0 = none, 1 = player 1, 2 = player 2)
 **/
   public synchronized void update(String player1,
                                          String player2,
                                          int up)
   {
      /* For convenience in looping through the strings */
      String strings[] = { player1, player1, player2, player2 };
      NSMutableAttributedString newStrings[] =
         new NSMutableAttributedString[4];
                
      for (int i = 0; i < 4; i += 2)
      {
         /* Create the pair of attributed strings (foreground and background) */
         newStrings[i] = 
            new NSMutableAttributedString(strings[i]);
         newStrings[i + 1] = 
            new NSMutableAttributedString(strings[i + 1]);
   /* Create a range for the string pair */
         NSRange range = new NSRange(0, strings[i].length());
            
   /* Set the text alignment */
         NSMutableParagraphStyle paragraphStyle =
            new NSMutableParagraphStyle();
         paragraphStyle.setAlignment((i < 2) ? 
            NSText.LeftTextAlignment :
            NSText.RightTextAlignment);
         newStrings[i].addAttributeInRange(
            NSAttributedString.ParagraphStyleAttributeName,
            paragraphStyle, range);
         newStrings[i + 1].addAttributeInRange(
            NSAttributedString.ParagraphStyleAttributeName,
            paragraphStyle, range);
                
   /* Set the font to the system font, size 10 (localization?) */
         NSFont font = NSFont.systemFontOfSize(10);
         newStrings[i].addAttributeInRange(
            NSAttributedString.FontAttributeName,
            font, range);
         newStrings[i + 1].addAttributeInRange(
            NSAttributedString.FontAttributeName,
            font, range);
            
   /* Set the foreground and background colors */
         NSColor foregroundColor = FOREGROUND_COLOR;
         NSColor backgroundColor = BACKGROUND_COLOR;
         if ((i < 2 && up == 1) ||
            (i > 1 && up == 2))
         {
            foregroundColor = FOREGROUND_UP_COLOR;
            backgroundColor = BACKGROUND_UP_COLOR;
         }
         newStrings[i].addAttributeInRange(
            NSAttributedString.ForegroundColorAttributeName,
            backgroundColor, range);
         newStrings[i + 1].addAttributeInRange(
            NSAttributedString.ForegroundColorAttributeName,
            foregroundColor, range);
            
   /* Fix up the attributes, whatever that does */
         newStrings[i].fixAttributesInRange(range);
         newStrings[i + 1].fixAttributesInRange(range);
            
   /* Set the actual attributed score strings */
         mScoreStrings[i] = newStrings[i];
         mScoreStrings[i + 1] = newStrings[i + 1];
      }
      /* Redraw the view! */
      display();
   }
}

Conclusion

Java is an excellent choice for developing Cocoa applications. If you are a Java programmer, are new to Cocoa, or are not interested in learning Objective-C, you should give Cocoa Java a try. The popularity of the language and the sheer quantity of third-party libraries and tools provide Java programmers with an impressive array of pre-engineered solutions over those available in Objective-C. Apple continues to provide Java interfaces to the new features it adds to Cocoa. It's time for developers to take better advantage of this technology and provide Apple with the feedback they need to make Cocoa Java even better. The end result is more great applications for Mac OS X.

Resources

The following resources will help you get started in learning about Cocoa Java programming. Sun has a general Java language tutorial, Apple has a Cocoa Java tutorial, and there are several sample applications installed with Xcode that will prove to be good references. The Aquataxx game distribution and full source code referenced in this article is available, and Apple and The Omni Group have good Cocoa development mailing lists that can be browsed and searched at http://cocoa.mamasam.com. If you have questions that you cannot find the answers to, or would like to discuss Cocoa Java programming in general, you can contact the author at steve@buzzlabs.com.


Steve Klingsporn is an independent software developer living in Chicago with his cat, Sonya. He has an 11 year history of working at companies such as Apple, Netscape, and Sun. He is available for independent Mac OS X, Java and web development, and can be reached at steve@buzzlabs.com.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Minecraft 1.19.3 - Popular sandbox build...
Minecraft allows players to build constructions out of textured cubes in a 3D procedurally generated world. Other activities in the game include exploration, gathering resources, crafting, and combat... Read more
Boom 3D 1.4.0 - $19.99
Boom 3D is a revolutionary app with 3D Surround Sound and phenomenally rich and intense audio that is realistic and works on any headphones. Features 3D surround sound Built-in audio player... Read more
Visual Studio Code 1.74.0 - Cross-platfo...
Visual Studio Code provides developers with a new choice of developer tool that combines the simplicity and streamlined experience of a code editor with the best of what developers need for their... Read more
Notion 2.1.9 - A unified workspace for m...
Notion is the unified workspace for modern teams. Features: Integration with Slack Documents Wikis Tasks More guests: invite up to 10 collaborators, friends & family to your pages Page... Read more
Spotify 1.2.0.1165 - Stream music, creat...
Spotify is a streaming music service that gives you on-demand access to millions of songs. Whether you like driving rock, silky R&B, or grandiose classical music, Spotify's massive catalogue puts... Read more
Thunderbird 102.5.1 - Email client from...
As of July 2012, Thunderbird has transitioned to a new governance model, with new features being developed by the broader free software and open source community, and security fixes and improvements... Read more
Pinegrow 7.03 - Mockup and design web pa...
Pinegrow (was Pinegrow Web Designer) is desktop app that lets you mockup and design webpages faster with multi-page editing, CSS and LESS styling, and smart components for Bootstrap, Foundation,... Read more
Adobe After Effects 2022 23.1 - Create p...
The new, more connected Adobe After Effects can make the impossible possible. Get powerful new features like a Live 3D Pipeline that brings CINEMA 4D scenes in as layers - without intermediate... Read more
SteerMouse 5.6.7 - Powerful third-party...
SteerMouse is an advanced driver for USB and Bluetooth mice. SteerMouse can assign various functions to buttons that Apple's software does not allow, including double-clicks, modifier clicks,... Read more
Wireshark 4.0.2 - Network protocol analy...
Wireshark is one of the world's foremost network protocol analyzers, and is the standard in many parts of the industry. It is the continuation of a project that started in 1998. Hundreds of... Read more

Latest Forum Discussions

See All

Level Infinite announce December events...
The hit MMORPG Tower of Fantasy will receive a new update in December, along with a powerful new Simulacrum. Players will be able to explore new areas of Mirroria with fun new games and take part in a big new event. [Read more] | Read more »
Dead Cells: Return to Castlevania DLC Re...
Dead Cells on iOS from Playdigious recently released on Apple Arcade in the form of Dead Cells+ (). Dead Cells+ is an App Store Great featuring all prior DLC and updates. At The Game Awards 2022, Motion Twin revealed the next major DLC for Dead... | Read more »
‘Among Us’ Hide and Seek Mode Update Com...
At The Game Awards 2022, Innersloth announced the next major update for Among Us (Free). This update is arriving today for all platforms and it will bring in the new Hide n Seek game mode alongside new cosmetics and pets. This update is the game’s... | Read more »
Massively Popular ‘Vampire Survivors’ Is...
Ahead of The Game Awards 2022, the massively popular Vampire Survivors (Free) has released on iOS and Android for free. Vampire Survivors is one of the most popular PC games right now, and it is a regular on every Steam Deck most-played list from... | Read more »
SwitchArcade Round-Up: ‘Chained Echoes’,...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for December 8th, 2022. Today is Thursday, and that usually means an absolute deluge of new releases on the eShop. But the year is winding down, so we’ve only got ten or so to look at... | Read more »
‘Awaken Legends: Idle RPG’ Celebrates th...
Awaken Legends: Idle RPG is adding its first update since the game was soft-launched in November, letting players get their hands on a new hero “Hera Valen". Players can also look forward to the Covenant of the Dark Knight event and the Wishing Well... | Read more »
‘Horizon Chase 2’ Japan World Tour Expan...
Horizon Chase 2 () from Aquiris is getting a major expansion today on Apple Arcade. The Japan World Tour expansion brings in 11 new races across 9 cities and it should be rolling out now as of this writing. I expect it to be available worldwide... | Read more »
Dark Fantasy Visual Novel ‘The 13th Mont...
Originally announced for release in August, The 13th Month from Japanese developer Kobayashimaru and publisher Kodansha released on PC via Steam worldwide this month. The dark fantasy visual novel that reimagines the classic Sleeping Beauty tale, is... | Read more »
Tom Clancey’s The Divison Resurgence ann...
Ubisoft has announced the latest Live Test dates for Tom Clancy’s The Division Resurgence, the hotly anticipated mobile entry in the Divison series. Starting December 8th and ending on the 22nd, the test will offer a huge amount of content for the... | Read more »
‘Easy Come Easy Golf’ New Update Adds St...
Easy Come Easy Golf () from Clap Hanz is one of my favorite games on Apple Arcade. It has been updated quite a bit since launch bringing in new modes and improvements. It recently launched on Nintendo Switch as well. | Read more »

Price Scanner via MacPrices.net

Lowest price of the season: 2022 Apple AirPod...
Verizon has new 2022 AirPods Pro in stock and on sale for $199.99 shipped as part of their Holiday sale. Their price is $50 off Apple’s MSRP, and it’s the lowest price currently available for 2022... Read more
New! Details on Verizon’s Christmas/Holiday p...
Verizon is offering discounts on iPhones, Apple Watch models, and iPads with specific promo codes as part of their Christmas/Holiday 2022 offerings. Codes are valid when adding a new line of service... Read more
Apple MagSafe accessories are back on Holiday...
Amazon has Apple MagSafe Chargers and Apple’s MagSafe Battery on sale for up to 24% off MSRP again as part of their Christmas/Holiday sale. Shipping is free, and all models are in stock: – MagSafe... Read more
13″ M2 MacBook Airs on sale again for the low...
Amazon has 13″ MacBook Airs with M2 CPUs in stock today and on sale for $150 off MSRP as part of their Christmas/Holiday Sale, prices start at $1049. Shipping is free. They are the lowest prices... Read more
Get an Apple 16″ MacBook Pro for $400 off MSR...
16″ MacBook Pros with Apple’s M1 Pro CPUs are in stock and on sale today at B&H Photo for $300-$400 off Apple’s MSRP for a limited time. Prices start at $2099 for M1 Pro models with 512GB or 1TB... Read more
Holiday clearance sale! Previous-generation A...
Amazon has 2nd generation 32GB and 64GB 4K Apple TVs with Siri remotes and 32GB Apple TV HDs on clearance sale for $80-$90 off original MSRP. Shipping is free, and delivery is available in time for... Read more
Christmas sale at Verizon: Apple AirPods Pro...
Verizon has first-generation Apple AirPods Pro on sale for $159.99 on their online store as part of their continuing Christmas/Holiday sale. Their price is $90 off Apple’s original MSRP, and it’s the... Read more
New Christmas/New Years promo at Xfinity Mobi...
Switch to Xfinity Mobile and open a new line of service, and take $400 off the price of a new iPhone, no trade-in required, through January 10, 2023. The $400 is applied to your account as credits... Read more
Apple iPad Smart Keyboard Folio prices drop u...
Apple iPad Smart Keyboard Folio prices have dropped up to $60 off MSRP at Amazon and Walmart as part of their Christmas/Holiday sales. These are the cheapest prices currently available for these iPad... Read more
Today is the final day for Xfinity Mobile’s $...
If you switch to Xfinity Mobile and open a new line of service, they will take $500 off the price of a new iPhone, no trade-in required. This is the best no trade-in Cyber Monday Apple iPhone 14 deal... Read more

Jobs Board

*Apple* Systems Administrator - JAMF - Activ...
…Administration **Duties and Responsibilities** + Configure and maintain the client's Apple Device Management (ADM) solution. The current solution is JAMF supporting Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Sephora Beauty Advisor - *Apple* Blossom Ma...
Sephora Beauty Advisor - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Operations Associate - *Apple* Blossom Mall...
Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.