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

OmniOutliner Pro 5.4.1 - Pro version of...
OmniOutliner Pro is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It's... Read more
EarthDesk 7.3 - $24.99
EarthDesk replaces your static desktop picture with a rendered image of Earth showing correct sun, moon, and city illumination. With an Internet connection, EarthDesk displays near-real-time global... Read more
Monosnap 3.5.3 - Versatile screenshot ut...
Monosnap lets you capture screenshots, share files, and record video and .gifs! Features Capture Capture full screen, just part of the screen, or a selected window Make your crop area pixel... Read more
Monosnap 3.5.3 - Versatile screenshot ut...
Monosnap lets you capture screenshots, share files, and record video and .gifs! Features Capture Capture full screen, just part of the screen, or a selected window Make your crop area pixel... Read more
Spotify 1.0.93.244 - 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
Evernote 7.6 - Create searchable notes a...
Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at anytime, from... Read more
Final Cut Pro X 10.4.4 - Professional vi...
Final Cut Pro X is a professional video editing solution. Completely redesigned from the ground up, Final Cut Pro adds extraordinary speed, quality, and flexibility to every part of the post-... Read more
Compressor 4.4.2 - Adds power and flexib...
Compressor adds power and flexibility to Final Cut Pro X export. Customize output settings, work faster with distributed encoding, and tap into a comprehensive set of delivery features. Features... Read more
Motion 5.4.2 - Create and customize Fina...
Motion is designed for video editors, Motion 5 lets you customize Final Cut Pro titles, transitions, and effects. Or create your own dazzling animations in 2D or 3D space, with real-time feedback as... Read more
Thunderbird 60.3.1 - Email client from M...
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

Latest Forum Discussions

See All

Slots Panther Vegas offers a social gamb...
New era of Online gambling Want to try your luck in online social gambling? More and more people are into online casinos as a risk-free amazing way to experience the excitement of a big game. Online casinos and slots machines are gaining popularity... | Read more »
3 features we think you'll love in...
Well known classic RPG “Shin Megami Tensei” franchise originally created by Atlus, can now be played throughout iOS and Android. Created by Sega, “Shin Megami Tensei” has spawned a mobile-centric installment in the shape of “Shin Megami Tensei:... | Read more »
These are the top 3 games for iPhone and...
The end of the week has rolled around again, which means it's time for us to look forward to the games you're going to be playing over the next seven days. We've got the return of a mobile gaming legend next week, as well as a couple of other... | Read more »
Time for you to pick which of these top...
Oh look, Thursday is upon us once more. And we all know what that means! You guessed it, it's time for you to vote for which of these five games you think deserves to win our game of the week award. And have we got a selection for y'all this week... | Read more »
Dragalia Lost - High Midgardsormr Prep G...
It might not seem like there's a ton to do between events in Dragalia Lost, but there is one high level piece of content that can keep you occupied for a long time. Defeating High Midgardsormr is currently the game's most difficult non-event... | Read more »
Get your friends, these are the top 5 be...
You can't be a lone wolf all the time, especially if you want to show off your gaming prowess. And that's where this list comes in - we're running down what we think are the top 5 multiplayer games for iPhone. There might be some controversial... | Read more »
SpitKiss is the worthy winner of last we...
It's been a rough and tumble battle this week, with all of the games managing to get a few hits in where it counts, but after checking with the independent adjudicators at ringside, we can now reveal that gloriously gross smooching sim SpitKiss has... | Read more »
The best games for iPhone - The definiti...
Hi there, and welcome to our ever-increasing list of the very best games for iPhone. We're going to be updating this regularly with new content, so make sure you check back often, because you're not going to want to miss out on even one of the... | Read more »
Dragalia Lost Guide - What You Need To K...
Another raid has come and gone in Dragalia Lost, but that doesn’t mean there’s not still lots to do. In fact, the game’s next event, A Wish to the Winds, has already been announced and will be coming to the game this Wednesday. Although details are... | Read more »
The top 5 best games like Star Wars: Gal...
One of the things we like to do here at 148Apps is broaden your horizons. Maybe you're a fan of Star Wars: Galaxy of Heroes and you're looking for something that's going to scratch similar itches? Well that's where we come, and more specifically... | Read more »

Price Scanner via MacPrices.net

T-Mobile Black Friday deal: Free iPhone Xr wi...
T-Mobile is offering the 64GB iPhone Xr for free as part of their Black Friday 2018 sale. Two new lines are required, as well as an eligible trade-in (iPhone 6s models or newer). $20.84 is applied to... Read more
Save up to $157 on a 10.5″ iPad Pro with thes...
Apple’s newest authorized reseller, Jet, has 10.5″ iPad Pros on sale for up to $157 off MSRP as part of their Black Friday week sale. Shipping is free. Note that some sale prices may be restricted to... Read more
US Cellular offers free iPhone Xr for new lin...
US Cellular is offering the 64GB iPhone Xr for free as part of their Black Friday 2018 sale. A new line is required, but there is no trade in requirement. Any of the iPhone Xr colors qualify. The... Read more
Roundup of Black Friday Week 2018 Sales &...
At MacPrices.net, we give you the most accurate Mac and Apple prices on the web. Choose one of our price trackers at the top of the page to see all the current sale prices on Apple’s products from... Read more
Details of Amazon’s 2018 Black Friday week di...
Amazon’s recent agreement with Apple has allowed the online store to add most of Apple’s most popular products to its inventory, including new 2018 iPad Pros, Mac minis, Apple Watch Series 4, and... Read more
Get A Job With Apple, The No. 3 ‘World’s Best...
FEATURE: 11.16.18- If you are a fan of Apple, Inc. and an avid user of any one of its vast array of tech gadgets, why not take it a step further and work for the company behind those products you... Read more
Sprint offers $100 discounts on Apple Watch S...
Sprint is offering customers $100 discounts on the purchase of a cellular Apple Watch Series 4 or Apple Watch Series 3. Their discount reduces the cost of a Series 4 watch to $399 (40mm) or $429 (... Read more
New 2018 11″ 64GB & 256GB iPad Pros in st...
MacMall has the new 2018 11″ 64GB and 256GB iPad Pros in stock today for $50 off Apple’s prices. They’re currently the lowest prices available for these new iPad Pros. – 11″ 64GB Space Gray WiFi iPad... Read more
New Mac minis in stock and available today at...
Apple Authorized Reseller Adorama has the new 2018 Mac minis in stock today today sales tax free for residents outside of NY & NJ. Shipping is also free. – 3.6GHz Quad-Core mini: $799 – 3.0GHz 6... Read more
Apple redesigns refurbished and clearance sec...
Apple’s Certified Refurbished Products have always been some of the best deals on Apple products such as Macs, iPads, iPhones, iPods, and accessories. Today they offered up a redesigned refurbished... Read more

Jobs Board

Best Buy *Apple* Computing Master - Best Bu...
**658102BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Location Number:** 000395-Pensacola-Store **Job Description:** **What does a Read more
*Apple* Mobile Master - Best Buy (United Sta...
**658022BR** **Job Title:** Apple Mobile Master **Job Category:** Store Associates **Location Number:** 000793-Dothan-Store **Job Description:** **What does a Best Read more
Geek Squad *Apple* Master Consultation Agen...
**657784BR** **Job Title:** Geek Squad Apple Master Consultation Agent **Job Category:** Services/Installation/Repair **Location Number:** 000597-Erie-Store **Job Read more
Best Buy *Apple* Computing Master - Best Bu...
**655276BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Location Number:** 000387-Randall Road-Store **Job Description:** **What does a Read more
Omni-Channel Associate - *Apple* Blossom Ma...
Omni-Channel Associate - Apple Blossom Mall Location:Winchester, VA, United States- Apple Blossom Mall 1850 Apple Blossom Dr Job ID:1074107 Date:November 12, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.