Did you end up with 2 projects, one being a framework, the other being the app?
No. I had a single project with two targets.
The framework contains the
#if LOG ...
but the app project is where you would set
LOG
in the
SWIFT_ACTIVE_COMPILATION_CONDITIONS
.
After reading your message, I think I've got this around the wrong way.
Indeed. Remember that frameworks are built binaries, so the Active Compilation Conditions has to be set when that binary is built, that is, in the framework target (or project, if you’re using separate projects). Setting it in the app target only affects the built app, and your app contains no code that depends on it.
I think I should expose a global property out of the Framework that enables the logging based on the
SWIFT_ACTIVE_COMPILATION_CONDITIONS
in the app.
That’s one option. The main drawback to this approach is that the logging code all gets compiled into your framework, so if that code is large then your framework is unnecessarily large. As I’ve no idea how much logging you’re doing, you’ll have to make that call yourself.
Is this a better way of address the problem?
If you’re OK with the logging code being compiled into your framework, you have some other options, as discussed below.
Also, do you have any info on the Activity tracing for Unified logging in Swift?
I’m not sure whether you’re talking about
OSLog
here? In which case, yes, that has a Swift wrapper as I’ve discussed below. However, if you’re asking about activity tracing specifically, I’ve not looked at that recently.
You can inject an
OSLog
object into your framework, or into the object’s vended by your framework. Your framework can then log to that object always, relying on the fact that
OSLog
is super efficient if the logging is disabled.
So your framework code might look like this:
import os.log
var log: OSLog = .disabled
and inside your framework you can log like this:
// If you’re deploying to the very latest systems, use the very latest
// `os_log` function.
os_log(.default, log: log, "Hello Cruel World!")
// If not, use the older version.
os_log("Hello Cruel World!", log: log, type: .default)
Your client code can then tell the framework to log by changing the
log
global variable to something more appropriate.
MyFramework.log = OSLog(subsystem: "com.example.MyApp", category: "MyFramework")
This approach has a bunch of advantages:
You can do a similar thing on an object-by-object basis. So if you have an object exported from your framework, you can add a
log
property to that and then the client can control its logging directly.
Another option is to have your framework, or the object’s vended by your framework, have a delegate that they call to log. This gives the client complete control.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"