Skip to content

Commit 45c4fe9

Browse files
author
Andy Johns
committed
Updates for XCode 9
1 parent 5882666 commit 45c4fe9

File tree

1 file changed

+77
-115
lines changed

1 file changed

+77
-115
lines changed

WebAppUpdater.swift

Lines changed: 77 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -18,239 +18,201 @@
1818
import Foundation
1919
import PredixMobileSDK
2020

21-
internal class WebAppUpdater
22-
{
21+
internal class WebAppUpdater {
2322
internal static let AppDocumentDirectoryFilesChangedNotification = "AppDocumentDirectoryFilesChangedNotification"
24-
fileprivate var source : DispatchSource!
25-
fileprivate var filesChangedObserver : NSObjectProtocol?
26-
fileprivate var foregroundingObserver : NSObjectProtocol?
27-
fileprivate var backgroundingObserver : NSObjectProtocol?
23+
fileprivate var source: DispatchSource!
24+
fileprivate var filesChangedObserver: NSObjectProtocol?
25+
fileprivate var foregroundingObserver: NSObjectProtocol?
26+
fileprivate var backgroundingObserver: NSObjectProtocol?
2827

29-
init()
30-
{
28+
init() {
3129
self.filesChangedObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: WebAppUpdater.AppDocumentDirectoryFilesChangedNotification), object: nil, queue: nil, using: {(_:Notification) -> Void in
3230
// we use a utility service class queue here so the file copy operation, which runs on a higher service class queue completes first.
3331
DispatchQueue.global(qos: DispatchQoS.QoSClass.utility).async(execute: {[unowned self] () -> Void in
3432
self.documentsUpdated()
3533
})
3634
})
37-
35+
3836
self.foregroundingObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationWillEnterForeground, object: nil, queue: nil, using: {(_:Notification) -> Void in
3937
self.startWatcher()
4038
})
41-
39+
4240
self.backgroundingObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationDidEnterBackground, object: nil, queue: nil, using: {(_:Notification) -> Void in
4341
self.stopWatcher()
4442
})
45-
43+
4644
startWatcher()
4745
}
48-
49-
deinit
50-
{
46+
47+
deinit {
5148
// cleanup our observer and file watcher.
52-
if let observer = self.filesChangedObserver
53-
{
49+
if let observer = self.filesChangedObserver {
5450
NotificationCenter.default.removeObserver(observer)
5551
self.filesChangedObserver = nil
5652
}
57-
if let observer = self.foregroundingObserver
58-
{
53+
if let observer = self.foregroundingObserver {
5954
NotificationCenter.default.removeObserver(observer)
6055
self.foregroundingObserver = nil
6156
}
62-
if let observer = self.backgroundingObserver
63-
{
57+
if let observer = self.backgroundingObserver {
6458
NotificationCenter.default.removeObserver(observer)
6559
self.backgroundingObserver = nil
6660
}
6761
stopWatcher()
6862
}
69-
70-
func startWatcher()
71-
{
63+
64+
func startWatcher() {
7265
Logger.info("Started watching documents directory for replacement WebApp files.")
73-
if let documentsUrl = self.getDocumentsUrl()
74-
{
66+
if let documentsUrl = self.getDocumentsUrl() {
7567
let fileDescriptor = open((documentsUrl as NSURL).fileSystemRepresentation, O_EVTONLY)
7668
let queue = DispatchQueue(label: "filewatcher_queue", attributes: [])
77-
self.source = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fileDescriptor, eventMask: DispatchSource.FileSystemEvent.write, queue: queue) /*Migrator FIXME: Use DispatchSourceFileSystemObject to avoid the cast*/ as! DispatchSource;
78-
69+
self.source = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fileDescriptor, eventMask: DispatchSource.FileSystemEvent.write, queue: queue) /*Migrator FIXME: Use DispatchSourceFileSystemObject to avoid the cast*/ as! DispatchSource
70+
7971
// call documentsUpdated if changes are detected.
8072
// schedule documentsUpdate as next event on the queue to give a chance for
8173
// any file IO to complete.
82-
self.source.setEventHandler(handler: {()->() in
74+
self.source.setEventHandler(handler: {() -> Void in
8375
NotificationCenter.default.post(name: Notification.Name(rawValue: WebAppUpdater.AppDocumentDirectoryFilesChangedNotification), object: nil)
8476
})
85-
77+
8678
// Cleanup when the source is canceled
8779
self.source.setCancelHandler(handler: {() in
88-
80+
8981
close(fileDescriptor)
9082
})
91-
83+
9284
// everything is setup, start watching
93-
self.source.resume();
85+
self.source.resume()
9486
}
9587
}
96-
97-
func stopWatcher()
98-
{
88+
89+
func stopWatcher() {
9990
Logger.info("Stopped watching documents directory for replacement WebApp files.")
100-
self.source.cancel();
91+
self.source.cancel()
10192
}
102-
103-
func documentsUpdated()
104-
{
93+
94+
func documentsUpdated() {
10595
Logger.info("Changes detected in the Documents directory")
106-
107-
if let documentsURL = self.getDocumentsUrl()
108-
{
109-
for subDirectoryURL in self.getSubdirectories(documentsURL)
110-
{
96+
97+
if let documentsURL = self.getDocumentsUrl() {
98+
for subDirectoryURL in self.getSubdirectories(documentsURL) {
11199
// match subdirectories in the Documents folder, with loaded webapp names.
112-
if let webAppLocation = self.getWebAppURL(subDirectoryURL.lastPathComponent)
113-
{
100+
if let webAppLocation = self.getWebAppURL(subDirectoryURL.lastPathComponent) {
114101
self.copyFilesFromURL(subDirectoryURL, toURL: webAppLocation)
115102
}
116103
}
117104
}
118105
}
119-
106+
120107
// Helper function, enumerates a directory, calling onEachItem closure for each item in the directory.
121108
// includingPropertiesForKeys can effect the metadata resources retreived: xcdoc://?url=developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFURLRef/index.html#//apple_ref/doc/constant_group/Common_File_System_Resource_Keys
122109
// options can be used to specify what items are included: xcdoc://?url=developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/index.html#//apple_ref/c/tdef/NSDirectoryEnumerationOptions
123110
//
124-
func enumerateItemsInDirectoryURL(_ URL: Foundation.URL, includingPropertiesForKeys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions, onEachItem: (Foundation.URL)->())
125-
{
126-
127-
if let urlEnumerator = FileManager.default.enumerator(at: URL, includingPropertiesForKeys: includingPropertiesForKeys, options: options, errorHandler: {(errURL: Foundation.URL, error: Error)->(Bool) in
111+
func enumerateItemsInDirectoryURL(_ URL: Foundation.URL, includingPropertiesForKeys: [URLResourceKey]?, options: FileManager.DirectoryEnumerationOptions, onEachItem: (Foundation.URL) -> Void) {
112+
113+
if let urlEnumerator = FileManager.default.enumerator(at: URL, includingPropertiesForKeys: includingPropertiesForKeys, options: options, errorHandler: {(errURL: Foundation.URL, error: Error) -> (Bool) in
128114
Logger.error("Error enumerating URL: \(errURL) : \(error)")
129115
return true
130-
})
131-
{
132-
for case let subURL as Foundation.URL in urlEnumerator
133-
{
116+
}) {
117+
for case let subURL as Foundation.URL in urlEnumerator {
134118
onEachItem(subURL)
135119
}
136120
}
137121
}
138-
122+
139123
// Helper function. Returns array of subdirectories in provided directory as NSURLs
140-
func getSubdirectories(_ url: URL) -> ([URL])
141-
{
142-
var subDirectories : [URL] = []
124+
func getSubdirectories(_ url: URL) -> ([URL]) {
125+
var subDirectories: [URL] = []
143126
let keys = [URLResourceKey.isDirectoryKey]
144127

145128
// get a shallow enumerator for this directory, skipping hidden files
146129

147-
self.enumerateItemsInDirectoryURL(url, includingPropertiesForKeys: keys, options: [.skipsSubdirectoryDescendants,.skipsHiddenFiles]) { (itemURL: URL) -> () in
148-
130+
self.enumerateItemsInDirectoryURL(url, includingPropertiesForKeys: keys, options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles]) { (itemURL: URL) -> Void in
131+
149132
// get the resource property for this item, and check if it's a directory
150-
if let resourceValues = try? (itemURL as NSURL).resourceValues(forKeys: keys), let isDirectory = resourceValues[URLResourceKey.isDirectoryKey] as? Bool, isDirectory
151-
{
133+
if let resourceValues = try? (itemURL as NSURL).resourceValues(forKeys: keys), let isDirectory = resourceValues[URLResourceKey.isDirectoryKey] as? Bool, isDirectory {
152134
subDirectories.append(itemURL)
153135
}
154136
}
155-
137+
156138
return subDirectories
157139
}
158-
140+
159141
// Performs the actual file copy.
160-
func copyFilesFromURL(_ fromURL: URL, toURL: URL)
161-
{
142+
func copyFilesFromURL(_ fromURL: URL, toURL: URL) {
162143
// There are two ways to go with this. We could copy fromURL to toURL entirely. This would be a single quick operation,
163144
// however, if would completely replace toURL. Any files under toURL not under fromURL, would be deleted.
164145
// In this case we want to be "gentler". Matching files will be replaced, new files will be copied, but
165146
// any missing files will not be deleted. This will allow the web developer to just drop in updates, rather than a complete
166147
// replacement directory structure.
167-
148+
168149
print("\(#function): fromURL: \(fromURL.path) toURL: \(toURL.path)")
169-
150+
170151
let keys = [URLResourceKey.isDirectoryKey]
171-
172-
self.enumerateItemsInDirectoryURL(fromURL, includingPropertiesForKeys: keys, options: [.skipsSubdirectoryDescendants,.skipsHiddenFiles]) { (itemURL:URL) -> () in
152+
153+
self.enumerateItemsInDirectoryURL(fromURL, includingPropertiesForKeys: keys, options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles]) { (itemURL: URL) -> Void in
173154

174155
Logger.trace("File: \(itemURL.path)")
175-
156+
176157
let targetURL = toURL.appendingPathComponent(itemURL.lastPathComponent)
177158

178159
let fileExists = FileManager.default.fileExists(atPath: targetURL.path)
179-
160+
180161
// inspect each URL to determine if it's a file or directory
181-
if let resourceValues = try? (itemURL as NSURL).resourceValues(forKeys: keys), let isDirectory = resourceValues[URLResourceKey.isDirectoryKey] as? Bool, isDirectory
182-
{
162+
if let resourceValues = try? (itemURL as NSURL).resourceValues(forKeys: keys), let isDirectory = resourceValues[URLResourceKey.isDirectoryKey] as? Bool, isDirectory {
183163
// we have a directory....
184-
164+
185165
if !fileExists // directory is new, need to create it.
186166
{
187-
do
188-
{
167+
do {
189168
Logger.trace("Creating directory: \(targetURL.path)")
190169
try FileManager.default.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil)
191-
}
192-
catch let error
193-
{
170+
} catch let error {
194171
Logger.error("Error creating subdirectory: \(targetURL) : \(error)")
195172
}
196173
}
197-
174+
198175
// recurse this subdirectory
199176
self.copyFilesFromURL(itemURL, toURL: targetURL)
200-
201-
}
202-
else
203-
{
177+
178+
} else {
204179
// we have a file -- replace or copy it
205-
if fileExists
206-
{
180+
if fileExists {
207181
Logger.trace("Replacing file: \(targetURL.path) with file: \(itemURL.path)")
208-
do
209-
{
182+
do {
210183
try FileManager.default.replaceItem(at: targetURL, withItemAt: itemURL, backupItemName: nil, options: [.usingNewMetadataOnly], resultingItemURL: nil)
211-
}
212-
catch let error
213-
{
184+
} catch let error {
214185
Logger.error("Error replacing file: \(targetURL) : \(error)")
215186
}
216-
}
217-
else
218-
{
187+
} else {
219188
Logger.trace("Copying file: \(itemURL.path) to file: \(targetURL.path)")
220-
do
221-
{
189+
do {
222190
try FileManager.default.copyItem(at: itemURL, to: targetURL)
223-
}
224-
catch let error
225-
{
191+
} catch let error {
226192
Logger.error("Error copying file: \(targetURL) : \(error)")
227193
}
228194
}
229-
195+
230196
}
231-
197+
232198
}
233199
}
234-
235-
200+
236201
// Helper function, gets the App's Documents directory, where iTunes file drops are stored.
237-
func getDocumentsUrl()->URL?
238-
{
202+
func getDocumentsUrl() -> URL? {
239203
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
240204
}
241-
205+
242206
// Helper function, returns the URL for the given webapp name, if it exists.
243-
func getWebAppURL(_ webAppName : String?) -> (URL?)
244-
{
207+
func getWebAppURL(_ webAppName: String?) -> (URL?) {
245208
guard let webAppName = webAppName else {return nil}
246-
247-
if let userURL = PredixMobilityConfiguration.userLocalStorageURL
248-
{
209+
210+
if let userURL = PredixMobilityConfiguration.userLocalStorageURL {
249211
let webappLocation = userURL.appendingPathComponent("WebApps").appendingPathComponent(webAppName)
250-
212+
251213
return self.getSubdirectories(webappLocation).first
252214
}
253-
215+
254216
return nil
255217
}
256218
}

0 commit comments

Comments
 (0)