Xcode 4.2 with Arc: Will My Code Run Even on iOS Devices with Firmware Older Than 5.0

Xcode 4.2 with ARC: will my code run even on iOS devices with firmware older than 5.0?

ARC applications will run on OS 4.0 (4.3?) and up. On 4.3 you will lose the zeroing-weak-reference feature though. So if you rely on __weak, you shouldn't expect to work properly on < 5.0.

iOS automatic reference counting (ARC) backward compatibility?

ARC is (with some limitations) backward compatible to iOS 4.
http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/_index.html

ARC is supported in Xcode 4.2 for Mac OS X v10.6 and v10.7 (64-bit
applications) and for iOS 4 and iOS 5. Weak references are not
supported in Mac OS X v10.6 and iOS 4.

Does iOS 4.3 support ARC

Transitioning to ARC:

ARC is supported in Xcode 4.2 for Mac OS X v10.6 and v10.7 (64-bit applications) and for iOS 4 and iOS 5. Weak references are not supported in Mac OS X v10.6 and iOS 4.

Will an ARC application run on iOS 3.2?

Well, it runs on iOS 3.2 for iPad at least. I've encountered this for other things, where the documentation says it only works for such-and-such a version, but it works for earlier versions at well.

What are the advantages and disadvantages of using ARC?

What are the advantages and disadvantages of using the new automatic reference counting (ARC) memory management style in an iOS project?

An ARC program's execution is nearly identical to well written MRC. That is, the behavioral differences are often undetectable because both the order of operations and performance are very close.

If you already know how to implement OS X or iOS apps with manual reference counting (MRC), ARC doesn't really add functionality -- it just allows you to remove reference counting operations from your sources.

If you don't want to learn MRC, then you may want to first try ARC. A lot of people struggle with, or try to ignore common practices of MRC (example: I've introduced a number of objc devs to the static analyzer). If you want to avoid those issues, ARC will allow you to postpone your understanding; you cannot write nontrivial objc programs without understanding reference counting and object lifetimes and relationships, whether MRC, ARC, or GC. ARC and GC simply remove the implementation from your sources and do the right thing in most cases. With ARC and GC, you will still need to give some guidance.

I've not measured this, but it may be worth mentioning that compiling ARC sources would take more time and resources.

If the program you're developing has rather loose usage of reference counting (e.g. a typical amount of autoreleases), switching to ARC could really improve your program's execution times and peak memory usage.

Can you choose not to use ARC when developing with the iOS 5.0 SDK?

Yes, using CLANG_ENABLE_OBJC_ARC. ARC is binary compatible, and all that really happens is that the compiler does its best to introduce the appropriate reference counting operations automatically for you, based on the declarations visible to the current translation (see my answer here as to why translation visibility is important). Therefore, you can also enable and disable it for some sources in a project and enable it for others.

Mixed mode (some MRC and some ARC sources) is however quite complicated, and subtly, notably wrt implementations which may be duplicated by the compiler (e.g. an inline function's body may be incorrect). Such mixed mode issues will be very difficult to isolate. ObjC++ programs and sources will be particularly difficult in this regard. Furthermore, the behavior may differ based on your optimizations settings (as one example); a program which works perfectly in a debug build may introduce a leak or zombie in release.

Do you recommend ARC or manual reference counting (MRC) for a new project?

Personally, I'll be sticking with MRC for some time. Even if ARC has been tested in real world usage, it's likely that there are a number issues remaining which show up in complex scenarios, which you will want to avoid being the first to know and debug. OS X's Garbage Collection is an example of why you may want to wait. As one example, the switch could alter when objects are destroyed -- your objects may be destroyed sooner and never be placed in autorelease pools. It could also change the order in which ivars are released, which could have some side effects.

I also have a large codebase that I don't want to lose a week testing this feature for at this time. Finally, backwards compatibility is still important for me.

Will an application using ARC be able to run on older OS versions than iOS 5.0?

If you develop with MRC, it will be backwards compatible. If you develop with ARC, it will not necessarily be compatible. In fact, it may not even compile without a little extra work. The requirements for the runtime are available in some earlier versions. See also this question. If you need backwards compatibility, ARC will not be an option for some OS versions.

Lastly, if you were to limit the choice to GC or ARC, I'd recommend ARC.

Version vs build in Xcode

Apple sort of rearranged/repurposed the fields.

Going forward, if you look on the Info tab for your Application Target, you should use the "Bundle versions string, short" as your Version (e.g., 3.4.0) and "Bundle version" as your Build (e.g., 500 or 1A500). If you don't see them both, you can add them. Those will map to the proper Version and Build textboxes on the Summary tab; they are the same values.

When viewing the Info tab, if you right-click and select Show Raw Keys/Values, you'll see the actual names are CFBundleShortVersionString (Version) and CFBundleVersion (Build).

The Version is usually used how you appear to have been using it with Xcode 3. I'm not sure on what level you're asking about the Version/Build difference, so I'll answer it philosophically.

There are all sorts of schemes, but a popular one is:

{MajorVersion}.{MinorVersion}.{Revision}

  • Major version - Major changes, redesigns, and functionality
    changes
  • Minor version - Minor improvements, additions to functionality
  • Revision - A patch number for bug-fixes

Then the Build is used separately to indicate the total number of builds for a release or for the entire product lifetime.

Many developers start the Build number at 0, and every time they build they increase the number by one, increasing forever. In my projects, I have a script that automatically increases the build number every time I build. See instructions for that below.

  • Release 1.0.0 might be build 542. It took 542 builds to get to a
    1.0.0 release.
  • Release 1.0.1 might be build 578.
  • Release 1.1.0 might be build 694.
  • Release 2.0.0 might be build 949.

Other developers, including Apple, have a Build number comprised of a major version + minor version + number of builds for the release. These are the actual software version numbers, as opposed to the values used for marketing.

If you go to Xcode menu > About Xcode, you'll see the Version and Build numbers. If you hit the More Info... button you'll see a bunch of different versions. Since the More Info... button was removed in Xcode 5, this information is also available from the Software > Developer section of the System Information app, available by opening Apple menu > About This Mac > System Report....

For example, Xcode 4.2 (4C139). Marketing version 4.2 is Build major version 4, Build minor version C, and Build number 139. The next release (presumably 4.3) will likely be Build release 4D, and the Build number will start over at 0 and increment from there.

The iPhone Simulator Version/Build numbers are the same way, as are iPhones, Macs, etc.

  • 3.2: (7W367a)
  • 4.0: (8A400)
  • 4.1: (8B117)
  • 4.2: (8C134)
  • 4.3: (8H7)

Update: By request, here are the steps to create a script that runs each time you build your app in Xcode to read the Build number, increment it, and write it back to the app's {App}-Info.plist file. There are optional, additional steps if you want to write your version/build numbers to your Settings.bundle/Root*.plist file(s).

This is extended from the how-to article here.

In Xcode 4.2 - 5.0:

  1. Load your Xcode project.
  2. In the left hand pane, click on your project at the very top of the hierarchy. This will load the project settings editor.
  3. On the left-hand side of the center window pane, click on your app under the TARGETS heading. You will need to configure this setup for each project target.
  4. Select the Build Phases tab.
    • In Xcode 4, at the bottom right, click the Add Build Phase button and select Add Run Script.
    • In Xcode 5, select Editor menu > Add Build Phase > Add Run Script Build Phase.
  5. Drag-and-drop the new Run Script phase to move it to just before the Copy Bundle Resources phase (when the app-info.plist file will be bundled with your app).
  6. In the new Run Script phase, set Shell: /bin/bash.
  7. Copy and paste the following into the script area for integer build numbers:

    buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
    buildNumber=$(($buildNumber + 1))
    /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"

    As @Bdebeez pointed out, the Apple Generic Versioning Tool (agvtool) is also available. If you prefer to use it instead, then there are a couple things to change first:

    • Select the Build Settings tab.
    • Under the Versioning section, set the Current Project Version to the initial build number you want to use, e.g., 1.
    • Back on the Build Phases tab, drag-and-drop your Run Script phase after the Copy Bundle Resources phase to avoid a race condition when trying to both build and update the source file that includes your build number.

    Note that with the agvtool method you may still periodically get failed/canceled builds with no errors. For this reason, I don't recommend using agvtool with this script.

    Nevertheless, in your Run Script phase, you can use the following script:

    "${DEVELOPER_BIN_DIR}/agvtool" next-version -all

    The next-version argument increments the build number (bump is also an alias for the same thing), and -all updates Info.plist with the new build number.

  8. And if you have a Settings bundle where you show the Version and Build, you can add the following to the end of the script to update the version and build. Note: Change the PreferenceSpecifiers values to match your settings. PreferenceSpecifiers:2 means look at the item at index 2 under the PreferenceSpecifiers array in your plist file, so for a 0-based index, that's the 3rd preference setting in the array.

    productVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$INFOPLIST_FILE")
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:2:DefaultValue $buildNumber" Settings.bundle/Root.plist
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $productVersion" Settings.bundle/Root.plist

    If you're using agvtool instead of reading the Info.plist directly, you can add the following to your script instead:

    buildNumber=$("${DEVELOPER_BIN_DIR}/agvtool" what-version -terse)
    productVersion=$("${DEVELOPER_BIN_DIR}/agvtool" what-marketing-version -terse1)
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:2:DefaultValue $buildNumber" Settings.bundle/Root.plist
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $productVersion" Settings.bundle/Root.plist
  9. And if you have a universal app for iPad & iPhone, then you can also set the settings for the iPhone file:

    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:2:DefaultValue $buildNumber" Settings.bundle/Root~iphone.plist    
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $productVersion" Settings.bundle/Root~iphone.plist


Related Topics



Leave a reply



Submit