Using ARC in tweaks

From iPhone Development Wiki

What is ARC?

Quoting from the Wikipedia article on Automatic Reference Counting:

In Objective-C and Swift programming, Automatic Reference Counting (ARC) is a memory management enhancement where the burden of keeping track of an object's reference count is lifted from the programmer to the compiler. In traditional Objective-C, the programmer would send retain and release messages to objects in order to mark objects for deallocation or to prevent deallocation. Under ARC, the compiler does this automatically by examining the source code and then adding the retain and release messages in the compiled code.

How should I use ARC in tweaks?

For hooks

It is not recommended, unless if you absolutely know what you are doing. Hook methods are slightly different from your typical Objective-C class declarations, and as such, the compiler has a more limited concept of ownership due to the nature of these hooks. In most cases it would be totally fine, but there are certain cases where you would get unexpected behavior, so in general it ends up being less of a headache if you avoid ARC altogether. Also, typically with hook methods, the compiler sees you passing objective-C objects to and from vanilla C methods which requires (__bridge) casts which ends up being more annoying than manually managing memory.

For class declarations

If you are declaring new classes, or subclassing existing ones, then ARC will behave exactly as one would expect it to behave and it would be totally fine to use.

Generally speaking

However, even though using ARC for class declarations is A-OK, people still consider it to be a bad idea to use it at all. Generally, you never use ARC in your hook methods, so there ends up being this disconnect between your different implementation files, and the programmer ends up forgetting which files use ARC and which files don't. This inevitably leads to memory leaks. One example of this is when you write some code in a file that you thought uses ARC (but actually doesn't).

Plus, if you're using theos, you can't discern which files compile with ARC and which files don't. So your tweak file ends up being forced to use ARC.

So the gist of this is, for most cases: it's more trouble than it's worth.

How do I use ARC in tweaks?

Using theos (limited)

In your Makefile:

<TweakName>_CFLAGS = -fobjc-arc

Please note that this applies ARC to all files you are compiling including your tweak file.

If you only want to use ARC on specific files, you will need to separate the projects. NewTerm, for instance, uses ARC but contains external code that isn't ARC. The latter code is split into a library called libvt100.dylib, which the main NewTerm project then links against:

LIBRARY_NAME = libvt100
# ...
libvt100_INSTALL_PATH = /Applications/NewTerm.app

APPLICATION_NAME = NewTerm
# ...
NewTerm_CFLAGS = -fobjc-arc
NewTerm_LDFLAGS = -L$(THEOS_OBJ_DIR)
NewTerm_LIBRARIES = vt100

include $(THEOS_MAKE_PATH)/library.mk
include $(THEOS_MAKE_PATH)/application.mk

You should pick another install path if your project isn't an app; try /Library/Application Support/PackageName.


Without theos

This is how the flags would look like in a typical build process:

#optional: convert from logos to objective c
logos.pl tweak.x > tweak.m
#compile tweak without ARC
clang -c tweak.m -isysroot /path/to/sdk
#compile class declaration with ARC
clang -c YourClass.m -isysroot /path/to/sdk -fobjc-arc
#link to dylib
clang -o YouTweak.dylib -dynamiclib tweak.o YourClass.o -framework Foundation -framework UIKit -framework OtherFrameworkYoureUsing -isysroot /path/to/sdk