     
     
     /// export setting file to passed-in URL
-    func exportSetting(name: String, to fileURL: URL) throws {
+    final func exportSetting(name: String, to fileURL: URL) throws {
         
         let sourceURL = self.preparedURLForUserSetting(name: name)
         

    
    
    /// update internal cache data
    func updateCache(completionHandler: (() -> Void)? = nil) {  // @escaping
        
        let previousSettingNames = self.settingNames
        
        DispatchQueue.global().async { [weak self] in
            guard let strongSelf = self else { return }
            
            strongSelf.loadUserSettings()
            
            let didUpdateList = strongSelf.settingNames != previousSettingNames
            
            DispatchQueue.main.sync {
                if didUpdateList {
                    strongSelf.notifySettingListUpdate()
                }
                
                completionHandler?()
            }
        }
    }
    
    
    /// notify about a line-up update of managed setting files.
    func notifySettingListUpdate() {
        
        NotificationCenter.default.post(name: SettingFileManager.didUpdateSettingListNotification, object: self)
    }
    
    
    /// notify about change of a managed setting
    func notifySettingUpdate(oldName: String, newName: String) {
        
        NotificationCenter.default.post(name: SettingFileManager.didUpdateSettingNotification, object: self,
                                        userInfo: [SettingFileManager.NotificationKey.old: oldName,

    
    
    /// validate whether the setting name is valid (for a file name) and throw an error if not
    final func validate(settingName: String, originalName: String) throws {
        
        // just case difference is OK
        guard settingName.caseInsensitiveCompare(originalName) != .orderedSame else { return }
