Hello! Rookie Swift developer here!
I am trying to make an app that uses the Screen Time API to block a list of websites. Specifically, I want it to take a list of web domains in String format and restrict them instead of using the FamilyActivityPicker. So far, I have been unsuccessful.
When using the FamilyActivityPicker, I have been able to restrict websites by modifying the shield instance variable of the ManagedSettingsStore.
let store = ManagedSettingsStore()
// Got selection from familyActivityPicker.
store.shield.webDomains = selection.webDomainTokens
"store.shield.webDomains" is of type "Set<Token>" and as far as I know, you can create a WebDomain struct with a String url but not Token. I was only able to get a token using the FamilyActivityPicker.
Hence, I was wondering if it was even possible to do this and if so, how you'd go about it. Thanks!
Post
Replies
Boosts
Views
Activity
Hello!
I'm new to iOS development and am developing an app that blocks certain websites. At the moment, I'm thinking of using the Network Extension capability to do the job. From what I have read, in the production version of the app, you'd need to make use of MDM profiles since NE filtering only works on supervised devices. So, I'm here to ask the community if there are better options than using this method.
As far as screen time api is concerned, I believe it requires the user to specify which websites they want blocked by themselves using the activity picker so that doesn't quite work for me since i want to allow the app to block groups of websites by itself based on the user's preference.
Thanks!
Hello! New to swift development.
I've created a very basic iOS app that uses the network extension to block web domains.
Now, I am trying to make it work on a macOS using Mac Catalyst. However, when I build the project, I get this error:
2023-09-08 23:31:32.540010+0600 controlShift[69583:2468143] [Metadata] unable to get a dev_t for store 1795162192.
2023-09-08 23:31:33.986014+0600 controlShift[69583:2467453] [] -[NEFilterManager saveToPreferencesWithCompletionHandler:]_block_invoke_3: failed to save the new configuration: (null)
The app launches and the UI works correctly. However, it fails to save the preference as stated in the error, so it does not block anything.
Here is the relevant part of the code in the root file:
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.onAppear {
NEFilterManager.shared().loadFromPreferences { error in
if let loadError = error {
print("Failed to load the filter configuration: \(loadError)")
return
}
}
DispatchQueue.main.asyncAfter(deadline: .now()+1.5) {
if NEFilterManager.shared().providerConfiguration == nil {
let newConfiguration = NEFilterProviderConfiguration()
newConfiguration.username = "UserName"
newConfiguration.organization = "myApp "
newConfiguration.filterBrowsers = true
newConfiguration.filterSockets = true
newConfiguration.serverAddress = "http://192.168.100.48:3000"
NEFilterManager.shared().providerConfiguration = newConfiguration
}
NEFilterManager.shared().isEnabled = true
NEFilterManager.shared().saveToPreferences { error in
if let saveError = error {
print("Failed to save the filter configuration: \(saveError)")
}
}
}
}
}
I'm at a loss for what is wrong. Lmk if you need additional details. Thanks!
btw, I am very new to swift and iOS/macOS development in general so if there's a better way to write or structure the logic inside the "onAppear" method (of which I'm sure there is), lmk as well. ^_^
Hi! I've been working on a project that requires firebase. I have version 10.15 installed.
The issue is that Xcode gives me this error sometimes when I try to import FirebaseCore: No such module 'FirebaseCore'
However, I don't get this error in some other Swift file in the same project.
Why is this and how do I solve this issue? Thanks.
Hi! I'm having this issue that wasn't present before in this project.
In my app's entry file, which is named 'controlShiftApp.swift' and NOT 'main.swift' (which has been documented to cause the same error), the @main attribute gives the following error:
'main' attribute cannot be used in a module that contains top-level code
I have no other files named main.swift in this target. I only have main.swift in the targets for system extensions. I also haven't used @main anywhere else in this project. Here is a screenshot to show you what I mean.
I'd really appreciate inputs on this matter. I need to get this fixed so that I can continue my development ASAP. Also, I'm new to Swift so many things are not as trivial to me, and I would like it if you could give me clear steps on how to resolve this. Thanks!
Hello!
I made an iOS app for a research study that blocks network connections with certain websites. I need to block around 2000 web domains. To achieve this, I had two options:
Use Screentime API
Use Network Extension
Screentime API has a limitation that limits the number of websites it can block to 50 (https://developer.apple.com/documentation/managedsettings/webcontentsettings/blockedbyfilter-swift.property).
The Network Extension on the other hand requires my device to be in supervised mode, which as I understand it, involves erasing the data on the phone and resetting it.
Hence, I am here to ask if there is a way to do this without erasing user data when setting the device into supervised mode.
Also, I am open to hearing any other alternatives I could pursue. Thanks!!
Hello!
I have never distributed an apple app before. Right now, I am trying to distribute a macOS app. I created a provisioning profile of type "Developer ID Application" and it has the following capabilities enabled.
Now, when I download the profile and use it for my app, xcode gives me the following error:
Lmk what I need to do since I am super unfamiliar with this process.
Hello!
I created a simple DNS filter application for iOS but the extension is not launching. I am getting this log message in the console.
Failed to start extension edu.stanford.stilakid.testDnsFilter.DNSFiltering: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named edu.stanford.stilakid.testDnsFilter.DNSFiltering.apple-extension-service" UserInfo={NSDebugDescription=connection to service named edu.stanford.stilakid.testDnsFilter.DNSFiltering.apple-extension-service}
For another project with the same code for dns filtering but different bundleID, I also got the following log message.
Failed to start extension edu.stanford.sml.rdahlke.controlShift.DNSProxy: Error Domain=PlugInKit Code=4 "RBSLaunchRequest error trying to launch plugin edu.stanford.sml.rdahlke.controlShift.DNSProxy(D26CD63C-4656-4A30-99A0-7C867265DD75): Error Domain=RBSRequestErrorDomain Code=5 "Launch failed." UserInfo={NSLocalizedFailureReason=Launch failed., NSUnderlyingError=0xc62b8c0d0 {Error Domain=NSPOSIXErrorDomain Code=111 "Unknown error: 111" UserInfo={NSLocalizedDescription=Launchd job spawn failed}}}" UserInfo={NSLocalizedDescription=RBSLaunchRequest error trying to launch plugin edu.stanford.sml.rdahlke.controlShift.DNSProxy(D26CD63C-4656-4A30-99A0-7C867265DD75): Error Domain=RBSRequestErrorDomain Code=5 "Launch failed." UserInfo={NSLocalizedFailureReason=Launch failed., NSUnderlyingError=0xc62b8c0d0 {Error Domain=NSPOSIXErrorDomain Code=111 "Unknown error: 111" UserInfo={NSLocalizedDescription=Launchd job spawn failed}}}}
Also, the log messages I have defined inside the constructor of the dns proxy extension is nowhere to be found in the logs, so I am pretty sure the extension is failing to launch.
The debugger attached to the main target app shows no errors as well, so it is able to load and update dnsProtocol.
Here is the code:
// DNSProxyProvider.swift
// DNSFiltering
//
// Created by Juben Rana on 2/20/24.
//
import NetworkExtension
import os.log
class DNSProxyProvider: NEDNSProxyProvider {
// MARK: - Logger
static let logger = Logger(subsystem: "edu.stanford.sml.rdahlke.controlShift", category: "dns-filter")
override init() {
Self.logger.log(level: .debug, "TestDns: dns proxy provider will init")
self.logger = Self.logger
super.init()
}
let logger: Logger
override func startProxy(options:[String: Any]? = nil, completionHandler: @escaping (Error?) -> Void) {
// Add code here to start the DNS proxy.
logger.log(level: .debug, "TestDns: proxy will start")
completionHandler(nil)
}
override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
// Add code here to stop the DNS proxy.
logger.log(level: .debug, "TestDns: proxy will stop")
completionHandler()
}
override func sleep(completionHandler: @escaping () -> Void) {
// Add code here to get ready to sleep.
completionHandler()
}
override func wake() {
// Add code here to wake up.
}
override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
// Add code here to handle the incoming flow.
logger.log(level: .debug, "TestDns: proxy is handling flow")
return false
}
}
// ContentView.swift
// testDnsFilter
//
// Created by Juben Rana on 2/20/24.
//
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
// LoginScreen()
// .onOpenURL { url in
// GIDSignIn.sharedInstance.handle(url)
// }
Spacer()
#if os(macOS)
Text("I'm running on macOS")
#else
Text("I'm running on iOS")
#endif
Spacer()
Button("Activate") {
#if os(macOS)
ContentFilterMac.shared.activate()
#elseif os(iOS)
ContentFilter.shared.enable()
#endif
}
Spacer()
Button("Deactivate") {
#if os(macOS)
ContentFilterMac.shared.deactivate()
#elseif os(iOS)
ContentFilter.shared.disable()
#endif
}
Spacer()
Spacer()
}
.padding()
}
}
#Preview {
ContentView()
}
//
// ContentFilter.swift
// controlShift
//
// Created by Juben Rana on 9/28/23.
//
// This is only for macOS
import Foundation
import NetworkExtension
import os.log
// MARK: - Content Filter
class ContentFilter {
// MARK: - Set Up
static let shared = ContentFilter()
private init() {
Self.logger.log(level: .debug, "content filter will init")
self.logger = Self.logger
}
// MARK: - Logger
static let logger = Logger(subsystem: "edu.stanford.stilakid.testDnsFilter", category: "content-filter")
let logger: Logger
// MARK: - DNS Filter
private let manager = NEDNSProxyManager.shared()
func enable() {
loadAndUpdatePreferences {
self.manager.localizedDescription = "DNSProxySample"
let dnsProtocol = NEDNSProxyProviderProtocol()
dnsProtocol.providerBundleIdentifier = "edu.stanford.stilakid.testDnsFilter.DNSFiltering"
self.manager.providerProtocol = dnsProtocol
self.manager.isEnabled = true
}
}
func disable() {
loadAndUpdatePreferences {
self.manager.isEnabled = false
}
}
private func loadAndUpdatePreferences(_ completion: @escaping () -> Void) {
manager.loadFromPreferences { error in
guard error == nil else {
debugPrint("DNSProxySample.App: load error")
return
}
completion()
self.manager.saveToPreferences { (error) in
guard error == nil else {
debugPrint("DNSProxySample.App: save error")
return
}
debugPrint("DNSProxySample.App: saved")
}
}
}
}
Hello.
Can someone please explain to me what "per-app" means in "per-app on managed devices" in the context of this document(https://developer.apple.com/documentation/technotes/tn3134-network-extension-provider-deployment)?
Thank you!
Hello.
We are working on a flutter project using the same unique iOS app bundle id in all of our team's local repo. Only one of us is enrolled in an individual Apple Developer Program.
The app runs properly for at least 3 of us while others are getting the error that the bundle ID is not available. Given that it the 3 of us did not require a unique bundle ID in each of our local copies, do you know how to resolve this issue?
Also, it would be helpful if you could share how to handle the issue of requiring a unique bundle ID for flutter projects if our team is not enrolled in the Apple Developer Enterprise program.
Hello!
I am part of a research team who need advice on how to track and intercept network requests from a device.
More specifically, we are interested in collecting the websites the research participants have tried to access. We want something like what YouGov does with their Pulse App.
Also, is it possible to implement this without having to rely on an external server that acts as a intermediary?
How do we achieve this? We'd appreciate a detailed response with helpful links to how to implement it. Thank you very much for your time.