TweetFollow Us on Twitter

MacApp Objects
Volume Number:3
Issue Number:9
Column Tag:MacApp Objects

Programming in the Closet

By David A. Wilson, Personal Concepts, Palo Alto, CA

or

“How to write a program without really writing a program”

Dave Wilson is the owner of Personal Concepts, a consulting firm specializing in software development for the Macintosh. He currently is teaching courses for Apple on both beginning Macintosh programming and object-oriented programming.

This article can be blamed on Howard Katz, who is the newsletter Editor for the MacApp Developer’s Association. Howard knew that I present four-day Seminars for Apple entitled MacApp™ and Object Oriented Programming , and thought that experiences from the first five of these seminars might be useful to others who are learning MacApp. Much of this article first appeared in the May 1987 issue of the MacAppDA’s newsletter, and is reprinted with their permission. I might add that you should definitely join us in the MacAppDA if you have an interest in object-oriented programming for the Macintosh. You can join by sending $15.00 to:

MacApp Developer’s Association

P.O. Box 23

Everett, WA 98206-0023.

First, some background to put the article in perspective. I have taught Apple’s beginning Macintosh Programming Seminars for the last two and one-half years, and have developed a healthy respect for the difficulties of writing Mac applications during this time. Starting about two years ago, I began to hear about this strange beast called MacApp that was claimed to make Mac programing relatively easy, so I got a copy to try out.

I didn’t begin seriously learning to use it until last Fall, when Apple agreed that a monthly Seminar was needed to help people get up to speed quickly on this new and powerful tool, so I started learning MacApp with more urgency. It took me about three man-months to feel comfortable with it, and the seminar is designed to fit as much of those experiences as possible into four days.

By the way, Apple also decided to provide a separate one-day seminar on Using MPW the day before each MacApp class, so we could cover Make files, Rez, etc. before worrying about MacApp itself. More about that below. By now you should be wondering if I am ever going to explain the weird title, so here goes

A History Lesson

A long, long time ago, in an operating system far, far away, applications programmers wrote code that directed the user along a certain path. As the programmer, you were clearly in control of what happened, so you gave orders to the user, and the user did what he or she was told. If the user did not follow orders, you displayed friendly error message such as “Syntax Error 5”, and hoped the user would shape up.

Then the Macintosh came along, and you were instructed to write friendly, “modeless” programs, with the operation controlled by the user. (Incidentally, humor writer Dave Barry defines “User” as the word that programmers use when they mean “idiot”). You wrote modeless programs by basing your application on a Main Event Loop. This had you calling the GetNextEvent ROM routine, and responding accordingly to events caused by the user. I liken this to programming in a room with the door closed. You can’t see the user, but when the user clicks the mouse down or types a key, the Event Manager slides a piece of paper under the door that contains the Event Record. You read the piece of paper, and respond accordingly.

Some programmers who are new to the Macintosh feel a bit nervous with this style because they don’t feel in control, but users certainly prefer it - because they are in control.

What happens with MacApp? It gets even worse. MacApp is an expandable generic application, consisting of hundreds of pages of Object Pascal source code written by some of Apple’s best programmers. All you have to do is customize the application through the special hooks provided by object-oriented programming, and, presto: you have your program!

Fig. 1 Getting into Objects in the Class Lab

Are you still all alone in the room, looking at pieces of paper slid under the door by the Event Manager? Uh-uh, MacApp is. Where are you? You are in the closet. Most of the time the program runs without needing your code at all, so MacApp will handle moving and resizing windows, operating scroll bars, opening Desk Accessories, etc. Once in a while MacApp needs you to do something specific to your program, so it opens the closet door, barks at you to “Draw yourself” or “Save the data to disk”, and then closes the door. You just do what your told, and stay out of the way the rest of the time.

With MacApp, you are no longer writing an applications program, but rather you are writing a few code fragments that customize the generic program written by Apple. Apple’s code runs the Main Event Loop, and does most of the event handling, so be sure to take a good book in the closet, because most of the time, you won’t have anything to do.

Your only problem will be in learning to use MacApp, and getting used to this new style of writing code. Which brings us

Back to the Seminars

Who takes these seminars? So far, we have had programmers from large corporations and universities, independent developers, Apple systems engineers, and Apple internal software developers. I expect to see many VARs (Value Added Resellers) and consultants during the next year - particularly as the powerful Macintosh II stimulates new interest in programming the Mac.

The MacApp seminar itself is a mixture of lectures and hands-on labs. We probably spend about 25% of the first two days programming, and perhaps 50% of the last two days. Each person has a Mac Plus with an HD-20 or HD-20SC with MPW and MacApp installed to use during class. We also provide some new sample programs and a 500-page Notebook.

The programming Labs begin with the Nothing program provided by Apple as a standard MacApp sample. You then add features to this program over the next four days until you have a text editor that, just for fun, can draw rectangles on top of the text. A palette controls part of the program’s operation, and the text and graphics can be saved to a document file on disk. This process is described in a 13-part exercise that you work on for the whole four days - at your own pace. The majority of people will not finish this project during class, but do leave with the “solution” on disk, so they can finish it on their own if they wish. A screen dump from the finished Lab is shown below in figure 1.

At this point, you might ask “Is MacApp easy to learn?”, and I would have to answer a definite “maybe”. Perhaps 25% of the students so far find that they are writing MacApp programs within four days. The other 75% find that they know much more about MacApp, but still feel that they need to invest more time on their own before they are ready to write a program. The major obstacle seems to be learning the new style and behavior of object-oriented programming, so people who have had experience with SmallTalk, Neon, Common LISP, etc. have a much easier time.

In the rest of this article, I’ll mention some of the common stumbling blocks, and suggest ways around them. This article will be most useful to you if you have already tried to learn MacApp on your own, and are having problems with understanding certain concepts. If you have never seen MPW or MacApp, you might want to read MacTutor’s introductory articles published in back issues first.

MPW

MPW (the Macintosh Programmer’s Workshop) seems to be easy for people to handle because of MacApp’s nifty MABuild command. There are a couple of things to keep in mind, however.

Remember to update your Make file when you use new building blocks (such as the text edit Unit UTEView), or new files containing resources (such as you might make with ResEdit). Otherwise, MABuild will not update everything properly if changes are made to these files.

MENU resources are not directly used in MacApp, so we instead need to use command menus, of resource type ‘cmnu’. These are easy to describe in a text file for Rez, as long as you can figure out which items to enable. The golden rule is that the least significant bit in the enable flag should be set to 1 to enable the first item in the menu, the next bit controls the second menu item, and so forth.

Object Oriented Programming

The major obstacles involve object-oriented programming(OOP), rather than Object Pascal or the MacApp libraries. Here are some of the common problems:

Program Design

Almost everyone has a hard time deciding which object types should be defined for the program that they wish to write. We spend a few hours in class on this subject, so I can’t make a simple answer here, but I’ll suggest a partial method to use (notice the great pun).

Step 1: Decide on what types of documents you need on disk. These will then correspond to your Document object types. For example, you might have text documents that will be displayed in windows, and Index documents that the user never manipulates, but that are used by data base access routines.

Step 2: Decide what views of your document’s data are to be shown in the windows. These will correspond to your View object types. For example, you might have a text view of your text document, a tabular view of some data base information, and a palette view that the user can use to control the program’s operation. Note that the palette view may not be associated with any specific document.

Step 3: Decide what data objects you need to manipulate. These might represent graphics objects, “customer” objects, or other objects that you might have formulated as Pascal Records in an earlier life. You still may decide to keep customer information in a record, but it is often better to create an Object Type, since you can then associate the methods that operate on the customer with the data about the customers.

INHERITED vs. SELF

A great strength of OOP is that we can Override a method, and substitute a new version of it with modified behavior. A common approach is to then reuse the old behavior in the new method by using the Object Pascal keyword INHERITED. This tells the program to use the ancestor’s method. Another common technique is for an object to call one of it’s own methods, using the optional keyword SELF.

That all sounds simple, but most people get confused as to when to call SELF.DoMenuCommand, and when to call INHERITED.DoMenuCommand, and in fact I have even been guilty of writing

INHERITED SELF.DoMenuCommand;

in my code. Not good. The rule to remember is that you use INHERITED to call a method of the ancestor to the object, while SELF refers to a method (or field) of the current object type.

Out of sight, out of mind

When you define an Object Type in the Interface of your Unit, you only define changes to the Object Type. Consider the example below:

TMyView = OBJECT(TView)
 TMyView.IMyView;
 TMyView.Draw(area:Rect); OVERRIDE;
 END;

This looks so simple that people often forget that an object of type TMyView also has all the fields and methods of TView, so that INHERITED Draw is definitely different than SELF.Draw. Furthermore, they forget that an object of type TMyView now has method IView in addition to method IMyView. It even has the method IEvtHandler that is inherited from the ancestor of TView.

This confusion leads to various strange things in people’s code, so remember that everything that we don’t override does get inherited from all the ancestors, including the ancestors of the immediate ancestors.

Fields that refer to other objects

A typical Interface might include the following:

TMyDocument = OBJECT(TDocument)
 fMyView: TMyView;
 TMyDocument.DoMakeViews; OVERRIDE;
 etc.

 TMyView = OBJECT(TView)
 fMyDocument: TMyDocument
 etc.

I find that people (a) often do not understand why they should include these cross-references, and (b) often forget to stuff correct values into these fields.

You should save a reference to an object so you can easily refer to a method or field of that object. You should then remember to initialize these fields with the proper values. If you do not, your program will crash into the MacApp interactive debugger with MacApp’s most common error, which is an ID = 03 crash. This usually means that your program is trying to use a field or method of an object that has an invalid address (i.e.,, an object reference that has never been initialized).

Inheritance Tree vs. Creation tree

Some people get confused about tree diagrams, since you may see more than one type. A typical inheritance diagram might look the one below, in figure 2, which means that TList, TCommand, and TEvtHandler each inherit all the fields and methods of TObject.

On the other hand, you might sometimes see a diagram that shows which objects create other objects, such as shown below in figure 3.

Fig. 2 Inheritance from TObject

Fig. 3 Objects from Objects

The confusion arises because people may think that the latter diagram represents property inheritance, rather than creation order. Remember, just because your application object creates your document objects does not imply that documents are descendents of applications.

Initialization methods

You need initialization methods to stuff correct values into the data fields of your object. This can be confusing because MacApp provides a number of initialization methods that you must call, but you usually also define some of your own. And, you should follow a certain style convention in doing this.

Consider defining a type of object TMyView that it a descendent of TView. That means that TMyView inherits an IView method. Now should you (1) use IView, (2) Override IView, or (3) define an new initialization method IMyView? The correct answers are “yes”, “no”, and “yes”. Let’s see why.

If your new Object Type has no new data fields to initialize, you may just want to use the following:

 New(aView):
 FailNil(aView);
 aView.IView( );

If your new Object Type does have data fields, you should not Override IView, but rather define a new method IMyView, and call IView from within that method. Why? Because if you keep IView and IMyView as separate methods, and never Override either one anywhere in your program, the compiler/linker can optimize them to be called as normal procedure calls rather than method calls. This will take place if you compile your program with the Optimize option turned on, and will improve performance and reduce overhead.

The MacApp Object Library

Managing all the goodies provided by MacApp.

We use a quick reference guide to MacApp when working in class, as an easier method to access all of MacApp Constants, Globals, fields, methods, etc. This Quick Reference is in the class Notebooks, but I will probably arrange for A.P.D.A. to distribute this so others can use it.

I also use a recipes file that contains sample Implementations to commonly used MacApp methods such as DoMenuCommand, TrackMouse, ITEView, etc. I usually work with this file open in MPW and liberally steal from it. This saves having to type the long parameter lists that many of these routines need.

The MacApp Developer’s Association is now selling a Browser Desk Accessory, modeled after the Browser in SmallTalk, that should be of great help in accessing the source code.

Drawing in the wrong methods

A common mistake is to draw on the screen in other methods than your view object’s Draw method.

An advantage to having Draw do all the work is that both screen updating and printing call the draw method. If you were to instead call QuickDraw graphics routines from other methods, then your drawings may not appear after screen updates, or on the printouts.

Another advantage to using the Draw method is that MacApp will first call TFrame.Focus method before calling Draw. The Focus method insures that the origin and clip region are properly set. If this is not called, you may find that drawing takes place in the wrong part of your view, or that you draw all over the scroll bars - which you will find to be both ugly and embarrassing.

The best technique is usually to have other methods invalidate a region or rectangle in the view, and then wait for an update event to force your view object to draw itself. It is, of course, perfectly O.K. to have your Draw method ask individual objects to draw themselves, as is done in the DrawShapes sample program. If you can’t wait for an update event, be sure to call Focus before calling Draw.

The mysterious command object

Command objects are very difficult for newcomers to MacApp to understand. People are usually pleased when I tell them that they can ignore command objects if they do not wish to implement Undo. Unfortunately, you should implement Undo for any operation that changes the data in a document, and therefore you often should use command objects.

What are command objects? They are merely temporary objects that save enough information so that the last operation can be undone. Keep in mind is that MacApp will call the methods of TCommand at certain times during the operation of your program. All you have to learn is when these methods will be called, and what any OVERRIDEs of these methods should do when they are called.

For example, MacApp will call the current command object’s DoIt method after a menu item is chosen by the user. All you have to do is create the command object in your DoMenuCommand method, and then have a DoIt method to do what you want done in response to that menu command. What could be easier? Don’t answer.

Some methods create command objects

This brings up another source of confusion. There are three common methods that create command objects: DoKeyCommand, DoMouseCommand, and DoMenuCommand. These are not methods of command objects, but merely methods that create new instances of command objects. For example, TYourView.DoMouseCommand may create an object of Type TSketcher, so it is TSketcher that needs a DoIt method, not TView.

Frames, views, and windows

It is easy to get confused as to the difference between a frame, a view, and a window. Consider the screen dump shown below in figure 4.

The resizable window contains a large, resizable frame which displays part of a view of type TParentView. There are three smaller frames installed in the large frame, and each frame has it’s own set of scroll bars (you can see that the scroll bars clearly belong to the frame, and not the window). Each frame displays part of a view, with the frame being a “porthole” through which the user can see part of what might be a very large view.

By the way, the key to handling more than one view in a window is to remember that each view lives in its own coordinate system, with each origin at (0,0). Resist the temptation to offset the origin just because the view will live in a frame in the middle of the window. The frame’s job is to take care of the origin - all the view needs to do is pretend it is the only view in the world.

Using TextEdit objects

It is easy to use a view of type TTEView, and create a cute little text editor with only a few lines of code. The tricky part is remembering to add UTEView to your USES statement in both your Unit and in the main program. If you forget this, you will get compiler error messages that mumble about there being no methods of that type for this object, and so forth. What we need is a compiler that says “Hey dummy, you forgot to add the UTEView Unit to the Uses statement!” Perhaps in version 2.0

When will MacApp call its methods, and will it ever call yours?

A major source of confusion has to do with how MacApp works. MacApp is based on hundreds of pages of source code, written in the OOP style, leading to what Howard Katz called “ a futile search for where the buck stops”. This means that newcomers to MacApp have to deal with a mysterious program that calls hundreds of its methods when it feels like it, and you often do not know when that is going to be. There is a rule to guide us, however.

The Rule: MacApp can only call methods that are defined as part of MacApp. This means that MacApp will call the DoMouseCommand method for a view, if that view is the “target”. This DoMouseCommand method will be the one provided with MacApp if you have not Overriden it, but it will be your DoMouseCommand if you have done an Override. The Rule also means that MacApp will never call the IYourDocument method that you created to initialize objects of type TYourDocument, because that method was unknown to the people who wrote MacApp. Remember Wilson’s Conjecture: MacApp is just computer code - its not magic.

The Rule, Part B: When you define new types of objects, with new methods, you are providing a set of tools for MacApp and you to use. When you Override an existing method, you are, in a sense, leaving that customized tool on the table for MacApp to use, and MacApp will generally use that tool when appropriate. When you define a method that is unique to your program, then MacApp cannot use that tool, so it is up to you to use it when necessary.

Fig. 4 MacApp in Operation

Andy Seligman’s Poem

The following poem was written by a student in the first MacApp class. It makes MacApp sound challenging, which it is, but it will show you that we have interesting and talented people learning MacApp.

There was a young hacker from Apple

Who haplessly started to grapple

With Windows and mice, and Inside Mac vice

He thought “User Friendly’s not nice!”

He told his boss of his confusion,

Who answered “I see that your usin’

Old coding technique, that’s now quite antique,

I’ll send you to class all next week!”

He went there to master MacApp,

but soon realized his mishap,

The instructor strode in and proclaimed with a grin

I can talk longer than you can listen!

He froze as he sat in the room,

and felt with a keen sense of gloom

“The problem with me, is I can not see

Which object sends what and to whom.”

He labored until his mind reeled,

through Object and Method and Field,

The class was sure great, but now he can’t wait,

To read Dave’s book MacApp Revealed!

Conclusion

What should we conclude from all this? I feel that MacApp is a bit tricky to learn to use, but I also feel that it is well worth the investment. I haven’t dwelled on the advantages to using MacApp in this article, but they are very compelling. MacApp’s value lies in four major areas:

(1) You can get a complete Mac application running in much less time than if you use a traditional development system,

(2) The user interface will conform very well to Apple’s recommendations,

(3) The MacApp code follows the compatibility guidelines, so that your application will run unchanged on everything from an old Mac 512K to a Macintosh II, and

(4) The program will be relatively bullet-proof, in that most errors will generally be trapped by the error handling routines. This latter point is often overlooked, but it is much better to present the user with an alert box that says that the window cannot be opened because of a lack of memory, instead of the program crashing with the dreaded bomb.

For those who might be interested in attending Apple’s monthly MPW and/or MacApp seminars, you should contact Karen Frazier at Apple for data sheets and prices. She can be reached at (408) 973-2726.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Hazel 5.3 - Create rules for organizing...
Hazel is your personal housekeeper, organizing and cleaning folders based on rules you define. Hazel can also manage your trash and uninstall your applications. Organize your files using a familiar... Read more
Duet 3.15.0.0 - Use your iPad as an exte...
Duet is the first app that allows you to use your iDevice as an extra display for your Mac using the Lightning or 30-pin cable. Note: This app requires a iOS companion app. Release notes were... Read more
DiskCatalogMaker 9.0.3 - Catalog your di...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast Finder-like intuitive look and feel Super-fast search algorithm Can compress catalog data for... Read more
Maintenance 3.1.2 - System maintenance u...
Maintenance is a system maintenance and cleaning utility. It allows you to run miscellaneous tasks of system maintenance: Check the the structure of the disk Repair permissions Run periodic scripts... Read more
Final Cut Pro 10.7 - Professional video...
Redesigned from the ground up, Final Cut Pro combines revolutionary video editing with a powerful media organization and incredible performance to let you create at the speed of thought.... Read more
Pro Video Formats 2.3 - Updates for prof...
The Pro Video Formats package provides support for the following codecs that are used in professional video workflows: Apple ProRes RAW and ProRes RAW HQ Apple Intermediate Codec Avid DNxHD® / Avid... Read more
Apple Safari 17.1.2 - Apple's Web b...
Apple Safari is Apple's web browser that comes bundled with the most recent macOS. Safari is faster and more energy efficient than other browsers, so sites are more responsive and your notebook... Read more
LaunchBar 6.18.5 - Powerful file/URL/ema...
LaunchBar is an award-winning productivity utility that offers an amazingly intuitive and efficient way to search and access any kind of information stored on your computer or on the Web. It provides... Read more
Affinity Designer 2.3.0 - Vector graphic...
Affinity Designer is an incredibly accurate vector illustrator that feels fast and at home in the hands of creative professionals. It intuitively combines rock solid and crisp vector art with... Read more
Affinity Photo 2.3.0 - Digital editing f...
Affinity Photo - redefines the boundaries for professional photo editing software for the Mac. With a meticulous focus on workflow it offers sophisticated tools for enhancing, editing and retouching... Read more

Latest Forum Discussions

See All

New ‘Zenless Zone Zero’ Trailer Showcase...
I missed this late last week, but HoYoverse released another playable character trailer for the upcoming urban fantasy action RPG Zenless Zone Zero. We’ve had a few trailers so far for playable characters, but the newest one focuses on Nicole... | Read more »
Get your heart pounding quicker as Autom...
When it comes to mobile battle royales, it wouldn’t be disrespectful to say the first ones to pop to mind would be PUBG Mobile, but there is one that perhaps doesn’t get the worldwide recognition it should and that's Garena’s Free Fire. Now,... | Read more »
‘Disney Dreamlight Valley Arcade Edition...
Disney Dreamlight Valley Arcade Edition () launches beginning Tuesday worldwide on Apple Arcade bringing a new version of the game without any passes or microtransactions. While that itself is a huge bonus for Apple Arcade, the fact that Disney... | Read more »
Adventure Game ‘Urban Legend Hunters 2:...
Over the weekend, publisher Playism announced a localization of the Toii Games-developed adventure game Urban Legend Hunters 2: Double for iOS, Android, and Steam. Urban Legend Hunters 2: Double is available on mobile already without English and... | Read more »
‘Stardew Valley’ Creator Has Made a Ton...
Stardew Valley ($4.99) game creator Eric Barone (ConcernedApe) has been posting about the upcoming major Stardew Valley 1.6 update on Twitter with reveals for new features, content, and more. Over the weekend, Eric Tweeted that a ton of progress... | Read more »
Pour One Out for Black Friday – The Touc...
After taking Thanksgiving week off we’re back with another action-packed episode of The TouchArcade Show! Well, maybe not quite action-packed, but certainly discussion-packed! The topics might sound familiar to you: The new Steam Deck OLED, the... | Read more »
TouchArcade Game of the Week: ‘Hitman: B...
Nowadays, with where I’m at in my life with a family and plenty of responsibilities outside of gaming, I kind of appreciate the smaller-scale mobile games a bit more since more of my “serious" gaming is now done on a Steam Deck or Nintendo Switch.... | Read more »
SwitchArcade Round-Up: ‘Batman: Arkham T...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for December 1st, 2023. We’ve got a lot of big games hitting today, new DLC For Samba de Amigo, and this is probably going to be the last day this year with so many heavy hitters. I... | Read more »
Steam Deck Weekly: Tales of Arise Beyond...
Last week, there was a ton of Steam Deck coverage over here focused on the Steam Deck OLED. | Read more »
World of Tanks Blitz adds celebrity amba...
Wargaming is celebrating the season within World of Tanks Blitz with a new celebrity ambassador joining this year's Holiday Ops. In particular, British footballer and movie star Vinnie Jones will be brightening up the game with plenty of themed in-... | Read more »

Price Scanner via MacPrices.net

Apple M1-powered iPad Airs are back on Holida...
Amazon has 10.9″ M1 WiFi iPad Airs back on Holiday sale for $100 off Apple’s MSRP, with prices starting at $499. Each includes free shipping. Their prices are the lowest available among the Apple... Read more
Sunday Sale: Apple 14-inch M3 MacBook Pro on...
B&H Photo has new 14″ M3 MacBook Pros, in Space Gray, on Holiday sale for $150 off MSRP, only $1449. B&H offers free 1-2 day delivery to most US addresses: – 14″ 8-Core M3 MacBook Pro (8GB... Read more
Blue 10th-generation Apple iPad on Holiday sa...
Amazon has Apple’s 10th-generation WiFi iPad (in Blue) on Holiday sale for $349 including free shipping. Their discount applies to WiFi models only and includes a $50 instant discount + $50 clippable... Read more
All Apple Pencils are on Holiday sale for $79...
Amazon has all Apple Pencils on Holiday sale this weekend for $79, ranging up to 39% off MSRP for some models. Shipping is free: – Apple Pencil 1: $79 $20 off MSRP (20%) – Apple Pencil 2: $79 $50 off... Read more
Deal Alert! Apple Smart Folio Keyboard for iP...
Apple iPad Smart Keyboard Folio prices are on Holiday sale for only $79 at Amazon, or 50% off MSRP: – iPad Smart Folio Keyboard for iPad (7th-9th gen)/iPad Air (3rd gen): $79 $79 (50%) off MSRP This... Read more
Apple Watch Series 9 models are now on Holida...
Walmart has Apple Watch Series 9 models now on Holiday sale for $70 off MSRP on their online store. Sale prices available for online orders only, in-store prices may vary. Order online, and choose... Read more
Holiday sale this weekend at Xfinity Mobile:...
Switch to Xfinity Mobile (Mobile Virtual Network Operator..using Verizon’s network) and save $500 instantly on any iPhone 15, 14, or 13 and up to $800 off with eligible trade-in. The total is applied... Read more
13-inch M2 MacBook Airs with 512GB of storage...
Best Buy has the 13″ M2 MacBook Air with 512GB of storage on Holiday sale this weekend for $220 off MSRP on their online store. Sale price is $1179. Price valid for online orders only, in-store price... Read more
B&H Photo has Apple’s 14-inch M3/M3 Pro/M...
B&H Photo has new Gray and Black 14″ M3, M3 Pro, and M3 Max MacBook Pros on Holiday sale this weekend for $100-$200 off MSRP, starting at only $1499. B&H offers free 1-2 day delivery to most... Read more
15-inch M2 MacBook Airs are $200 off MSRP on...
Best Buy has Apple 15″ MacBook Airs with M2 CPUs in stock and on Holiday sale for $200 off MSRP on their online store. Their prices are among the lowest currently available for new 15″ M2 MacBook... Read more

Jobs Board

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
Senior Product Manager - *Apple* - DISH Net...
…Responsibilities** We are seeking an ambitious, data-driven thinker to assist the Apple Product Development team as our Wireless Product division continues to grow Read more
Senior Product Manager - *Apple* - DISH Net...
…Responsibilities** We are seeking an ambitious, data-driven thinker to assist the Apple Product Development team as our Wireless Product division continues to grow Read more
Senior Software Engineer - *Apple* Fundamen...
…center of Microsoft's efforts to empower our users to do more. The Apple Fundamentals team focused on defining and improving the end-to-end developer experience in 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
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.