TweetFollow Us on Twitter

Leap of Faith

Volume Number: 19 (2003)
Issue Number: 3
Column Tag: Leap of Faith

Leap of Faith

Why and how we switched from Carbon to Cocoa

by Steven Frank

A Dilemma

From the beginning, we were excited. A new Mac OS based on Unix! We loved the look and feel of Mac OS, and we loved the stability and standards of Unix, and the thought of the two combined was so wonderful that it was as if a choir of angels had descended with baskets of fine Belgian chocolates and sweet-smelling flowers on down pillows. That is to say, we liked the idea very much. But we also realized the magnitude of the change, and that it wasn't going to happen overnight.

After the release of Mac OS X we found ourselves, like many other Mac developers, confronted with a dilemma. We had two successful applications under our collective belt and, being serious Mac OS X fans, we knew beyond a doubt we wanted to upgrade them to Mac OS X native status. Our dilemma was, should we quickly port our applications using Carbon or essentially start them over in Cocoa?

Time being of the essence in those early days, we started ripping out the legacy code, and went the Carbon route. The Wild West-like frontier of Carbon was a little rough at first, but as Carbon itself was revised and finalized, it became mostly painless to get Classic code running on Mac OS X. Apple's Carbon team did a truly commendable job in making so many old applications run on a brand-new operating system architecture with so few changes. However, when the dust settled, it became apparent that our newer application, Audion, had fared much better in the transition than our older application Transmit.

Transmit, a graphical File Transfer Protocol (FTP) client, was originally written in 1996-1997, targeting Mac OS 7.5. Open Transport was still something new on the horizon. The Appearance Manager had not yet made its debut. Transmit was the first application I had ever written in C++ and my first PowerPlant application, and as such had a number of, shall we say, fascinating design decisions that, to be honest, are too embarrassing to mention.

As the Mac OS evolved, so did Transmit. Code was added to decide between MacTCP and Open Transport networking at runtime. More bridging code decided whether Mac OS 8 Appearance Manager widgets could be used, or whether backwards-compatible work-alikes were needed.

Mac OS X was unkind to our four year old code, and rightly so. Little bugs that had slipped past us, due to the lax nature of earlier OS versions, brought Transmit down in a flaming wreck on Mac OS X. I was grateful (no, really) to have these bugs brought to my attention, but it was clear that the code was due for an overhaul.

I had been learning Cocoa in my spare cycles for some time, and I very much liked what I saw. Here was a framework that was well designed, extensible, and very easy to use. The more I learned about it, the more I liked. It seemed like a good way for us to embrace the future, and bury that old code once and for all.

In March 2002 I decided to take the plunge, and started a skunkworks rewrite of Transmit in Cocoa that would later become the official Transmit 2 project with a three-person strong development team. What follows are some of the lessons we learned along the way.

Learning To Speak

One of the first decisions we faced was which language to use. Cocoa code can be written in either Objective-C or Java. My being more familiar with C and C++, as well as having an existing codebase written in those languages pretty much sealed the deal for Objective-C.

I've been surprised by the overwhelming reluctance of some of my fellow developers when it comes to Objective-C. It's a phenomenon I, as of five minutes ago, call "bracket shock". Developer sees what appears to be straight C code, but is confused by inexplicable brackets. Developer runs screaming back to their currently preferred language.

Objective-C is a very easy language to learn and surprisingly powerful once you understand its nuances. If you currently know ANSI C, and are at least familiar with object-oriented programming concepts, you can learn enough in one or two days to grope your way through your first project. I'm not exaggerating. You just have to get over your bracket shock.

In fact, to help you out, here are the only things a practicing C programmer really needs to know about Objective-C to get started:

    1. It's just C, but with object-oriented programming facilities.

    2. Those brackets surround method invocations. They're essentially just fancy function calls.

    3. Method arguments have names indicating their purpose.

    4. A hyphen indicates a method that is invoked on an instance of a class. A plus sign indicates a method that is invoked on the class itself.

Come to grips with those, then bounce back and forth between sample code, tutorials, and developer documentation, and you will be a master Objective-C programmer in less time than it would take you to complain about Objective-C's syntax. Apple provides a great introduction called "The

Objective-C Programming Language", located at: http://developer.apple.com/techpubs/macosx/Cocoa/ObjectiveC/index.html

Make no mistake though, the best way to write Cocoa code is not to hurriedly shoehorn in your old C++ code. Beyond the syntax itself, Objective-C code has its own style. There are "traditional" ways of naming methods and their arguments. I spent some time fighting this, and eventually realized I was just making things more difficult for myself. If you follow the traditional styles, other Objective-C programmers will be able to read your code and offer assistance. Learn about the Foundation types, especially NSString, NSArray, and NSDictionary, as these are workhorse classes that are used over and over and over again. Use these Foundation types instead of re-inventing your own container classes for the n-th time. It will make things easier. After a while, it gets under your skin and you will start to subconsciously realize when you are not doing things "the Cocoa way". As a general rule for Cocoa newcomers, if you ever find yourself saying, "There's got to be an easier way to do this," you are almost certainly right, and you should go find out what it is before continuing down your current path.

Keep in mind that learning additional programming languages beyond your comfort zone exposes you to new ideas and concepts, and makes you more employable. Go on! Try it! I had bracket shock at first too, but Objective-C is now among my favorite programming languages.

Dealing With Humans

Pesky humans! As developers, we write all this amazing and wondrous code, and then we have to figure out a way to expose the greatness of it all to plain-old ordinary human beings.

Fortunately for us, Apple has spent hundreds of thousands of dollars figuring out really good ways for us to do so, and they're giving this research away to us, for free, in the form of the Human Interface Guidelines, available online at: http://developer.apple.com/techpubs/macosx/Essentials/AquaHIGuidelines/index.html

Have you actually ever read the Human Interface Guidelines (HIG)? Be honest. I won't tell. What you need to know, as a Classic Mac OS programmer considering making the move to Mac OS X, is that these guidelines have changed for Aqua. In some areas, they've changed a lot.

When is it appropriate to use sheets? Drawers? Toolbars? The "metal" appearance? "Whenever it looks cool" is not the right answer for any of these.

If you have directly ported your Mac OS 9 interface to Mac OS X, it's going to look weird. You may not think it looks weird, but your Mac OS X users, even if they don't know exactly why, will feel a vague sense of unease when using your application. Something, they'll think, looks off. They'll find themselves compelled to use a different application that doesn't give them that feeling. You can get away with a sloppy interface on Windows, but on the Mac OS, it's cause for a public flogging.

In Mac OS X, the default fonts and font sizes have changed. The recommended spacing between controls has changed. Sheets are generally preferred over dialogs, but not always. The location of the Preferences and Quit menu items has changed. There are specific guidelines for designing your application's icon. Whitespace is preferred over separator lines. Visual hierarchy is preferred over group boxes. Do your windows avoid overlapping the Dock when zoomed?

If nothing else, you owe it to yourself to read the HIG section "Checklist for Creating Aqua Applications" which will give you a nice summary of the rest of the material. While it is obviously important that your application perform its tasks quickly and reliably, never underestimate the weight placed by users on your application's appearance, familiarity, and usability. That's true no matter which version of Mac OS you're developing for.

Environmental Concerns

It used to be that if you wanted to write a Cocoa application, you had to use Apple's Project Builder. Since then, Metrowerks has updated CodeWarrior to also support development with Cocoa.

Since CodeWarrior's Cocoa support was not completely available at the very beginning, I ended up learning Project Builder, and it's now my development environment of choice. Unfortunately, never having used it, I'm not qualified to talk to you about CodeWarrior's Cocoa support. But, I can tell you what I like about Project Builder.

First and foremost, I love Project Builder's integration with the gdb debugger. If you are not a Unix aficionado, you may not be familiar with gdb. At the surface, setting breakpoints within Project Builder and so forth is as easy as any other IDE, but if you're willing to spend a little time learning about gdb and delving into the debugging console, you can do some phenomenally advanced debugging. It is possible, just as an example, to set a programmatic breakpoint in a loop that stops execution, dumps the state of a few variables and then resumes, all automatically.

I've also come to appreciate Project Builder's single window layout option. At first, it felt a bit foreign, but before long I was zipping around as fast as ever. Integration with the CVS source management system was another big plus.

One Cocoa-ism that tends to throw people coming over from Carbon is the significance of Interface Builder in the development process. At first glance, it appears to be just a user interface layout tool like PowerPlant's Constructor. It is used for that purpose, but its role goes much further. In Interface Builder, you actually describe relationships between GUI controls and living, breathing objects in your code. If you find yourself looking for a call that just doesn't seem to exist ("How do I get a pointer to that button object in my window?") the answer probably lies in Interface Builder. (In this case, connect the button to a member variable in the class that is looking for it; Cocoa will set its value at runtime.) Project Builder and Interface Builder are tightly integrated, which is another advantage to using Apple's IDE.

On the flip side, Project Builder (or rather gcc, the underlying compiler) does seem slower at compilation than CodeWarrior did. My personal opinion is that the speed factor is outweighed by Project Builder's integration and overall stability. In this case, if it's good enough for Apple's developers, it's good enough for me.

Development environments are like religions though, and I know better than to recommend either. Try all of the available environments and see what you like. You may even be a truly hardcore user and prefer the Terminal's command line for all your development needs. That's OK too. Use whatever works best for you. But, as I said in the section about Objective-C, don't be a stereotypical stubborn developer. Keep your mind open, and don't be afraid to try new things. You might just learn something.

Getting Some New Threads

The first real issue I encountered while rewriting Transmit in Cocoa was a fundamental change in the operating system's threading model. All well-behaved network applications use some sort of threading, since it's no fun to be locked out of the user interface while network activity is taking place, with nothing but the rainbow beachball to keep you company.

In the old world, Transmit used the Thread Manager, which implemented the moderately cheesy "cooperative threading" model. In cooperative threading, each thread of execution is responsible for transferring control to the next eligible thread whenever it feels the time is right. Cocoa's threading model (NSThread) is built atop POSIX threads, which are preemptive. In the world of preemptive threading, your threads must be prepared to be swapped in and out at the operating system's whim. This is much harder to get right, but it results in significantly more efficient threading. The kernel is even smart enough to often be able to execute threads on different processors on multiprocessor Macs.

The issue of threading is complicated by somewhat vague documentation on which parts of Cocoa are "thread-safe" and which are not. The very general consensus seems to be that it is best to avoid calling into the Application Kit from any thread other than the main thread. So how, for example, should worker threads update elements in the user interface?

Until 10.2, the answer was to use Cocoa's Distributed Objects (DO) mechanism to invoke a method on the main thread that would perform the update on the worker thread's behalf. Explaining how to do this correctly is another article in itself, but enough information exists on the net that careful web searching will reveal what you need to know.

Alternatively, there is a new call available in 10.2, which makes the whole business much easier: performSelectorOnMainThread in NSApplication. You simply choose which method ("selector" is a bit of Objective-C jargon) you want, and it will be scheduled to run on the main thread. Very handy. But if you use performSelectorOnMainThread, your program will only be compatible with 10.2 and up, so consider your audience carefully.

There's not enough room in this article to get into all the intricacies of threading, so I'll refer you to Apple's TechNote 2028, which compares the OS 9 and OS X threading models in greater depth: http://developer.apple.com/technotes/tn/tn2028.html

Making The Network Work

Around the Mac OS 8 timeframe, Apple introduced a new networking API called Open Transport, which still exists today in Mac OS X's Carbon layer. But there's another API worth considering when doing Cocoa development, which is the traditional BSD sockets interface. (BSD refers to the flavor of Mac OS X's underlying Unix subsystem.)

Open Transport views network connections as "streams". You set up a network "endpoint", and a handler function, and then sit back until you receive notification at your handler of network events, such as connections, incoming data, and so on.

The socket model, an older but arguably more popular metaphor, treats network connections similarly to file handles. You "open" them by connecting to the other side, then you read and write data, and eventually close them.

This is a gross oversimplification of the whole thing, of course. Many long and tiresome battles have been waged about the relative merits of sockets versus streams, and to get into that mess would be beyond the scope of this article. What's relevant here is that the availability of industry-standard BSD socket calls on Mac OS X opens up a wonderful world of third-party code, of which you can take advantage. In our case, I discovered LibNcFTP, a highly competent C library implementing most all facets of the FTP protocol.

With the threading model already in place, it was easy enough to drop in calls to LibNcFTP and let it do the heavy lifting as far as network activity was concerned. Having been originally written for Unix, the library compiled effortlessly on Mac OS X, and plugged into our project without much sweat at all. Nothing's perfect of course, and we sent our share of feedback to the very patient library developer, who dutifully incorporated our suggestions and patches into his own code. The availability of this library saved us probably weeks worth of re-inventing the wheel. I had a barebones version of Cocoa Transmit able to connect to FTP servers and get a file listing within the first week of development, and we were more than happy to pay the modest licensing fee asked for LibNcFTP. It would have been a much more rigorous ordeal to use this same library in a Classic Mac OS application.

Switching to Mac OS X and Cocoa allowed us to ditch our capable but sometimes fragile homegrown FTP implementation in favor of one that has been in continuous development and refinement for ten years. It was something that actually provided a visible benefit to our customers too, not just a gratuitous technical achievement.

Mach-o, Mach-o Man

If you are used to Classic Mac OS programming, you are probably at least remotely familiar with the PEF binary format. PEF is the native format of executable binaries on Mac OS 9. Mac OS X can load PEF binaries for backwards compatibility, but its native format is Mach-O. In fact, Mach-O is the only binary format that Project Builder's tool chain will generate.

Classic PEF binaries had the concept of code modules that could be "weak-linked" or "strong-linked". To very quickly summarize, if you wanted to call an operating system API that was present in one version of the OS, but not another, you could tell the linker to either weak-link or strong-link that reference. If strong-linked, your application would not launch unless that API was present. Instead, the Finder would display a (usually quite terse) error message about the missing API. If the same application was weak-linked to the API, the application would launch, but the function pointer for the missing API would be set to NULL. This allowed the programmer to check at runtime what capabilities were available. The downside was if you forgot to check first and jumped to a NULL API, your application would crash.

Under Mac OS X and Mach-O, by default, if you have calls to functions in the BSD subsystem that are not implemented on the OS version that your program is running on, the OS will abort launching your application and log the offending call into the Console. We quickly discovered this within ten minutes of sending out our first Transmit 2 beta release, as we started getting reports from about half the testers that it wouldn't launch on their computers. We finally determined that all of these testers were running Mac OS X 10.1 and we were all running 10.2.

The problem was we had called a BSD function that was implemented on 10.2, but not 10.1. The 10.1 users saw only a generic Finder error message ("The application has unexpectedly quit"), while the true cause could be found in the Console's log. The system had logged the exact name of the missing function, which lead us straight to the root of the problem. Once we added a runtime check for the function, and appropriate bridging code, everything was back to normal.

However, if you invoke methods in the Cocoa frameworks that are unimplemented on the running system, a message will be logged to the Console, but your program will continue execution. This can lead to insidious bugs that seem inexplicable, unless your user happens to be running with the Console open. (Hint: He or she isn't.)

The best way to check if a Cocoa method exists before calling it is to send a respondsToSelector: message to the target object, passing the method in question. It will return a Boolean value indicating whether the method is implemented.

It's also beneficial to read the release notes for the Cocoa frameworks with each new release of the developer tools. They will explain which functions are new to each version.

An extra tip to those using the Jaguar developer tools: Apple now provides a preprocessor macro to control the compatibility level of the Cocoa headers. In other words, if you want precompiled headers that contain only APIs present in 10.1, you can run the following Terminal command:

   sudo fixPrecomps -force -precompFlags -DMAC_OS_X_VERSION_MAX_ALLOWED=1010

Then, in the area labeled "Other C Compiler Flags" in the "GCC Compiler Settings" section of your Project Builder project's target settings, add:

-DMAC_OS_X_VERSION_MAX_ALLOWED=1010

After completing these two steps, you'll get compiler errors if you try to use a Cocoa feature that is not available in 10.1.

There are two more probably obvious bits of advice that can be gleaned from our experience:

    1. Always try running your application on a system that meets only your application's minimum requirements before sending it off to anyone. Before you say your program runs on 10.1, try it to make sure!

    2. If your users are reporting weird behavior in your Cocoa application that does not match your understanding of the world, the first place you should look is the Console log. The odds are high that there will be some sort of message that will give you a clue, if it doesn't lead you directly to the source of the problem.

You should be aware that the few short paragraphs above represent only a very light treatment of the Mach-O linking and loading process. For more in-depth information, I recommend reading Apple's "Mach-O Runtime Architecture" located at: http://developer.apple.com/techpubs/macosx/DeveloperTools/MachORuntime/index.html

Care Package

Another aspect of Cocoa and Mac OS X programming in general that Classic Mac OS programmers will want to familiarize themselves with is application packaging. The Classic version of Transmit was distributed as a single file with code in the data fork and GUI resources in the resource fork.

The preferred format on Mac OS X is the application package. This is a folder hierarchy organized in a specific, known way, containing your binary executable, application metadata, and any resource files your application uses. The entire folder structure is presented to the user as a single double-clickable application icon.

Project Builder will automatically package your Cocoa application, so this is generally not something you have to worry too much about. However, it is worth your time to understand the layout of an application package and the reasoning behind it. To this end, you should read the "Application Packaging" section of Apple's Mac OS X "System Overview", which can be found here:

http://developer.apple.com/techpubs/macosx/Essentials/SystemOverview/ AppPackaging/Application_Packaging.html

The Cocoa class NSBundle assumes most of the roles of the classic Resource Manager, automatically locating application resources by name and type. A significant benefit of the application package appears when it comes time to localize your application into another language. In a nutshell, a folder is added to your application package for each language that your application supports. The files within each of these folders are identical for each language, but their content is localized for that language. When you ask Cocoa to retrieve, for example, your Preferences window from your resources, it is smart enough to return the French version when running on a French system, the German version on a German system, and so on. You only have to maintain one build, and it will localize itself at runtime. If you've ever localized a Classic Mac OS application, you can appreciate how much easier this is than the previously required gyrations.

It's not uncommon for your more devoted users to do the dirty work of localization for you, before you've even started looking for a translator. Within days of Transmit 2's release, we received a set of fully localized French resources which we were able to simply drop into the project, rebuild, and add French localization to our list of features.

Before releasing your code into the wild, you should go to the Terminal and type man strip. This curiously worded command will give you probably more information than you want to know about the "strip" command, which can be used to remove debugging symbols from your code. Even in a "deployment" build, Project Builder appears to leave behind a lot of symbolic information that is not needed in a shipping project. This can bloat the size of your executable dramatically, often to two or three times more than its natural size. The man page will describe all of the available options in gory detail, but my favorite incantation is strip -S <filename> (note the capital S), which removes symbols related to debugging, but not things like function names. You'll need to run this command on the actual executable, located in the Contents/MacOS directory of your application package. Why would you want to leave behind function names? For crash logs, which I'll get to in just a moment. Using strip -S reduces the size of the Transmit 2 executable by about three megabytes, which is nothing to sneeze at. One thing to look out for, though - if you leave function names in your shipping executable, you do make it slightly easier for pirates and other nefarious types to find their way through your code and deactivate any copy protection or registration schemes you may have employed.

Inevitably, the day will come when one of your users will report that your application has crashed. Wouldn't it be nice if you could get some truly detailed technical information about the nature of the crash? Mac OS X makes it possible! The first thing your user can do to help you is to head to the preferences of the Console utility. There, under the Crashes tab, are two checkboxes: Enable crash reporting, and Automatically display crash logs. Have the user turn both checkboxes on, then try to reproduce the crash. If the application does crash again, a log window will automatically pop up, containing vital clues about what happened, including a call stack trace of all running threads. Best of all, it's very easy for the user to cut and paste this information into an email to you. Much easier than it ever was with MacsBug!

Because you took my advice and used strip -S, the function names will be present in the stack traces, and hopefully it will be obvious what happened. One caveat about the crash logs - they get appended to the bottom of the file each time, but when the log window appears, its scrollbar is always scrolled to the top of the file. If you're not paying attention, you may think a bug you have already fixed is reappearing, when in fact you have to scroll down to get at the truth of the matter. Be sure to advise your users of this too. The quickest way to get to the most recent crash log is to scroll all the way down to the bottom, then page up until you see a row of 10 asterisks (**********). This indicates the start of an individual crash log.

Precious Natural Resources

The most important thing you need to know if you decide to make the journey from Carbon to Cocoa is that you aren't alone. There are plenty of other developers in the same boat, and many who have already traveled the road ahead. Don't make the mistake of isolating yourself from these great resources!

Cocoa sample code is increasingly abundant. If you find yourself stuck on a particular API, try plugging its name into Google and see what you find. Odds are good that relevant information is just waiting for you to discover it.

Web sites dedicated just to Cocoa programming are popping up left up and right. Just to name a few: www.cocoadevcentral.com, www.stepwise.com, and my own www.cocoadev.com each provide a slightly different approach to the topic, and are all worth a visit.

There are at least two mailing lists on the topic, which are worth joining. You can join Apple's cocoa-dev list at http://lists.apple.com/mailman/listinfo/cocoa-dev. The macosx-dev mailing list, hosted by Cocoa gurus The Omni Group, tends

to delve a bit deeper into the technical: http://www.omnigroup.com/developer/mailinglists/macosx-dev/. It's not necessary to read every message on the list (although you'd certainly learn a great deal if you did). I have a Mail filter set up that saves each mailing list message as it arrives into a mail sub-folder. This provides me with an extensive archive of discussions that's easily searchable for those times when I'm just stumped. Almost always I find that my most pressing questions have already been asked. If you do find you need to pose a new question, please be careful to observe good netiquette when posting to the lists, or you may find yourself feeling somewhat unwelcome.

If you are brand new to Cocoa and looking for something in hardcopy, I enthusiastically recommend Cocoa Programming for Mac OS X by Aaron Hillegass. It was the first Cocoa book that I felt was truly accessible when I was just starting out.

Last but not least, don't underestimate the value of joining Apple's Developer Connection (ADC) at http://connect.apple.com/. Basic accounts are free, but for a nominal subscription fee you'll receive prerelease seeds of upcoming versions of Mac OS X, as well as access to developer technical support from actual Apple employees, and a wealth of other perks.

All of these resources came to our rescue over and over again as we came to grips with the brave new world of Cocoa. It would have taken us much longer to release the product if we had not been fully plugged-in to them. Don't go it alone!

The Outcome

You're probably wondering, after all that work, was it worth it? We started over with a blank page and worked for about six months to recreate something that, by and large, already existed. It seems hard to justify. It seems like a duplication of effort.

I can assure you that it was absolutely worth it.

Our users were almost universally delighted to see the Cocoa version of Transmit. They were loud and clear that the time we had spent in the rewrite had paid off in terms of stability and functionality. User interface elements, such as toolbars and tables, that were tough to implement in Carbon required very little effort in Cocoa. Our native threading and networking model took full advantage of Mac OS X's architecture, especially on multiprocessor machines, and paid off dividends in speed. Not only that, but we got a chance to apply four years of user feedback in a major re-design of the program's underpinnings. Transmit's code is now significantly easier to maintain as well, and adding new features no longer has that "hope I don't bump the house of cards" feeling that I know you've experienced at some point in your projects. I don't regret any part of the endeavor.

You (or your manager) may have qualms about the size of the Mac OS X market. All indications from this end are that it's growing and fast. We released Transmit 2 for Mac OS X only in October of 2002 and it is selling at least as well, if not better than the previous OS 9 versions. Although we still offer an older version, 1.7, for our OS 9 users, we did not receive the torrent of "Where is Transmit 2 for OS 9?" email that we were expecting. In fact the people who are writing in about the OS 9 version seem to be almost universally indicating that it's only a stepping-stone until they get the chance to install Mac OS X.

Don't forget that Apple has decreed that new Macs will no longer be able to boot into OS 9. Whether you ultimately choose Carbon or Cocoa, the message is clear: migrate your code to OS X or become irrelevant. Mac OS X is the future of the Macintosh platform.

Moving to Cocoa isn't suitable or possible for everyone, and I can understand that. Every project has its own unique situation, scope, and requirements. But if you think there's even a slight chance you might be able to make the leap, you have my full encouragement to go for it, and hopefully this article will help you avoid some of the snake pits along the way. Good luck!


Steven Frank is the co-founder of Mac software renegade Panic, Inc. He was the original programmer of Transmit, an FTP client, and Audion, a digital audio player, as well as other smaller utilities. He can be contacted via email at stevenf@panic.com.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Summon your guild and prepare for war in...
Netmarble is making some pretty big moves with their latest update for Seven Knights Idle Adventure, with a bunch of interesting additions. Two new heroes enter the battle, there are events and bosses abound, and perhaps most interesting, a huge... | Read more »
Make the passage of time your plaything...
While some of us are still waiting for a chance to get our hands on Ash Prime - yes, don’t remind me I could currently buy him this month I’m barely hanging on - Digital Extremes has announced its next anticipated Prime Form for Warframe. Starting... | Read more »
If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly “borrowed” many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »
PUBG Mobile teams up with global phenome...
Since launching in 2019, SpyxFamily has exploded to damn near catastrophic popularity, so it was only a matter of time before a mobile game snapped up a collaboration. Enter PUBG Mobile. Until May 12th, players will be able to collect a host of... | Read more »
Embark into the frozen tundra of certain...
Chucklefish, developers of hit action-adventure sandbox game Starbound and owner of one of the cutest logos in gaming, has released their roguelike deck-builder Wildfrost. Created alongside developers Gaziter and Deadpan Games, Wildfrost will... | Read more »
MoreFun Studios has announced Season 4,...
Tension has escalated in the ever-volatile world of Arena Breakout, as your old pal Randall Fisher and bosses Fred and Perrero continue to lob insults and explosives at each other, bringing us to a new phase of warfare. Season 4, Into The Fog of... | Read more »
Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links below... | Read more »
Marvel Future Fight celebrates nine year...
Announced alongside an advertising image I can only assume was aimed squarely at myself with the prominent Deadpool and Odin featured on it, Netmarble has revealed their celebrations for the 9th anniversary of Marvel Future Fight. The Countdown... | Read more »
HoYoFair 2024 prepares to showcase over...
To say Genshin Impact took the world by storm when it was released would be an understatement. However, I think the most surprising part of the launch was just how much further it went than gaming. There have been concerts, art shows, massive... | Read more »

Price Scanner via MacPrices.net

Apple Watch Ultra 2 now available at Apple fo...
Apple has, for the first time, begun offering Certified Refurbished Apple Watch Ultra 2 models in their online store for $679, or $120 off MSRP. Each Watch includes Apple’s standard one-year warranty... Read more
AT&T has the iPhone 14 on sale for only $...
AT&T has the 128GB Apple iPhone 14 available for only $5.99 per month for new and existing customers when you activate unlimited service and use AT&T’s 36 month installment plan. The fine... Read more
Amazon is offering a $100 discount on every M...
Amazon is offering a $100 instant discount on each configuration of Apple’s new 13″ M3 MacBook Air, in Midnight, this weekend. These are the lowest prices currently available for new 13″ M3 MacBook... Read more
You can save $300-$480 on a 14-inch M3 Pro/Ma...
Apple has 14″ M3 Pro and M3 Max MacBook Pros in stock today and available, Certified Refurbished, starting at $1699 and ranging up to $480 off MSRP. Each model features a new outer case, shipping is... Read more
24-inch M1 iMacs available at Apple starting...
Apple has clearance M1 iMacs available in their Certified Refurbished store starting at $1049 and ranging up to $300 off original MSRP. Each iMac is in like-new condition and comes with Apple’s... Read more
Walmart continues to offer $699 13-inch M1 Ma...
Walmart continues to offer new Apple 13″ M1 MacBook Airs (8GB RAM, 256GB SSD) online for $699, $300 off original MSRP, in Space Gray, Silver, and Gold colors. These are new MacBook for sale by... Read more
B&H has 13-inch M2 MacBook Airs with 16GB...
B&H Photo has 13″ MacBook Airs with M2 CPUs, 16GB of memory, and 256GB of storage in stock and on sale for $1099, $100 off Apple’s MSRP for this configuration. Free 1-2 day delivery is available... Read more
14-inch M3 MacBook Pro with 16GB of RAM avail...
Apple has the 14″ M3 MacBook Pro with 16GB of RAM and 1TB of storage, Certified Refurbished, available for $300 off MSRP. Each MacBook Pro features a new outer case, shipping is free, and an Apple 1-... Read more
Apple M2 Mac minis on sale for up to $150 off...
Amazon has Apple’s M2-powered Mac minis in stock and on sale for $100-$150 off MSRP, each including free delivery: – Mac mini M2/256GB SSD: $499, save $100 – Mac mini M2/512GB SSD: $699, save $100 –... Read more
Amazon is offering a $200 discount on 14-inch...
Amazon has 14-inch M3 MacBook Pros in stock and on sale for $200 off MSRP. Shipping is free. Note that Amazon’s stock tends to come and go: – 14″ M3 MacBook Pro (8GB RAM/512GB SSD): $1399.99, $200... Read more

Jobs Board

*Apple* Systems Administrator - JAMF - Syste...
Title: Apple Systems Administrator - JAMF ALTA is supporting a direct hire opportunity. This position is 100% Onsite for initial 3-6 months and then remote 1-2 Read more
Relationship Banker - *Apple* Valley Financ...
Relationship Banker - Apple Valley Financial Center APPLE VALLEY, Minnesota **Job Description:** At Bank of America, we are guided by a common purpose to help Read more
IN6728 Optometrist- *Apple* Valley, CA- Tar...
Date: Apr 9, 2024 Brand: Target Optical Location: Apple Valley, CA, US, 92308 **Requisition ID:** 824398 At Target Optical, we help people see and look great - and Read more
Medical Assistant - Orthopedics *Apple* Hil...
Medical Assistant - Orthopedics Apple Hill York Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Now Read more
*Apple* Systems Administrator - JAMF - Activ...
…**Public Trust/Other Required:** None **Job Family:** Systems Administration **Skills:** Apple Platforms,Computer Servers,Jamf Pro **Experience:** 3 + years of Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.