Module 'DeviceActivity' not found

I have a class that uses DeviceActivityMonitor as a subclass: // MyMonitor.swift

import DeviceActivity

@objc(MyMonitor)
class MyMonitor: DeviceActivityMonitor {
...
} 

In order to use SwiftUI in Objective-C, I'm importing this in my objective-c file #import "MyProject-Swift.h".

But, when I try to build, I get the error Module 'DeviceActivity' not found from wthin #import "MyProject-Swift.h"

I've tried "Link Binary with Libraries":

I've also tried to turn on Define Modules in Build Settings -> Packaging.

It just seems as though the DeviceActivity framework doesn't have a header file. Seems like it should? When I click "Show in Finder" in MyProject -> Frameworks -> DeviceAcitivity.framework, there is not DeviceActivity.h file in that dir (also not in the modules folder in my screenshot):

Is there a way to create a header file for an apple framework? Or force the creation of one?

I have also tried cleaning the build folder

Here's the framework for reference: https://developer.apple.com/documentation/DeviceActivity?changes=latest_major

Let me know if there's anything else I can describe to help. I'm new to this!

Answered by DTS Engineer in 738637022

The issue here is that, in most languages, including Objective-C, a class’s super class is part of the class’s public API. In your example the MyMonitor class has a public use of DeviceActivityMonitor, which means that Swift has to include the framework that exports that class, DeviceActivity, in the generated MyTestProject-Swift.h header. However, DeviceActivity is a Swift-only framework, and so everything falls apart.

One way around this is to add another layer of wrapping:

import Foundation
import DeviceActivity

@objc(ObjCMonitor)
class ObjCMonitor: NSObject {
    override init() {
        self.sm = SwiftMonitor()
    }
    private let sm: SwiftMonitor
}

private class SwiftMonitor: DeviceActivityMonitor {
}

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I was also able to reproduce this by creating a new barebones project, with adding only two files:

MyObjectiveC.m

#import "MyTestProject-Swift.h"

and MySwift.swift

import DeviceActivity import ManagedSettings import Foundation @objc(MyMonitor) class MyMonitor: DeviceActivityMonitor { }

I was also able to reproduce this by creating a new barebones project, with adding only two files:  "MyObjectiveC.m "

#import "MyTestProject-Swift.h" 

and "MySwift.swift" 

import DeviceActivity import ManagedSettings import Foundation @objc(MyMonitor) class MyMonitor: DeviceActivityMonitor { }

If there was a way to use SwiftUI without needing to import MyProject-Swift.h into ObjC, then I would be able to avoid this issue I think... But I can't find a way to do this

Maybe I have to create my own header for DeviceActivity... But that seems wrong

Accepted Answer

The issue here is that, in most languages, including Objective-C, a class’s super class is part of the class’s public API. In your example the MyMonitor class has a public use of DeviceActivityMonitor, which means that Swift has to include the framework that exports that class, DeviceActivity, in the generated MyTestProject-Swift.h header. However, DeviceActivity is a Swift-only framework, and so everything falls apart.

One way around this is to add another layer of wrapping:

import Foundation
import DeviceActivity

@objc(ObjCMonitor)
class ObjCMonitor: NSObject {
    override init() {
        self.sm = SwiftMonitor()
    }
    private let sm: SwiftMonitor
}

private class SwiftMonitor: DeviceActivityMonitor {
}

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

As Quinn suggested, you can add another layer of wrapping around your MyMonitor class. However, I don't see why you would need to use a DeviceActivityMonitor subclass in Objective-C code. The superclass is intended to be subclassed and used only in the context of your Device Activity monitor extension as the extension's principal class.

Module 'DeviceActivity' not found
 
 
Q