From b9729bdfe495f7d34aa48915e7302a353fc2f720 Mon Sep 17 00:00:00 2001 From: Craig Rouse Date: Thu, 13 Jun 2019 18:19:13 +0100 Subject: [PATCH] 0.6.4 watchOS, tvOS, macOS support Added watchOS, tvOS, macOS support. --- Disk.podspec | 5 +- Disk.xcodeproj/project.pbxproj | 24 +- .../xcshareddata/IDEWorkspaceChecks.plist | 8 + DiskExample/Common/GetPosts.swift | 46 + .../{DiskExample => Common}/Post.swift | 0 .../DiskExample.xcodeproj/project.pbxproj | 621 ++++++++++++- .../xcschemes/DiskIOSExample.xcscheme | 91 ++ .../AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../Base.lproj/LaunchScreen.storyboard | 0 .../Base.lproj/Main.storyboard | 31 +- .../Info.plist | 0 .../ViewController.swift | 55 +- DiskExample/DiskMacExample/AppDelegate.swift | 26 + .../AppIcon.appiconset/Contents.json | 58 ++ .../Assets.xcassets/Contents.json | 6 + .../DiskMacExample/Base.lproj/Main.storyboard | 842 ++++++++++++++++++ .../DiskMacExample.entitlements | 12 + DiskExample/DiskMacExample/Info.plist | 32 + .../DiskMacExample/ViewController.swift | 125 +++ DiskExample/DiskTVExample/AppDelegate.swift | 46 + .../Content.imageset/Contents.json | 11 + .../Back.imagestacklayer/Contents.json | 6 + .../Contents.json | 17 + .../Content.imageset/Contents.json | 11 + .../Front.imagestacklayer/Contents.json | 6 + .../Content.imageset/Contents.json | 11 + .../Middle.imagestacklayer/Contents.json | 6 + .../Content.imageset/Contents.json | 16 + .../Back.imagestacklayer/Contents.json | 6 + .../App Icon.imagestack/Contents.json | 17 + .../Content.imageset/Contents.json | 16 + .../Front.imagestacklayer/Contents.json | 6 + .../Content.imageset/Contents.json | 16 + .../Middle.imagestacklayer/Contents.json | 6 + .../Contents.json | 32 + .../Contents.json | 24 + .../Top Shelf Image.imageset/Contents.json | 24 + .../Assets.xcassets/Contents.json | 6 + .../Launch Image.launchimage/Contents.json | 22 + .../DiskTVExample/Base.lproj/Main.storyboard | 125 +++ DiskExample/DiskTVExample/Info.plist | 32 + .../DiskTVExample/ViewController.swift | 97 ++ .../Circular.imageset/Contents.json | 28 + .../Contents.json | 48 + .../Extra Large.imageset/Contents.json | 28 + .../Graphic Bezel.imageset/Contents.json | 28 + .../Graphic Circular.imageset/Contents.json | 28 + .../Graphic Corner.imageset/Contents.json | 28 + .../Contents.json | 28 + .../Modular.imageset/Contents.json | 28 + .../Utilitarian.imageset/Contents.json | 28 + .../Assets.xcassets/Contents.json | 6 + .../ExtensionDelegate.swift | 56 ++ .../DiskWatchExample Extension/Info.plist | 36 + .../InterfaceController.swift | 115 +++ .../NotificationController.swift | 38 + .../PushNotificationPayload.apns | 20 + .../AppIcon.appiconset/Contents.json | 81 ++ .../Assets.xcassets/Contents.json | 6 + .../Base.lproj/Interface.storyboard | 70 ++ DiskExample/DiskWatchExample/Info.plist | 33 + README.md | 20 +- Sources/Disk+Errors.swift | 15 +- Sources/Disk+InternalHelpers.swift | 55 +- Sources/Disk+UIImage.swift | 5 +- Sources/Disk+VolumeInformation.swift | 15 +- Sources/Disk+[UIImage].swift | 7 +- Sources/Disk.h | 3 +- Sources/Disk.swift | 30 +- Sources/DiskErrors.h | 24 + Sources/DiskErrors.m | 11 + Tests/DiskTests.swift | 3 +- 73 files changed, 3321 insertions(+), 141 deletions(-) create mode 100644 Disk.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 DiskExample/Common/GetPosts.swift rename DiskExample/{DiskExample => Common}/Post.swift (100%) create mode 100644 DiskExample/DiskExample.xcodeproj/xcshareddata/xcschemes/DiskIOSExample.xcscheme rename DiskExample/{DiskExample => DiskIOSExample}/AppDelegate.swift (100%) rename DiskExample/{DiskExample => DiskIOSExample}/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename DiskExample/{DiskExample => DiskIOSExample}/Base.lproj/LaunchScreen.storyboard (100%) rename DiskExample/{DiskExample => DiskIOSExample}/Base.lproj/Main.storyboard (96%) rename DiskExample/{DiskExample => DiskIOSExample}/Info.plist (100%) rename DiskExample/{DiskExample => DiskIOSExample}/ViewController.swift (63%) create mode 100644 DiskExample/DiskMacExample/AppDelegate.swift create mode 100644 DiskExample/DiskMacExample/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 DiskExample/DiskMacExample/Assets.xcassets/Contents.json create mode 100644 DiskExample/DiskMacExample/Base.lproj/Main.storyboard create mode 100644 DiskExample/DiskMacExample/DiskMacExample.entitlements create mode 100644 DiskExample/DiskMacExample/Info.plist create mode 100644 DiskExample/DiskMacExample/ViewController.swift create mode 100644 DiskExample/DiskTVExample/AppDelegate.swift create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/Contents.json create mode 100644 DiskExample/DiskTVExample/Assets.xcassets/Launch Image.launchimage/Contents.json create mode 100644 DiskExample/DiskTVExample/Base.lproj/Main.storyboard create mode 100644 DiskExample/DiskTVExample/Info.plist create mode 100644 DiskExample/DiskTVExample/ViewController.swift create mode 100644 DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json create mode 100644 DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Contents.json create mode 100644 DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json create mode 100644 DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json create mode 100644 DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json create mode 100644 DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json create mode 100644 DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json create mode 100644 DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json create mode 100644 DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json create mode 100644 DiskExample/DiskWatchExample Extension/Assets.xcassets/Contents.json create mode 100644 DiskExample/DiskWatchExample Extension/ExtensionDelegate.swift create mode 100644 DiskExample/DiskWatchExample Extension/Info.plist create mode 100644 DiskExample/DiskWatchExample Extension/InterfaceController.swift create mode 100644 DiskExample/DiskWatchExample Extension/NotificationController.swift create mode 100644 DiskExample/DiskWatchExample Extension/PushNotificationPayload.apns create mode 100644 DiskExample/DiskWatchExample/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 DiskExample/DiskWatchExample/Assets.xcassets/Contents.json create mode 100644 DiskExample/DiskWatchExample/Base.lproj/Interface.storyboard create mode 100644 DiskExample/DiskWatchExample/Info.plist create mode 100644 Sources/DiskErrors.h create mode 100644 Sources/DiskErrors.m diff --git a/Disk.podspec b/Disk.podspec index 45319d9..056e387 100644 --- a/Disk.podspec +++ b/Disk.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Disk" - s.version = "0.6.3" + s.version = "0.6.4" s.summary = "Delightful framework for iOS to easily persist structs, images, and data" s.description = <<-DESC Easily work with the iOS file system without worrying about any of its intricacies. Save Codable structs, UIImage, [UIImage], Data, [Data] to Apple recommended locations on the user's disk. Retrieve an object from disk as the type you specify, without having to worry about conversion or casting. Append data to file locations without worrying about retrieval, manipulation, or conversion. Clear entire directories if you need to, check if an object exists on disk, and much more. @@ -11,6 +11,9 @@ Pod::Spec.new do |s| s.social_media_url = "https://twitter.com/sdrzn" s.swift_version = "4.0", "4.2", "5.0" s.platform = :ios, "9.0" + s.platform = :osx, "10.10" + s.platform = :tvos, "9.0" + s.platform = :watchos, "3.0" s.source = { :git => "https://github.com/saoudrizwan/Disk.git", :tag => "#{s.version}" } s.source_files = "Sources/**/*.{h,m,swift}" end diff --git a/Disk.xcodeproj/project.pbxproj b/Disk.xcodeproj/project.pbxproj index 1163968..260e788 100644 --- a/Disk.xcodeproj/project.pbxproj +++ b/Disk.xcodeproj/project.pbxproj @@ -23,6 +23,8 @@ 10F3C7041F23D9C9006D42EF /* Disk+Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10F3C7031F23D9C9006D42EF /* Disk+Data.swift */; }; 10F3C7061F23D9E0006D42EF /* Disk+[Data].swift in Sources */ = {isa = PBXBuildFile; fileRef = 10F3C7051F23D9E0006D42EF /* Disk+[Data].swift */; }; 10F3C7081F23DAF2006D42EF /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10F3C7071F23DAF2006D42EF /* Message.swift */; }; + 261E777E2178916800B7DFB6 /* DiskErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = 261E777D2178916800B7DFB6 /* DiskErrors.m */; }; + 261E777F21789EB900B7DFB6 /* DiskErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 261E777C2178912C00B7DFB6 /* DiskErrors.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -55,6 +57,8 @@ 10F3C7031F23D9C9006D42EF /* Disk+Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Disk+Data.swift"; sourceTree = ""; }; 10F3C7051F23D9E0006D42EF /* Disk+[Data].swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Disk+[Data].swift"; sourceTree = ""; }; 10F3C7071F23DAF2006D42EF /* Message.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = ""; }; + 261E777C2178912C00B7DFB6 /* DiskErrors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DiskErrors.h; sourceTree = ""; }; + 261E777D2178916800B7DFB6 /* DiskErrors.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DiskErrors.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -103,6 +107,8 @@ 103FA3761F713332004C600F /* Disk+InternalHelpers.swift */, 103FA3781F713340004C600F /* Disk+VolumeInformation.swift */, 104611771F27B27E00BBDB3A /* Disk+Errors.swift */, + 261E777C2178912C00B7DFB6 /* DiskErrors.h */, + 261E777D2178916800B7DFB6 /* DiskErrors.m */, 109256591F247F7700B3C32A /* Disk+Helpers.swift */, 10F3C6FD1F23D9A4006D42EF /* Disk+Codable.swift */, 10F3C6FF1F23D9B1006D42EF /* Disk+UIImage.swift */, @@ -132,6 +138,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 261E777F21789EB900B7DFB6 /* DiskErrors.h in Headers */, 10F3C6F21F23D984006D42EF /* Disk.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -187,7 +194,7 @@ TargetAttributes = { 10F3C6E01F23D984006D42EF = { CreatedOnToolsVersion = 9.0; - LastSwiftMigration = 0900; + LastSwiftMigration = 1010; }; 10F3C6E91F23D984006D42EF = { CreatedOnToolsVersion = 9.0; @@ -246,6 +253,7 @@ 10F3C7041F23D9C9006D42EF /* Disk+Data.swift in Sources */, 103FA3791F713340004C600F /* Disk+VolumeInformation.swift in Sources */, 10F3C7001F23D9B1006D42EF /* Disk+UIImage.swift in Sources */, + 261E777E2178916800B7DFB6 /* DiskErrors.m in Sources */, 104611781F27B27E00BBDB3A /* Disk+Errors.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -405,12 +413,17 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.Disk; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchsimulator appletvsimulator watchos appletvos macosx"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,3,4"; + TVOS_DEPLOYMENT_TARGET = 9.0; + WATCHOS_DEPLOYMENT_TARGET = 3.0; }; name = Debug; }; @@ -429,11 +442,16 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.Disk; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchsimulator appletvsimulator watchos appletvos macosx"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,3,4"; + TVOS_DEPLOYMENT_TARGET = 9.0; + WATCHOS_DEPLOYMENT_TARGET = 3.0; }; name = Release; }; diff --git a/Disk.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Disk.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Disk.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/DiskExample/Common/GetPosts.swift b/DiskExample/Common/GetPosts.swift new file mode 100644 index 0000000..e4e1d10 --- /dev/null +++ b/DiskExample/Common/GetPosts.swift @@ -0,0 +1,46 @@ +// +// GetPosts.swift +// DiskExample +// +// Created by Craig Rouse on 29/05/2019. +// Copyright © 2019 Saoud Rizwan. All rights reserved. +// + +import Foundation + +func getPostsFromWeb(completion: (([Post]) -> Void)?) { + var urlComponents = URLComponents() + urlComponents.scheme = "https" + urlComponents.host = "jsonplaceholder.typicode.com" + urlComponents.path = "/posts" + let userIdItem = URLQueryItem(name: "userId", value: "1") + urlComponents.queryItems = [userIdItem] + guard let url = urlComponents.url else { fatalError("Could not create URL from components") } + var request = URLRequest(url: url) + request.httpMethod = "GET" + let config = URLSessionConfiguration.default + let session = URLSession(configuration: config) + let task = session.dataTask(with: request) { (data, response, error) in + DispatchQueue.main.async { + guard error == nil else { fatalError(error!.localizedDescription) } + guard let data = data else { fatalError("No data retrieved") } + + // We could directly save this data to disk... + // try? Disk.save(data, to: .caches, as: "posts.json") + + // ... and retrieve it later as [Post]... + // let posts = try? Disk.retrieve("posts.json", from: .caches, as: [Post].self) + + // ... but that's not good practice! Our networking and persistence logic should be separate. + // Let's return the posts in our completion handler: + do { + let decoder = JSONDecoder() + let posts = try decoder.decode([Post].self, from: data) + completion?(posts) + } catch { + fatalError(error.localizedDescription) + } + } + } + task.resume() +} diff --git a/DiskExample/DiskExample/Post.swift b/DiskExample/Common/Post.swift similarity index 100% rename from DiskExample/DiskExample/Post.swift rename to DiskExample/Common/Post.swift diff --git a/DiskExample/DiskExample.xcodeproj/project.pbxproj b/DiskExample/DiskExample.xcodeproj/project.pbxproj index dcfc595..9a340f8 100644 --- a/DiskExample/DiskExample.xcodeproj/project.pbxproj +++ b/DiskExample/DiskExample.xcodeproj/project.pbxproj @@ -14,9 +14,50 @@ 1092566D1F248E8800B3C32A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1092566B1F248E8800B3C32A /* Main.storyboard */; }; 1092566F1F248E8800B3C32A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1092566E1F248E8800B3C32A /* Assets.xcassets */; }; 109256721F248E8800B3C32A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 109256701F248E8800B3C32A /* LaunchScreen.storyboard */; }; - 1092567E1F24922500B3C32A /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1092567D1F24922500B3C32A /* Post.swift */; }; + D716BBAF229E723500B8E759 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D716BBAD229E723500B8E759 /* Interface.storyboard */; }; + D716BBB1229E723600B8E759 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D716BBB0229E723600B8E759 /* Assets.xcassets */; }; + D716BBB8229E723700B8E759 /* DiskWatchExample Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D716BBB7229E723700B8E759 /* DiskWatchExample Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + D716BBBD229E723700B8E759 /* InterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BBBC229E723700B8E759 /* InterfaceController.swift */; }; + D716BBBF229E723700B8E759 /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BBBE229E723700B8E759 /* ExtensionDelegate.swift */; }; + D716BBC1229E723700B8E759 /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BBC0229E723700B8E759 /* NotificationController.swift */; }; + D716BBC3229E723800B8E759 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D716BBC2229E723800B8E759 /* Assets.xcassets */; }; + D716BBC8229E723800B8E759 /* DiskWatchExample.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = D716BBAB229E723500B8E759 /* DiskWatchExample.app */; }; + D716BBD8229E726500B8E759 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BBD7229E726500B8E759 /* AppDelegate.swift */; }; + D716BBDA229E726500B8E759 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BBD9229E726500B8E759 /* ViewController.swift */; }; + D716BBDD229E726500B8E759 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D716BBDB229E726500B8E759 /* Main.storyboard */; }; + D716BBDF229E726700B8E759 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D716BBDE229E726700B8E759 /* Assets.xcassets */; }; + D716BBEB229E727A00B8E759 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BBEA229E727A00B8E759 /* AppDelegate.swift */; }; + D716BBED229E727A00B8E759 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BBEC229E727A00B8E759 /* ViewController.swift */; }; + D716BBEF229E727B00B8E759 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D716BBEE229E727B00B8E759 /* Assets.xcassets */; }; + D716BBF2229E727B00B8E759 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D716BBF0229E727B00B8E759 /* Main.storyboard */; }; + D716BC0E229E8B8600B8E759 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BC0C229E8B8600B8E759 /* Post.swift */; }; + D716BC0F229E8B8600B8E759 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BC0C229E8B8600B8E759 /* Post.swift */; }; + D716BC10229E8B8600B8E759 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BC0C229E8B8600B8E759 /* Post.swift */; }; + D716BC11229E8B8600B8E759 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BC0C229E8B8600B8E759 /* Post.swift */; }; + D716BC12229E8B8600B8E759 /* GetPosts.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BC0D229E8B8600B8E759 /* GetPosts.swift */; }; + D716BC13229E8B8600B8E759 /* GetPosts.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BC0D229E8B8600B8E759 /* GetPosts.swift */; }; + D716BC14229E8B8600B8E759 /* GetPosts.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BC0D229E8B8600B8E759 /* GetPosts.swift */; }; + D716BC15229E8B8600B8E759 /* GetPosts.swift in Sources */ = {isa = PBXBuildFile; fileRef = D716BC0D229E8B8600B8E759 /* GetPosts.swift */; }; + D716BC19229EBE4A00B8E759 /* Disk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D716BC18229EBE4A00B8E759 /* Disk.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + D716BBB9229E723700B8E759 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1092565C1F248E8800B3C32A /* Project object */; + proxyType = 1; + remoteGlobalIDString = D716BBB6229E723700B8E759; + remoteInfo = "DiskWatchExample Extension"; + }; + D716BBC6229E723800B8E759 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1092565C1F248E8800B3C32A /* Project object */; + proxyType = 1; + remoteGlobalIDString = D716BBAA229E723500B8E759; + remoteInfo = DiskWatchExample; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ 109254331F25C65100A93A13 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -29,18 +70,67 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; + D716BBCE229E723800B8E759 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + D716BBB8229E723700B8E759 /* DiskWatchExample Extension.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + D716BBD0229E723800B8E759 /* Embed Watch Content */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; + dstSubfolderSpec = 16; + files = ( + D716BBC8229E723800B8E759 /* DiskWatchExample.app in Embed Watch Content */, + ); + name = "Embed Watch Content"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 109254301F25C65100A93A13 /* Disk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Disk.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 109256641F248E8800B3C32A /* DiskExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DiskExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 109256641F248E8800B3C32A /* DiskIOSExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DiskIOSExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 109256671F248E8800B3C32A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 109256691F248E8800B3C32A /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 1092566C1F248E8800B3C32A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 1092566E1F248E8800B3C32A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 109256711F248E8800B3C32A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 109256731F248E8800B3C32A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1092567D1F24922500B3C32A /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = ""; }; + D716BBAB229E723500B8E759 /* DiskWatchExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DiskWatchExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D716BBAE229E723500B8E759 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; }; + D716BBB0229E723600B8E759 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + D716BBB2229E723700B8E759 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D716BBB7229E723700B8E759 /* DiskWatchExample Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "DiskWatchExample Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + D716BBBC229E723700B8E759 /* InterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceController.swift; sourceTree = ""; }; + D716BBBE229E723700B8E759 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = ""; }; + D716BBC0229E723700B8E759 /* NotificationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationController.swift; sourceTree = ""; }; + D716BBC2229E723800B8E759 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + D716BBC4229E723800B8E759 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D716BBC5229E723800B8E759 /* PushNotificationPayload.apns */ = {isa = PBXFileReference; lastKnownFileType = text; path = PushNotificationPayload.apns; sourceTree = ""; }; + D716BBD5229E726500B8E759 /* DiskTVExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DiskTVExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D716BBD7229E726500B8E759 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + D716BBD9229E726500B8E759 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + D716BBDC229E726500B8E759 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + D716BBDE229E726700B8E759 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + D716BBE0229E726700B8E759 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D716BBE8229E727A00B8E759 /* DiskMacExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DiskMacExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D716BBEA229E727A00B8E759 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + D716BBEC229E727A00B8E759 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + D716BBEE229E727B00B8E759 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + D716BBF1229E727B00B8E759 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + D716BBF3229E727B00B8E759 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D716BBF4229E727B00B8E759 /* DiskMacExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DiskMacExample.entitlements; sourceTree = ""; }; + D716BC0C229E8B8600B8E759 /* Post.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = ""; }; + D716BC0D229E8B8600B8E759 /* GetPosts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetPosts.swift; sourceTree = ""; }; + D716BC16229EBC9D00B8E759 /* Disk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Disk.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D716BC18229EBE4A00B8E759 /* Disk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Disk.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -52,13 +142,40 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D716BBB4229E723700B8E759 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D716BC19229EBE4A00B8E759 /* Disk.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D716BBD2229E726500B8E759 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D716BBE5229E727A00B8E759 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 1092565B1F248E8800B3C32A = { isa = PBXGroup; children = ( - 109256661F248E8800B3C32A /* DiskExample */, + D716BC0B229E8B8600B8E759 /* Common */, + 109256661F248E8800B3C32A /* DiskIOSExample */, + D716BBAC229E723500B8E759 /* DiskWatchExample */, + D716BBBB229E723700B8E759 /* DiskWatchExample Extension */, + D716BBD6229E726500B8E759 /* DiskTVExample */, + D716BBE9229E727A00B8E759 /* DiskMacExample */, 109256651F248E8800B3C32A /* Products */, 43A00271DAED0D8D01836231 /* Frameworks */, ); @@ -67,52 +184,184 @@ 109256651F248E8800B3C32A /* Products */ = { isa = PBXGroup; children = ( - 109256641F248E8800B3C32A /* DiskExample.app */, + 109256641F248E8800B3C32A /* DiskIOSExample.app */, + D716BBAB229E723500B8E759 /* DiskWatchExample.app */, + D716BBB7229E723700B8E759 /* DiskWatchExample Extension.appex */, + D716BBD5229E726500B8E759 /* DiskTVExample.app */, + D716BBE8229E727A00B8E759 /* DiskMacExample.app */, ); name = Products; sourceTree = ""; }; - 109256661F248E8800B3C32A /* DiskExample */ = { + 109256661F248E8800B3C32A /* DiskIOSExample */ = { isa = PBXGroup; children = ( 109256671F248E8800B3C32A /* AppDelegate.swift */, - 1092567D1F24922500B3C32A /* Post.swift */, 109256691F248E8800B3C32A /* ViewController.swift */, 1092566B1F248E8800B3C32A /* Main.storyboard */, 1092566E1F248E8800B3C32A /* Assets.xcassets */, 109256701F248E8800B3C32A /* LaunchScreen.storyboard */, 109256731F248E8800B3C32A /* Info.plist */, ); - path = DiskExample; + path = DiskIOSExample; sourceTree = ""; }; 43A00271DAED0D8D01836231 /* Frameworks */ = { isa = PBXGroup; children = ( + D716BC18229EBE4A00B8E759 /* Disk.framework */, + D716BC16229EBC9D00B8E759 /* Disk.framework */, 109254301F25C65100A93A13 /* Disk.framework */, ); name = Frameworks; sourceTree = ""; }; + D716BBAC229E723500B8E759 /* DiskWatchExample */ = { + isa = PBXGroup; + children = ( + D716BBAD229E723500B8E759 /* Interface.storyboard */, + D716BBB0229E723600B8E759 /* Assets.xcassets */, + D716BBB2229E723700B8E759 /* Info.plist */, + ); + path = DiskWatchExample; + sourceTree = ""; + }; + D716BBBB229E723700B8E759 /* DiskWatchExample Extension */ = { + isa = PBXGroup; + children = ( + D716BBBC229E723700B8E759 /* InterfaceController.swift */, + D716BBBE229E723700B8E759 /* ExtensionDelegate.swift */, + D716BBC0229E723700B8E759 /* NotificationController.swift */, + D716BBC2229E723800B8E759 /* Assets.xcassets */, + D716BBC4229E723800B8E759 /* Info.plist */, + D716BBC5229E723800B8E759 /* PushNotificationPayload.apns */, + ); + path = "DiskWatchExample Extension"; + sourceTree = ""; + }; + D716BBD6229E726500B8E759 /* DiskTVExample */ = { + isa = PBXGroup; + children = ( + D716BBD7229E726500B8E759 /* AppDelegate.swift */, + D716BBD9229E726500B8E759 /* ViewController.swift */, + D716BBDB229E726500B8E759 /* Main.storyboard */, + D716BBDE229E726700B8E759 /* Assets.xcassets */, + D716BBE0229E726700B8E759 /* Info.plist */, + ); + path = DiskTVExample; + sourceTree = ""; + }; + D716BBE9229E727A00B8E759 /* DiskMacExample */ = { + isa = PBXGroup; + children = ( + D716BBEA229E727A00B8E759 /* AppDelegate.swift */, + D716BBEC229E727A00B8E759 /* ViewController.swift */, + D716BBEE229E727B00B8E759 /* Assets.xcassets */, + D716BBF0229E727B00B8E759 /* Main.storyboard */, + D716BBF3229E727B00B8E759 /* Info.plist */, + D716BBF4229E727B00B8E759 /* DiskMacExample.entitlements */, + ); + path = DiskMacExample; + sourceTree = ""; + }; + D716BC0B229E8B8600B8E759 /* Common */ = { + isa = PBXGroup; + children = ( + D716BC0C229E8B8600B8E759 /* Post.swift */, + D716BC0D229E8B8600B8E759 /* GetPosts.swift */, + ); + path = Common; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 109256631F248E8800B3C32A /* DiskExample */ = { + 109256631F248E8800B3C32A /* DiskIOSExample */ = { isa = PBXNativeTarget; - buildConfigurationList = 109256761F248E8800B3C32A /* Build configuration list for PBXNativeTarget "DiskExample" */; + buildConfigurationList = 109256761F248E8800B3C32A /* Build configuration list for PBXNativeTarget "DiskIOSExample" */; buildPhases = ( 109256601F248E8800B3C32A /* Sources */, 109256611F248E8800B3C32A /* Frameworks */, 109256621F248E8800B3C32A /* Resources */, 109254331F25C65100A93A13 /* Embed Frameworks */, + D716BBD0229E723800B8E759 /* Embed Watch Content */, ); buildRules = ( ); dependencies = ( + D716BBC7229E723800B8E759 /* PBXTargetDependency */, ); - name = DiskExample; + name = DiskIOSExample; productName = DiskExample; - productReference = 109256641F248E8800B3C32A /* DiskExample.app */; + productReference = 109256641F248E8800B3C32A /* DiskIOSExample.app */; + productType = "com.apple.product-type.application"; + }; + D716BBAA229E723500B8E759 /* DiskWatchExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = D716BBCF229E723800B8E759 /* Build configuration list for PBXNativeTarget "DiskWatchExample" */; + buildPhases = ( + D716BBA9229E723500B8E759 /* Resources */, + D716BBCE229E723800B8E759 /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + D716BBBA229E723700B8E759 /* PBXTargetDependency */, + ); + name = DiskWatchExample; + productName = DiskWatchExample; + productReference = D716BBAB229E723500B8E759 /* DiskWatchExample.app */; + productType = "com.apple.product-type.application.watchapp2"; + }; + D716BBB6229E723700B8E759 /* DiskWatchExample Extension */ = { + isa = PBXNativeTarget; + buildConfigurationList = D716BBCD229E723800B8E759 /* Build configuration list for PBXNativeTarget "DiskWatchExample Extension" */; + buildPhases = ( + D716BBB3229E723700B8E759 /* Sources */, + D716BBB4229E723700B8E759 /* Frameworks */, + D716BBB5229E723700B8E759 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "DiskWatchExample Extension"; + productName = "DiskWatchExample Extension"; + productReference = D716BBB7229E723700B8E759 /* DiskWatchExample Extension.appex */; + productType = "com.apple.product-type.watchkit2-extension"; + }; + D716BBD4229E726500B8E759 /* DiskTVExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = D716BBE1229E726700B8E759 /* Build configuration list for PBXNativeTarget "DiskTVExample" */; + buildPhases = ( + D716BBD1229E726500B8E759 /* Sources */, + D716BBD2229E726500B8E759 /* Frameworks */, + D716BBD3229E726500B8E759 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DiskTVExample; + productName = DiskTVExample; + productReference = D716BBD5229E726500B8E759 /* DiskTVExample.app */; + productType = "com.apple.product-type.application"; + }; + D716BBE7229E727A00B8E759 /* DiskMacExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = D716BBF5229E727B00B8E759 /* Build configuration list for PBXNativeTarget "DiskMacExample" */; + buildPhases = ( + D716BBE4229E727A00B8E759 /* Sources */, + D716BBE5229E727A00B8E759 /* Frameworks */, + D716BBE6229E727A00B8E759 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DiskMacExample; + productName = DiskMacExample; + productReference = D716BBE8229E727A00B8E759 /* DiskMacExample.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -121,7 +370,7 @@ 1092565C1F248E8800B3C32A /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0900; + LastSwiftUpdateCheck = 1020; LastUpgradeCheck = 1020; ORGANIZATIONNAME = "Saoud Rizwan"; TargetAttributes = { @@ -129,6 +378,27 @@ CreatedOnToolsVersion = 9.0; LastSwiftMigration = 1020; }; + D716BBAA229E723500B8E759 = { + CreatedOnToolsVersion = 10.2.1; + ProvisioningStyle = Automatic; + }; + D716BBB6229E723700B8E759 = { + CreatedOnToolsVersion = 10.2.1; + ProvisioningStyle = Automatic; + }; + D716BBD4229E726500B8E759 = { + CreatedOnToolsVersion = 10.2.1; + ProvisioningStyle = Automatic; + }; + D716BBE7229E727A00B8E759 = { + CreatedOnToolsVersion = 10.2.1; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; }; }; buildConfigurationList = 1092565F1F248E8800B3C32A /* Build configuration list for PBXProject "DiskExample" */; @@ -144,7 +414,11 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 109256631F248E8800B3C32A /* DiskExample */, + 109256631F248E8800B3C32A /* DiskIOSExample */, + D716BBAA229E723500B8E759 /* DiskWatchExample */, + D716BBB6229E723700B8E759 /* DiskWatchExample Extension */, + D716BBD4229E726500B8E759 /* DiskTVExample */, + D716BBE7229E727A00B8E759 /* DiskMacExample */, ); }; /* End PBXProject section */ @@ -160,6 +434,41 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D716BBA9229E723500B8E759 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D716BBB1229E723600B8E759 /* Assets.xcassets in Resources */, + D716BBAF229E723500B8E759 /* Interface.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D716BBB5229E723700B8E759 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D716BBC3229E723800B8E759 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D716BBD3229E726500B8E759 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D716BBDF229E726700B8E759 /* Assets.xcassets in Resources */, + D716BBDD229E726500B8E759 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D716BBE6229E727A00B8E759 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D716BBEF229E727B00B8E759 /* Assets.xcassets in Resources */, + D716BBF2229E727B00B8E759 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -167,14 +476,62 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1092567E1F24922500B3C32A /* Post.swift in Sources */, + D716BC12229E8B8600B8E759 /* GetPosts.swift in Sources */, 1092566A1F248E8800B3C32A /* ViewController.swift in Sources */, 109256681F248E8800B3C32A /* AppDelegate.swift in Sources */, + D716BC0E229E8B8600B8E759 /* Post.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D716BBB3229E723700B8E759 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D716BC13229E8B8600B8E759 /* GetPosts.swift in Sources */, + D716BBC1229E723700B8E759 /* NotificationController.swift in Sources */, + D716BBBF229E723700B8E759 /* ExtensionDelegate.swift in Sources */, + D716BBBD229E723700B8E759 /* InterfaceController.swift in Sources */, + D716BC0F229E8B8600B8E759 /* Post.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D716BBD1229E726500B8E759 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D716BC10229E8B8600B8E759 /* Post.swift in Sources */, + D716BBDA229E726500B8E759 /* ViewController.swift in Sources */, + D716BC14229E8B8600B8E759 /* GetPosts.swift in Sources */, + D716BBD8229E726500B8E759 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D716BBE4229E727A00B8E759 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D716BC11229E8B8600B8E759 /* Post.swift in Sources */, + D716BBED229E727A00B8E759 /* ViewController.swift in Sources */, + D716BC15229E8B8600B8E759 /* GetPosts.swift in Sources */, + D716BBEB229E727A00B8E759 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + D716BBBA229E723700B8E759 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D716BBB6229E723700B8E759 /* DiskWatchExample Extension */; + targetProxy = D716BBB9229E723700B8E759 /* PBXContainerItemProxy */; + }; + D716BBC7229E723800B8E759 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D716BBAA229E723500B8E759 /* DiskWatchExample */; + targetProxy = D716BBC6229E723800B8E759 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 1092566B1F248E8800B3C32A /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -192,6 +549,30 @@ name = LaunchScreen.storyboard; sourceTree = ""; }; + D716BBAD229E723500B8E759 /* Interface.storyboard */ = { + isa = PBXVariantGroup; + children = ( + D716BBAE229E723500B8E759 /* Base */, + ); + name = Interface.storyboard; + sourceTree = ""; + }; + D716BBDB229E726500B8E759 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + D716BBDC229E726500B8E759 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + D716BBF0229E727B00B8E759 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + D716BBF1229E727B00B8E759 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ @@ -311,7 +692,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = DiskExample/Info.plist; + INFOPLIST_FILE = DiskIOSExample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.DiskExample; @@ -326,7 +707,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = DiskExample/Info.plist; + INFOPLIST_FILE = DiskIOSExample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.DiskExample; @@ -336,6 +717,174 @@ }; name = Release; }; + D716BBC9229E723800B8E759 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + IBSC_MODULE = DiskWatchExample_Extension; + INFOPLIST_FILE = DiskWatchExample/Info.plist; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.DiskExample.watchkitapp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 5.2; + }; + name = Debug; + }; + D716BBCA229E723800B8E759 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + IBSC_MODULE = DiskWatchExample_Extension; + INFOPLIST_FILE = DiskWatchExample/Info.plist; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.DiskExample.watchkitapp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 5.2; + }; + name = Release; + }; + D716BBCB229E723800B8E759 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = XC939GDC9P; + INFOPLIST_FILE = "DiskWatchExample Extension/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.DiskExample.watchkitapp.watchkitextension; + PRODUCT_NAME = "${TARGET_NAME}"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 5.2; + }; + name = Debug; + }; + D716BBCC229E723800B8E759 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = XC939GDC9P; + INFOPLIST_FILE = "DiskWatchExample Extension/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.DiskExample.watchkitapp.watchkitextension; + PRODUCT_NAME = "${TARGET_NAME}"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 5.2; + }; + name = Release; + }; + D716BBE2229E726700B8E759 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = DiskTVExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.DiskTVExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.2; + }; + name = Debug; + }; + D716BBE3229E726700B8E759 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = DiskTVExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.DiskTVExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.2; + }; + name = Release; + }; + D716BBF6229E727B00B8E759 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_ENTITLEMENTS = DiskMacExample/DiskMacExample.entitlements; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = DiskMacExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.DiskMacExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + D716BBF7229E727B00B8E759 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_ENTITLEMENTS = DiskMacExample/DiskMacExample.entitlements; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = DiskMacExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = saoudrizwan.DiskMacExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -348,7 +897,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 109256761F248E8800B3C32A /* Build configuration list for PBXNativeTarget "DiskExample" */ = { + 109256761F248E8800B3C32A /* Build configuration list for PBXNativeTarget "DiskIOSExample" */ = { isa = XCConfigurationList; buildConfigurations = ( 109256771F248E8800B3C32A /* Debug */, @@ -357,6 +906,42 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D716BBCD229E723800B8E759 /* Build configuration list for PBXNativeTarget "DiskWatchExample Extension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D716BBCB229E723800B8E759 /* Debug */, + D716BBCC229E723800B8E759 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D716BBCF229E723800B8E759 /* Build configuration list for PBXNativeTarget "DiskWatchExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D716BBC9229E723800B8E759 /* Debug */, + D716BBCA229E723800B8E759 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D716BBE1229E726700B8E759 /* Build configuration list for PBXNativeTarget "DiskTVExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D716BBE2229E726700B8E759 /* Debug */, + D716BBE3229E726700B8E759 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D716BBF5229E727B00B8E759 /* Build configuration list for PBXNativeTarget "DiskMacExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D716BBF6229E727B00B8E759 /* Debug */, + D716BBF7229E727B00B8E759 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 1092565C1F248E8800B3C32A /* Project object */; diff --git a/DiskExample/DiskExample.xcodeproj/xcshareddata/xcschemes/DiskIOSExample.xcscheme b/DiskExample/DiskExample.xcodeproj/xcshareddata/xcschemes/DiskIOSExample.xcscheme new file mode 100644 index 0000000..57df53b --- /dev/null +++ b/DiskExample/DiskExample.xcodeproj/xcshareddata/xcschemes/DiskIOSExample.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DiskExample/DiskExample/AppDelegate.swift b/DiskExample/DiskIOSExample/AppDelegate.swift similarity index 100% rename from DiskExample/DiskExample/AppDelegate.swift rename to DiskExample/DiskIOSExample/AppDelegate.swift diff --git a/DiskExample/DiskExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/DiskExample/DiskIOSExample/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from DiskExample/DiskExample/Assets.xcassets/AppIcon.appiconset/Contents.json rename to DiskExample/DiskIOSExample/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/DiskExample/DiskExample/Base.lproj/LaunchScreen.storyboard b/DiskExample/DiskIOSExample/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from DiskExample/DiskExample/Base.lproj/LaunchScreen.storyboard rename to DiskExample/DiskIOSExample/Base.lproj/LaunchScreen.storyboard diff --git a/DiskExample/DiskExample/Base.lproj/Main.storyboard b/DiskExample/DiskIOSExample/Base.lproj/Main.storyboard similarity index 96% rename from DiskExample/DiskExample/Base.lproj/Main.storyboard rename to DiskExample/DiskIOSExample/Base.lproj/Main.storyboard index ff33b6b..72736df 100644 --- a/DiskExample/DiskExample/Base.lproj/Main.storyboard +++ b/DiskExample/DiskIOSExample/Base.lproj/Main.storyboard @@ -1,10 +1,11 @@ - + - + + @@ -12,21 +13,11 @@ - - + + - diff --git a/DiskExample/DiskExample/Info.plist b/DiskExample/DiskIOSExample/Info.plist similarity index 100% rename from DiskExample/DiskExample/Info.plist rename to DiskExample/DiskIOSExample/Info.plist diff --git a/DiskExample/DiskExample/ViewController.swift b/DiskExample/DiskIOSExample/ViewController.swift similarity index 63% rename from DiskExample/DiskExample/ViewController.swift rename to DiskExample/DiskIOSExample/ViewController.swift index d442bd5..1463a8f 100644 --- a/DiskExample/DiskExample/ViewController.swift +++ b/DiskExample/DiskIOSExample/ViewController.swift @@ -24,7 +24,7 @@ class ViewController: UIViewController { @IBAction func getTapped(_ sender: Any) { // Be sure to check out the comments in the networking function below UIApplication.shared.isNetworkActivityIndicatorVisible = true - getPostsFromWeb { (posts) in + getPostsFromWeb { posts in UIApplication.shared.isNetworkActivityIndicatorVisible = false print("Posts retrieved from network request successfully!") self.posts = posts @@ -66,7 +66,8 @@ class ViewController: UIViewController { @IBAction func retrieveTapped(_ sender: Any) { // We'll keep things simple here by using try?, but it's good practice to handle Disk with do, catch, try blocks // so you can make sure everything is going according to plan. - if let retrievedPosts = try? Disk.retrieve("posts.json", from: .documents, as: [Post].self) { + do { + let retrievedPosts = try Disk.retrieve("posts.json", from: .documents, as: [Post].self) // If you Option+Click 'retrievedPosts' above, you'll notice that its type is [Post] // Pretty neat, huh? @@ -77,46 +78,18 @@ class ViewController: UIViewController { self.resultsTextView.text = result print("Retrieved posts from disk!") + } catch DiskError.noFileFound { + self.resultsTextView.text = "No file saved to disk yet!" + print ("No file found to retrieve posts from.") + } catch let error as NSError { + fatalError(""" + Domain: \(error.domain) + Code: \(error.code) + Description: \(error.localizedDescription) + Failure Reason: \(error.localizedFailureReason ?? "") + Suggestions: \(error.localizedRecoverySuggestion ?? "") + """) } } - - // MARK: Networking - - func getPostsFromWeb(completion: (([Post]) -> Void)?) { - var urlComponents = URLComponents() - urlComponents.scheme = "https" - urlComponents.host = "jsonplaceholder.typicode.com" - urlComponents.path = "/posts" - let userIdItem = URLQueryItem(name: "userId", value: "1") - urlComponents.queryItems = [userIdItem] - guard let url = urlComponents.url else { fatalError("Could not create URL from components") } - var request = URLRequest(url: url) - request.httpMethod = "GET" - let config = URLSessionConfiguration.default - let session = URLSession(configuration: config) - let task = session.dataTask(with: request) { (data, response, error) in - DispatchQueue.main.async { - guard error == nil else { fatalError(error!.localizedDescription) } - guard let data = data else { fatalError("No data retrieved") } - - // We could directly save this data to disk... - // try? Disk.save(data, to: .caches, as: "posts.json") - - // ... and retrieve it later as [Post]... - // let posts = try? Disk.retrieve("posts.json", from: .caches, as: [Post].self) - - // ... but that's not good practice! Our networking and persistence logic should be separate. - // Let's return the posts in our completion handler: - do { - let decoder = JSONDecoder() - let posts = try decoder.decode([Post].self, from: data) - completion?(posts) - } catch { - fatalError(error.localizedDescription) - } - } - } - task.resume() - } } diff --git a/DiskExample/DiskMacExample/AppDelegate.swift b/DiskExample/DiskMacExample/AppDelegate.swift new file mode 100644 index 0000000..4c75b9a --- /dev/null +++ b/DiskExample/DiskMacExample/AppDelegate.swift @@ -0,0 +1,26 @@ +// +// AppDelegate.swift +// DiskMacExample +// +// Created by Craig Rouse on 29/05/2019. +// Copyright © 2019 Saoud Rizwan. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + + + func applicationDidFinishLaunching(_ aNotification: Notification) { + // Insert code here to initialize your application + } + + func applicationWillTerminate(_ aNotification: Notification) { + // Insert code here to tear down your application + } + + +} + diff --git a/DiskExample/DiskMacExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/DiskExample/DiskMacExample/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/DiskExample/DiskMacExample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskMacExample/Assets.xcassets/Contents.json b/DiskExample/DiskMacExample/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DiskExample/DiskMacExample/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskMacExample/Base.lproj/Main.storyboard b/DiskExample/DiskMacExample/Base.lproj/Main.storyboard new file mode 100644 index 0000000..dc9dc0b --- /dev/null +++ b/DiskExample/DiskMacExample/Base.lproj/Main.storyboard @@ -0,0 +1,842 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DiskExample/DiskMacExample/DiskMacExample.entitlements b/DiskExample/DiskMacExample/DiskMacExample.entitlements new file mode 100644 index 0000000..625af03 --- /dev/null +++ b/DiskExample/DiskMacExample/DiskMacExample.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + com.apple.security.network.client + + + diff --git a/DiskExample/DiskMacExample/Info.plist b/DiskExample/DiskMacExample/Info.plist new file mode 100644 index 0000000..ef77081 --- /dev/null +++ b/DiskExample/DiskMacExample/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2019 Saoud Rizwan. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/DiskExample/DiskMacExample/ViewController.swift b/DiskExample/DiskMacExample/ViewController.swift new file mode 100644 index 0000000..fc3a78b --- /dev/null +++ b/DiskExample/DiskMacExample/ViewController.swift @@ -0,0 +1,125 @@ +// +// ViewController.swift +// DiskMacExample +// +// Created by Craig Rouse on 29/05/2019. +// Copyright © 2019 Saoud Rizwan. All rights reserved. +// + +import Cocoa +import Disk + +class ViewController: NSViewController { + + var posts = [Post]() + + + @IBOutlet var resultsTextView: NSTextView! + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + override var representedObject: Any? { + didSet { + // Update the view, if already loaded. + } + } + + @IBAction func getJSONFromWeb(_ sender: Any) { + getPostsFromWeb { posts in +// UIApplication.shared.isNetworkActivityIndicatorVisible = false + print("Posts retrieved from network request successfully!") + self.posts = posts + } + } + + @IBAction func saveJSONToDisk(_ sender: Any) { + // Disk is thorough when it comes to error handling, so make sure you understand why an error occurs when it does. + do { + try Disk.save(self.posts, to: .documents, as: "posts.json") + } catch let error as NSError { + fatalError(""" + Domain: \(error.domain) + Code: \(error.code) + Description: \(error.localizedDescription) + Failure Reason: \(error.localizedFailureReason ?? "") + Suggestions: \(error.localizedRecoverySuggestion ?? "") + """) + } + // Notice how we use a do, catch, try block when using Disk, this is because almost all of Disk's methods + // are throwing functions, meaning they will throw an error if something goes wrong. In almost all cases, these + // errors come with a lot of information like a description, failure reason, and recover suggestions. + + // You could alternatively use try! or try? instead of do, catch, try blocks + // try? Disk.save(self.posts, to: .documents, as: "posts.json") // returns a discardable result of nil + // try! Disk.save(self.posts, to: .documents, as: "posts.json") // will crash the app during runtime if this fails + + // You can also save files in folder hierarchies, for example: + // try? Disk.save(self.posts, to: .caches, as: "Posts/MyCoolPosts/1.json") + // This will automatically create the Posts and MyCoolPosts folders + + // If you want to save new data to a file location, you can treat the file as an array and simply append to it as well. + let newPost = Post(userId: 0, id: self.posts.count + 1, title: "Appended Post", body: "...") + try? Disk.append(newPost, to: "posts.json", in: .documents) + + print("Saved posts to disk!") + } + + @IBAction func retrieveJSONFromDisk(_ sender: Any) { + // We'll keep things simple here by using try?, but it's good practice to handle Disk with do, catch, try blocks + // so you can make sure everything is going according to plan. + do { + let retrievedPosts = try Disk.retrieve("posts.json", from: .documents, as: [Post].self) + // If you Option+Click 'retrievedPosts' above, you'll notice that its type is [Post] + // Pretty neat, huh? + + var result: String = "" + for post in retrievedPosts { + result.append("\(post.id): \(post.title)\n\(post.body)\n\n") + } + // We'll keep things simple here by using try?, but it's good practice to handle Disk with do, catch, try blocks + // so you can make sure everything is going according to plan. + do { + let retrievedPosts = try Disk.retrieve("posts.json", from: .documents, as: [Post].self) + // If you Option+Click 'retrievedPosts' above, you'll notice that its type is [Post] + // Pretty neat, huh? + + var result: String = "" + for post in retrievedPosts { + result.append("\(post.id): \(post.title)\n\(post.body)\n\n") + } + self.resultsTextView.string = result + + print("Retrieved posts from disk!") + } catch DiskError.noFileFound { + self.resultsTextView.string = "No file saved to disk yet!" + print ("No file found to retrieve posts from.") + } catch let error as NSError { + fatalError(""" + Domain: \(error.domain) + Code: \(error.code) + Description: \(error.localizedDescription) + Failure Reason: \(error.localizedFailureReason ?? "") + Suggestions: \(error.localizedRecoverySuggestion ?? "") + """) + } + } catch DiskError.noFileFound { + self.resultsTextView.string = "No file saved to disk yet!" + print ("No file found to retrieve posts from.") + } catch let error as NSError { + fatalError(""" + Domain: \(error.domain) + Code: \(error.code) + Description: \(error.localizedDescription) + Failure Reason: \(error.localizedFailureReason ?? "") + Suggestions: \(error.localizedRecoverySuggestion ?? "") + """) + } + } + + +} + diff --git a/DiskExample/DiskTVExample/AppDelegate.swift b/DiskExample/DiskTVExample/AppDelegate.swift new file mode 100644 index 0000000..04156e2 --- /dev/null +++ b/DiskExample/DiskTVExample/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// DiskTVExample +// +// Created by Craig Rouse on 29/05/2019. +// Copyright © 2019 Saoud Rizwan. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json new file mode 100644 index 0000000..db288f3 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json @@ -0,0 +1,32 @@ +{ + "assets" : [ + { + "size" : "1280x768", + "idiom" : "tv", + "filename" : "App Icon - App Store.imagestack", + "role" : "primary-app-icon" + }, + { + "size" : "400x240", + "idiom" : "tv", + "filename" : "App Icon.imagestack", + "role" : "primary-app-icon" + }, + { + "size" : "2320x720", + "idiom" : "tv", + "filename" : "Top Shelf Image Wide.imageset", + "role" : "top-shelf-image-wide" + }, + { + "size" : "1920x720", + "idiom" : "tv", + "filename" : "Top Shelf Image.imageset", + "role" : "top-shelf-image" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json new file mode 100644 index 0000000..7dc9502 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + }, + { + "idiom" : "tv-marketing", + "scale" : "1x" + }, + { + "idiom" : "tv-marketing", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 0000000..7dc9502 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + }, + { + "idiom" : "tv-marketing", + "scale" : "1x" + }, + { + "idiom" : "tv-marketing", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Assets.xcassets/Launch Image.launchimage/Contents.json b/DiskExample/DiskTVExample/Assets.xcassets/Launch Image.launchimage/Contents.json new file mode 100644 index 0000000..d746a60 --- /dev/null +++ b/DiskExample/DiskTVExample/Assets.xcassets/Launch Image.launchimage/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "orientation" : "landscape", + "idiom" : "tv", + "extent" : "full-screen", + "minimum-system-version" : "11.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "tv", + "extent" : "full-screen", + "minimum-system-version" : "9.0", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskTVExample/Base.lproj/Main.storyboard b/DiskExample/DiskTVExample/Base.lproj/Main.storyboard new file mode 100644 index 0000000..c6c20f1 --- /dev/null +++ b/DiskExample/DiskTVExample/Base.lproj/Main.storyboard @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DiskExample/DiskTVExample/Info.plist b/DiskExample/DiskTVExample/Info.plist new file mode 100644 index 0000000..02942a3 --- /dev/null +++ b/DiskExample/DiskTVExample/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + arm64 + + UIUserInterfaceStyle + Automatic + + diff --git a/DiskExample/DiskTVExample/ViewController.swift b/DiskExample/DiskTVExample/ViewController.swift new file mode 100644 index 0000000..281e72e --- /dev/null +++ b/DiskExample/DiskTVExample/ViewController.swift @@ -0,0 +1,97 @@ +// +// ViewController.swift +// DiskTVExample +// +// Created by Craig Rouse on 29/05/2019. +// Copyright © 2019 Saoud Rizwan. All rights reserved. +// + +import UIKit +import Disk + +class ViewController: UIViewController { + + // MARK: Properties + + var posts = [Post]() + + // MARK: IBOutlets + @IBOutlet weak var resultsTextView: UITextView! + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } + + // MARK: IBActions + + @IBAction func getJSONFromWeb(_ sender: Any) { + // Be sure to check out the comments in the networking function below + getPostsFromWeb { posts in + print("Posts retrieved from network request successfully!") + self.posts = posts + } + } + + @IBAction func saveJSONToDisk(_ sender: Any) { + // Disk is thorough when it comes to error handling, so make sure you understand why an error occurs when it does. + do { + try Disk.save(self.posts, to: .caches, as: "posts.json") + } catch let error as NSError { + fatalError(""" + Domain: \(error.domain) + Code: \(error.code) + Description: \(error.localizedDescription) + Failure Reason: \(error.localizedFailureReason ?? "") + Suggestions: \(error.localizedRecoverySuggestion ?? "") + """) + } + // Notice how we use a do, catch, try block when using Disk, this is because almost all of Disk's methods + // are throwing functions, meaning they will throw an error if something goes wrong. In almost all cases, these + // errors come with a lot of information like a description, failure reason, and recover suggestions. + + // You could alternatively use try! or try? instead of do, catch, try blocks + // try? Disk.save(self.posts, to: .documents, as: "posts.json") // returns a discardable result of nil + // try! Disk.save(self.posts, to: .documents, as: "posts.json") // will crash the app during runtime if this fails + + // You can also save files in folder hierarchies, for example: + // try? Disk.save(self.posts, to: .caches, as: "Posts/MyCoolPosts/1.json") + // This will automatically create the Posts and MyCoolPosts folders + + // If you want to save new data to a file location, you can treat the file as an array and simply append to it as well. + let newPost = Post(userId: 0, id: self.posts.count + 1, title: "Appended Post", body: "...") + try? Disk.append(newPost, to: "posts.json", in: .caches) + + print("Saved posts to disk!") + } + + @IBAction func retrieveJSONFromDisk(_ sender: Any) { + // We'll keep things simple here by using try?, but it's good practice to handle Disk with do, catch, try blocks + // so you can make sure everything is going according to plan. + do { + let retrievedPosts = try Disk.retrieve("posts.json", from: .caches, as: [Post].self) + // If you Option+Click 'retrievedPosts' above, you'll notice that its type is [Post] + // Pretty neat, huh? + + var result: String = "" + for post in retrievedPosts { + result.append("\(post.id): \(post.title)\n\(post.body)\n\n") + } + self.resultsTextView.text = result + + print("Retrieved posts from disk!") + } catch DiskError.noFileFound { + self.resultsTextView.text = "No file saved to disk yet!" + print ("No file found to retrieve posts from.") + } catch let error as NSError { + fatalError(""" + Domain: \(error.domain) + Code: \(error.code) + Description: \(error.localizedDescription) + Failure Reason: \(error.localizedFailureReason ?? "") + Suggestions: \(error.localizedRecoverySuggestion ?? "") + """) + } + } +} + diff --git a/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json new file mode 100644 index 0000000..aefef29 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Contents.json b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Contents.json new file mode 100644 index 0000000..1571c7e --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Contents.json @@ -0,0 +1,48 @@ +{ + "assets" : [ + { + "idiom" : "watch", + "filename" : "Circular.imageset", + "role" : "circular" + }, + { + "idiom" : "watch", + "filename" : "Extra Large.imageset", + "role" : "extra-large" + }, + { + "idiom" : "watch", + "filename" : "Graphic Bezel.imageset", + "role" : "graphic-bezel" + }, + { + "idiom" : "watch", + "filename" : "Graphic Circular.imageset", + "role" : "graphic-circular" + }, + { + "idiom" : "watch", + "filename" : "Graphic Corner.imageset", + "role" : "graphic-corner" + }, + { + "idiom" : "watch", + "filename" : "Graphic Large Rectangular.imageset", + "role" : "graphic-large-rectangular" + }, + { + "idiom" : "watch", + "filename" : "Modular.imageset", + "role" : "modular" + }, + { + "idiom" : "watch", + "filename" : "Utilitarian.imageset", + "role" : "utilitarian" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json new file mode 100644 index 0000000..aefef29 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json new file mode 100644 index 0000000..aefef29 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json new file mode 100644 index 0000000..aefef29 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json new file mode 100644 index 0000000..aefef29 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json new file mode 100644 index 0000000..aefef29 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json new file mode 100644 index 0000000..aefef29 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json new file mode 100644 index 0000000..aefef29 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample Extension/Assets.xcassets/Contents.json b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample Extension/ExtensionDelegate.swift b/DiskExample/DiskWatchExample Extension/ExtensionDelegate.swift new file mode 100644 index 0000000..1364f88 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/ExtensionDelegate.swift @@ -0,0 +1,56 @@ +// +// ExtensionDelegate.swift +// DiskWatchExample Extension +// +// Created by Craig Rouse on 29/05/2019. +// Copyright © 2019 Saoud Rizwan. All rights reserved. +// + +import WatchKit + +class ExtensionDelegate: NSObject, WKExtensionDelegate { + + func applicationDidFinishLaunching() { + // Perform any final initialization of your application. + } + + func applicationDidBecomeActive() { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillResignActive() { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, etc. + } + + func handle(_ backgroundTasks: Set) { + // Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one. + for task in backgroundTasks { + // Use a switch statement to check the task type + switch task { + case let backgroundTask as WKApplicationRefreshBackgroundTask: + // Be sure to complete the background task once you’re done. + backgroundTask.setTaskCompletedWithSnapshot(false) + case let snapshotTask as WKSnapshotRefreshBackgroundTask: + // Snapshot tasks have a unique completion call, make sure to set your expiration date + snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil) + case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask: + // Be sure to complete the connectivity task once you’re done. + connectivityTask.setTaskCompletedWithSnapshot(false) + case let urlSessionTask as WKURLSessionRefreshBackgroundTask: + // Be sure to complete the URL session task once you’re done. + urlSessionTask.setTaskCompletedWithSnapshot(false) + case let relevantShortcutTask as WKRelevantShortcutRefreshBackgroundTask: + // Be sure to complete the relevant-shortcut task once you're done. + relevantShortcutTask.setTaskCompletedWithSnapshot(false) + case let intentDidRunTask as WKIntentDidRunRefreshBackgroundTask: + // Be sure to complete the intent-did-run task once you're done. + intentDidRunTask.setTaskCompletedWithSnapshot(false) + default: + // make sure to complete unhandled task types + task.setTaskCompletedWithSnapshot(false) + } + } + } + +} diff --git a/DiskExample/DiskWatchExample Extension/Info.plist b/DiskExample/DiskWatchExample Extension/Info.plist new file mode 100644 index 0000000..a7ad451 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + DiskWatchExample Extension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSExtension + + NSExtensionAttributes + + WKAppBundleIdentifier + saoudrizwan.DiskExample.watchkitapp + + NSExtensionPointIdentifier + com.apple.watchkit + + WKExtensionDelegateClassName + $(PRODUCT_MODULE_NAME).ExtensionDelegate + + diff --git a/DiskExample/DiskWatchExample Extension/InterfaceController.swift b/DiskExample/DiskWatchExample Extension/InterfaceController.swift new file mode 100644 index 0000000..d126585 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/InterfaceController.swift @@ -0,0 +1,115 @@ +// +// InterfaceController.swift +// DiskWatchExample Extension +// +// Created by Craig Rouse on 29/05/2019. +// Copyright © 2019 Saoud Rizwan. All rights reserved. +// + +import WatchKit +import Foundation +import Disk + +class InterfaceController: WKInterfaceController { + + // MARK: Properties + + var posts = [Post]() + + override func awake(withContext context: Any?) { + super.awake(withContext: context) + // Configure interface objects here. + } + + override func willActivate() { + // This method is called when watch view controller is about to be visible to user + super.willActivate() + } + + override func didDeactivate() { + // This method is called when watch view controller is no longer visible + super.didDeactivate() + } + + // MARK: IBActions + + @IBAction func getJSONFromWeb() { + getPostsFromWeb { posts in + print("Posts retrieved from network request successfully!") + self.posts = posts + } + } + + @IBAction func saveJSONToDisk() { + // Disk is thorough when it comes to error handling, so make sure you understand why an error occurs when it does. + do { + try Disk.save(self.posts, to: .documents, as: "posts.json") + } catch let error as NSError { + fatalError(""" + Domain: \(error.domain) + Code: \(error.code) + Description: \(error.localizedDescription) + Failure Reason: \(error.localizedFailureReason ?? "") + Suggestions: \(error.localizedRecoverySuggestion ?? "") + """) + } + // Notice how we use a do, catch, try block when using Disk, this is because almost all of Disk's methods + // are throwing functions, meaning they will throw an error if something goes wrong. In almost all cases, these + // errors come with a lot of information like a description, failure reason, and recover suggestions. + + // You could alternatively use try! or try? instead of do, catch, try blocks + // try? Disk.save(self.posts, to: .documents, as: "posts.json") // returns a discardable result of nil + // try! Disk.save(self.posts, to: .documents, as: "posts.json") // will crash the app during runtime if this fails + + // You can also save files in folder hierarchies, for example: + // try? Disk.save(self.posts, to: .caches, as: "Posts/MyCoolPosts/1.json") + // This will automatically create the Posts and MyCoolPosts folders + + // If you want to save new data to a file location, you can treat the file as an array and simply append to it as well. + let newPost = Post(userId: 0, id: self.posts.count + 1, title: "Appended Post", body: "...") + try? Disk.append(newPost, to: "posts.json", in: .documents) + + print("Saved posts to disk!") + } + + @IBAction func retrieveJSONFromDisk() { + // We'll keep things simple here by using try?, but it's good practice to handle Disk with do, catch, try blocks + // so you can make sure everything is going according to plan. + do { + let retrievedPosts = try Disk.retrieve("posts.json", from: .documents, as: [Post].self) + // If you Option+Click 'retrievedPosts' above, you'll notice that its type is [Post] + // Pretty neat, huh? + + var result: String = "" + for post in retrievedPosts { + result.append("\(post.id): \(post.title)\n\(post.body)\n\n") + } + + let alert = WKAlertAction(title: "Disk Alert", style: .cancel) { + + } + presentAlert(withTitle: "Disk Alert", message: result, preferredStyle: .actionSheet, actions: [alert]) + + print("Retrieved posts from disk!") + } + catch DiskError.noFileFound { + + let alert = WKAlertAction(title: "Disk Alert", style: .cancel) { + + } + presentAlert(withTitle: "Disk Error", message: "No file saved to disk yet!", preferredStyle: .actionSheet, actions: [alert]) + + print ("No file found to retrieve posts from.") + } + catch let error as NSError { + fatalError(""" + Domain: \(error.domain) + Code: \(error.code) + Description: \(error.localizedDescription) + Failure Reason: \(error.localizedFailureReason ?? "") + Suggestions: \(error.localizedRecoverySuggestion ?? "") + """) + } + } + +} diff --git a/DiskExample/DiskWatchExample Extension/NotificationController.swift b/DiskExample/DiskWatchExample Extension/NotificationController.swift new file mode 100644 index 0000000..0e47ccc --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/NotificationController.swift @@ -0,0 +1,38 @@ +// +// NotificationController.swift +// DiskWatchExample Extension +// +// Created by Craig Rouse on 29/05/2019. +// Copyright © 2019 Saoud Rizwan. All rights reserved. +// + +import WatchKit +import Foundation +import UserNotifications + + +class NotificationController: WKUserNotificationInterfaceController { + + override init() { + // Initialize variables here. + super.init() + + // Configure interface objects here. + } + + override func willActivate() { + // This method is called when watch view controller is about to be visible to user + super.willActivate() + } + + override func didDeactivate() { + // This method is called when watch view controller is no longer visible + super.didDeactivate() + } + + override func didReceive(_ notification: UNNotification) { + // This method is called when a notification needs to be presented. + // Implement it if you use a dynamic notification interface. + // Populate your dynamic notification interface as quickly as possible. + } +} diff --git a/DiskExample/DiskWatchExample Extension/PushNotificationPayload.apns b/DiskExample/DiskWatchExample Extension/PushNotificationPayload.apns new file mode 100644 index 0000000..5ac5526 --- /dev/null +++ b/DiskExample/DiskWatchExample Extension/PushNotificationPayload.apns @@ -0,0 +1,20 @@ +{ + "aps": { + "alert": { + "body": "Test message", + "title": "Optional title", + "subtitle": "Optional subtitle" + }, + "category": "myCategory", + "thread-id":"5280" + }, + + "WatchKit Simulator Actions": [ + { + "title": "First Button", + "identifier": "firstButtonAction" + } + ], + + "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App." +} diff --git a/DiskExample/DiskWatchExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/DiskExample/DiskWatchExample/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..6c0f2b4 --- /dev/null +++ b/DiskExample/DiskWatchExample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,81 @@ +{ + "images" : [ + { + "size" : "24x24", + "idiom" : "watch", + "scale" : "2x", + "role" : "notificationCenter", + "subtype" : "38mm" + }, + { + "size" : "27.5x27.5", + "idiom" : "watch", + "scale" : "2x", + "role" : "notificationCenter", + "subtype" : "42mm" + }, + { + "size" : "29x29", + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "watch", + "scale" : "2x", + "role" : "appLauncher", + "subtype" : "38mm" + }, + { + "size" : "44x44", + "idiom" : "watch", + "scale" : "2x", + "role" : "appLauncher", + "subtype" : "40mm" + }, + { + "size" : "50x50", + "idiom" : "watch", + "scale" : "2x", + "role" : "appLauncher", + "subtype" : "44mm" + }, + { + "size" : "86x86", + "idiom" : "watch", + "scale" : "2x", + "role" : "quickLook", + "subtype" : "38mm" + }, + { + "size" : "98x98", + "idiom" : "watch", + "scale" : "2x", + "role" : "quickLook", + "subtype" : "42mm" + }, + { + "size" : "108x108", + "idiom" : "watch", + "scale" : "2x", + "role" : "quickLook", + "subtype" : "44mm" + }, + { + "idiom" : "watch-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample/Assets.xcassets/Contents.json b/DiskExample/DiskWatchExample/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DiskExample/DiskWatchExample/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DiskExample/DiskWatchExample/Base.lproj/Interface.storyboard b/DiskExample/DiskWatchExample/Base.lproj/Interface.storyboard new file mode 100644 index 0000000..b7d6663 --- /dev/null +++ b/DiskExample/DiskWatchExample/Base.lproj/Interface.storyboard @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DiskExample/DiskWatchExample/Info.plist b/DiskExample/DiskWatchExample/Info.plist new file mode 100644 index 0000000..d90e453 --- /dev/null +++ b/DiskExample/DiskWatchExample/Info.plist @@ -0,0 +1,33 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + DiskExample + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + + WKCompanionAppBundleIdentifier + saoudrizwan.DiskExample + WKWatchKitApp + + + diff --git a/README.md b/README.md index 6fd0398..ba3f29f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,10 @@

- Platform: iOS 9.0+ + Platform: iOS 9.0+ + Platform: tvOS 9.0+ + Platform: watchOS 3.0+ + Platform: macOS 10.10+ Language: Swift 4 Carthage compatible License: MIT @@ -21,11 +24,11 @@ • Questions?

-Disk is a **powerful** and **simple** file management library built with Apple's [iOS Data Storage Guidelines](https://developer.apple.com/icloud/documentation/data-storage/index.html) in mind. Disk uses the new `Codable` protocol introduced in Swift 4 to its utmost advantage and gives you the power to persist structs without ever having to worry about encoding/decoding. Disk also helps you save images and other data types to disk with as little as one line of code. +Disk is a **powerful** and **simple** file management library originally built with Apple's [iOS Data Storage Guidelines](https://developer.apple.com/icloud/documentation/data-storage/index.html) in mind. It now additionally supports tvOS, watchOS and macOS through the same simple API. Disk uses the new `Codable` protocol introduced in Swift 4 to its utmost advantage and gives you the power to persist structs without ever having to worry about encoding/decoding. Disk also helps you save images and other data types to disk with as little as one line of code. ## Compatibility -Disk requires **iOS 9+** and is compatible with projects using **Swift 4.0** and above. Therefore you must use at least Xcode 9 when working with Disk. +Disk requires **iOS 9+**, **macOS 10.10+**, **tvOS 9+**, or **watchOS 3+** and is compatible with projects using **Swift 4.0** and above. Therefore you must use at least Xcode 9 when working with Disk. ## Installation @@ -79,6 +82,7 @@ Disk currently supports persistence of the following types: Disk follows Apple's [iOS Data Storage Guidelines](https://developer.apple.com/icloud/documentation/data-storage/index.html) and therefore allows you to save files in four primary directories and shared containers: #### Documents Directory `.documents` +_**Not supported on tvOS**_ > Only documents and other data that is **user-generated, or that cannot otherwise be recreated by your application**, should be stored in the /Documents directory and will be automatically backed up by iCloud. @@ -91,6 +95,7 @@ Disk follows Apple's [iOS Data Storage Guidelines](https://developer.apple.com/i > Note that the system may delete the Caches/ directory to free up disk space, so your app must be able to re-create or download these files as needed. #### Application Support Directory `.applicationSupport` +_**Not supported on tvOS**_ > Put app-created support files in the /Library/Application support directory. In general, this directory includes files that the app uses to run but that should remain hidden from the user. This directory can also include data files, configuration files, templates and modified versions of resources loaded from the app bundle. @@ -99,6 +104,7 @@ Disk follows Apple's [iOS Data Storage Guidelines](https://developer.apple.com/i > Data that is used only temporarily should be stored in the /tmp directory. Although these files are not backed up to iCloud, remember to delete those files when you are done with them so that they do not continue to consume space on the user’s device. #### Application Group Shared Container `.sharedContainer(appGroupName: String)` +_**Not supported on tvOS**_ Multiple applications on a single device can access a shared directory, as long as these apps have the same `groupIdentifier` in the `com.apple.security.application-groups` entitlements array, as described in [Adding an App to an App Group](https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW19) in [Entitlement Key Reference](https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/AboutEntitlements.html#//apple_ref/doc/uid/TP40011195). @@ -106,7 +112,7 @@ For more information, visit the documentation: [https://developer.apple.com/docu --- -With all these requirements and best practices, it can be hard working with the iOS file system appropriately, which is why Disk was born. Disk makes following these tedious rules simple and fun. +With all these requirements and best practices, it can be hard working with the various file systems appropriately, which is why Disk was born. Disk makes following these tedious rules simple and fun. ### Using Disk is easy. @@ -291,7 +297,7 @@ DispatchQueue.global(qos: .userInitiated).async { ``` *Don't forget to handle these sorts of tasks [being interrupted](https://stackoverflow.com/a/18305715/3502608).* -### iOS 11 Volume Information +### Volume Information Apple introduced several great iOS storage practices in [Session 204](https://developer.apple.com/videos/play/fall2017/204/), putting emphasis on several new `NSURL` volume capacity details added in iOS 11. This information allows us to gauge when it's appropriate to store data on the user's disk. * Total capacity @@ -304,6 +310,8 @@ Disk.totalCapacity Disk.availableCapacity ``` +_**The following properties are available on iOS only**_ + * Available capacity for important usage. This indicates the amount of space that can be made available for things the user has explicitly requested in the app's UI (i.e. downloading a video or new level for a game.) ```swift Disk.availableCapacityForImportantUsage @@ -403,6 +411,8 @@ do { if Disk.exists("posts.json", in: .documents) { try Disk.remove("posts.json", from: .documents) } +} catch DiskError.noFileFound { + // Pattern matching to catch specific errors. } catch let error as NSError { fatalError(""" Domain: \(error.domain) diff --git a/Sources/Disk+Errors.swift b/Sources/Disk+Errors.swift index 29e637f..378fca5 100644 --- a/Sources/Disk+Errors.swift +++ b/Sources/Disk+Errors.swift @@ -23,24 +23,13 @@ import Foundation extension Disk { - public enum ErrorCode: Int { - case noFileFound = 0 - case serialization = 1 - case deserialization = 2 - case invalidFileName = 3 - case couldNotAccessTemporaryDirectory = 4 - case couldNotAccessUserDomainMask = 5 - case couldNotAccessSharedContainer = 6 - } - - public static let errorDomain = "DiskErrorDomain" /// Create custom error that FileManager can't account for - static func createError(_ errorCode: ErrorCode, description: String?, failureReason: String?, recoverySuggestion: String?) -> Error { + static func createError(_ errorCode: DiskError.Code, description: String?, failureReason: String?, recoverySuggestion: String?) -> DiskError { let errorInfo: [String: Any] = [NSLocalizedDescriptionKey : description ?? "", NSLocalizedRecoverySuggestionErrorKey: recoverySuggestion ?? "", NSLocalizedFailureReasonErrorKey: failureReason ?? ""] - return NSError(domain: errorDomain, code: errorCode.rawValue, userInfo: errorInfo) as Error + return NSError(domain: DiskErrorDomain, code: errorCode.rawValue, userInfo: errorInfo) as! DiskError } } diff --git a/Sources/Disk+InternalHelpers.swift b/Sources/Disk+InternalHelpers.swift index 68661af..079f995 100644 --- a/Sources/Disk+InternalHelpers.swift +++ b/Sources/Disk+InternalHelpers.swift @@ -36,46 +36,49 @@ extension Disk { } var searchPathDirectory: FileManager.SearchPathDirectory switch directory { + #if os(tvOS) + #else case .documents: searchPathDirectory = .documentDirectory - case .caches: - searchPathDirectory = .cachesDirectory case .applicationSupport: searchPathDirectory = .applicationSupportDirectory - case .temporary: - if var url = URL(string: NSTemporaryDirectory()) { + case .sharedContainer(let appGroupName): + if var url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupName) { if let validPath = validPath { url = url.appendingPathComponent(validPath, isDirectory: false) } if url.absoluteString.lowercased().prefix(filePrefix.count) != filePrefix { - let fixedUrlString = filePrefix + url.absoluteString - url = URL(string: fixedUrlString)! + let fixedUrl = filePrefix + url.absoluteString + url = URL(string: fixedUrl)! } return url } else { throw createError( - .couldNotAccessTemporaryDirectory, + .couldNotAccessSharedContainer, description: "Could not create URL for \(directory.pathDescription)/\(validPath ?? "")", - failureReason: "Could not get access to the application's temporary directory.", - recoverySuggestion: "Use a different directory." + failureReason: "Could not get access to shared container with app group named \(appGroupName).", + recoverySuggestion: "Check that the app-group name in the entitlement matches the string provided." ) } - case .sharedContainer(let appGroupName): - if var url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupName) { + #endif + case .caches: + searchPathDirectory = .cachesDirectory + case .temporary: + if var url = URL(string: NSTemporaryDirectory()) { if let validPath = validPath { url = url.appendingPathComponent(validPath, isDirectory: false) } if url.absoluteString.lowercased().prefix(filePrefix.count) != filePrefix { - let fixedUrl = filePrefix + url.absoluteString - url = URL(string: fixedUrl)! + let fixedUrlString = filePrefix + url.absoluteString + url = URL(string: fixedUrlString)! } return url } else { throw createError( - .couldNotAccessSharedContainer, + .couldNotAccessTemporaryDirectory, description: "Could not create URL for \(directory.pathDescription)/\(validPath ?? "")", - failureReason: "Could not get access to shared container with app group named \(appGroupName).", - recoverySuggestion: "Check that the app-group name in the entitlement matches the string provided." + failureReason: "Could not get access to the application's temporary directory.", + recoverySuggestion: "Use a different directory." ) } } @@ -100,20 +103,16 @@ extension Disk { /// Find an existing file's URL or throw an error if it doesn't exist static func getExistingFileURL(for path: String?, in directory: Directory) throws -> URL { - do { let url = try createURL(for: path, in: directory) - if FileManager.default.fileExists(atPath: url.path) { - return url + guard FileManager.default.fileExists(atPath: url.path) else { + throw createError( + .noFileFound, + description: "Could not find an existing file or folder at \(url.path).", + failureReason: "There is no existing file or folder at \(url.path)", + recoverySuggestion: "Check if a file or folder exists before trying to commit an operation on it." + ) } - throw createError( - .noFileFound, - description: "Could not find an existing file or folder at \(url.path).", - failureReason: "There is no existing file or folder at \(url.path)", - recoverySuggestion: "Check if a file or folder exists before trying to commit an operation on it." - ) - } catch { - throw error - } + return url } /// Convert a user generated name to a valid file name diff --git a/Sources/Disk+UIImage.swift b/Sources/Disk+UIImage.swift index b93ef46..899d33a 100644 --- a/Sources/Disk+UIImage.swift +++ b/Sources/Disk+UIImage.swift @@ -20,7 +20,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#if os(macOS) +#else import Foundation +import UIKit public extension Disk { /// Save image to disk @@ -129,4 +132,4 @@ public extension Disk { } } - +#endif diff --git a/Sources/Disk+VolumeInformation.swift b/Sources/Disk+VolumeInformation.swift index 69e43ad..8e36cde 100644 --- a/Sources/Disk+VolumeInformation.swift +++ b/Sources/Disk+VolumeInformation.swift @@ -26,7 +26,7 @@ import Foundation /// Confirm that you have enough local storage space for a large amount of data. /// /// Source: https://developer.apple.com/documentation/foundation/nsurlresourcekey/checking_volume_storage_capacity?changes=latest_major&language=objc -@available(iOS 11.0, *) + public extension Disk { /// Helper method to query against a resource value key private static func getVolumeResourceValues(for key: URLResourceKey) -> URLResourceValues? { @@ -35,7 +35,7 @@ public extension Disk { return results } - /// Volume’s total capacity in bytes. + /// Volume's total capacity in bytes. static var totalCapacity: Int? { get { let resourceValues = getVolumeResourceValues(for: .volumeTotalCapacityKey) @@ -43,7 +43,7 @@ public extension Disk { } } - /// Volume’s available capacity in bytes. + /// Volume's available capacity in bytes. static var availableCapacity: Int? { get { let resourceValues = getVolumeResourceValues(for: .volumeAvailableCapacityKey) @@ -51,10 +51,12 @@ public extension Disk { } } - /// Volume’s available capacity in bytes for storing important resources. + /// Volume's available capacity in bytes for storing important resources. /// /// Indicates the amount of space that can be made available for things the user has explicitly requested in the app's UI (i.e. downloading a video or new level for a game.) /// If you need more space than what's available - let user know the request cannot be fulfilled. + #if os(iOS) + @available(iOS 11.0, *) static var availableCapacityForImportantUsage: Int? { get { let resourceValues = getVolumeResourceValues(for: .volumeAvailableCapacityForImportantUsageKey) @@ -66,10 +68,11 @@ public extension Disk { } } - /// Volume’s available capacity in bytes for storing nonessential resources. + /// Volume's available capacity in bytes for storing nonessential resources. /// /// Indicates the amount of space available for things that the user is likely to want but hasn't explicitly requested (i.e. next episode in video series they're watching, or recently updated documents in a server that they might be likely to open.) /// For these types of files you might store them initially in the caches directory until they are actually used, at which point you can move them in app support or documents directory. + @available(iOS 11.0, *) static var availableCapacityForOpportunisticUsage: Int? { get { let resourceValues = getVolumeResourceValues(for: .volumeAvailableCapacityForOpportunisticUsageKey) @@ -80,4 +83,6 @@ public extension Disk { } } } + #endif } + diff --git a/Sources/Disk+[UIImage].swift b/Sources/Disk+[UIImage].swift index fd5dbc2..c7d4eec 100644 --- a/Sources/Disk+[UIImage].swift +++ b/Sources/Disk+[UIImage].swift @@ -20,7 +20,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#if os(macOS) +#else import Foundation +import UIKit public extension Disk { /// Save an array of images to disk @@ -191,6 +194,6 @@ public extension Disk { throw error } } - + } - +#endif diff --git a/Sources/Disk.h b/Sources/Disk.h index d0fd43c..c65fdae 100644 --- a/Sources/Disk.h +++ b/Sources/Disk.h @@ -20,7 +20,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#import +#import +#import "DiskErrors.h" //! Project version number for Disk. FOUNDATION_EXPORT double DiskVersionNumber; diff --git a/Sources/Disk.swift b/Sources/Disk.swift index e43d7e5..0f9b221 100644 --- a/Sources/Disk.swift +++ b/Sources/Disk.swift @@ -37,8 +37,10 @@ public class Disk { public enum Directory: Equatable { /// Only documents and other data that is user-generated, or that cannot otherwise be recreated by your application, should be stored in the /Documents directory. /// Files in this directory are automatically backed up by iCloud. To disable this feature for a specific file, use the .doNotBackup(:in:) method. + #if os(tvOS) + #else case documents - + #endif /// Data that can be downloaded again or regenerated should be stored in the /Library/Caches directory. Examples of files you should put in the Caches directory include database cache files and downloadable content, such as that used by magazine, newspaper, and map applications. /// Use this directory to write any application-specific support files that you want to persist between launches of the application or during application updates. Your application is generally responsible for adding and removing these files. It should also be able to re-create these files as needed because iTunes removes them during a full restoration of the device. In iOS 2.2 and later, the contents of this directory are not backed up by iTunes. /// Note that the system may delete the Caches/ directory to free up disk space, so your app must be able to re-create or download these files as needed. @@ -46,37 +48,51 @@ public class Disk { /// Put app-created support files in the /Library/Application support directory. In general, this directory includes files that the app uses to run but that should remain hidden from the user. This directory can also include data files, configuration files, templates and modified versions of resources loaded from the app bundle. /// Files in this directory are automatically backed up by iCloud. To disable this feature for a specific file, use the .doNotBackup(:in:) method. + #if os(tvOS) + #else case applicationSupport + #endif - /// Data that is used only temporarily should be stored in the /tmp directory. Although these files are not backed up to iCloud, remember to delete those files when you are done with them so that they do not continue to consume space on the user’s device. + /// Data that is used only temporarily should be stored in the /tmp directory. Although these files are not backed up to iCloud, remember to delete those files when you are done with them so that they do not continue to consume space on the user's device. /// The system will periodically purge these files when your app is not running; therefore, you cannot rely on these files persisting after your app terminates. case temporary /// Sandboxed apps that need to share files with other apps from the same developer on a given device can use a shared container along with the com.apple.security.application-groups entitlement. /// The shared container or "app group" identifier string is used to locate the corresponding group's shared directory. /// For more details, visit https://developer.apple.com/documentation/foundation/nsfilemanager/1412643-containerurlforsecurityapplicati + #if os(tvOS) + #else case sharedContainer(appGroupName: String) + #endif public var pathDescription: String { switch self { + #if os(tvOS) + #else case .documents: return "/Documents" - case .caches: return "/Library/Caches" + case .sharedContainer(let appGroupName): return "\(appGroupName)" case .applicationSupport: return "/Library/Application" + #endif + case .caches: return "/Library/Caches" case .temporary: return "/tmp" - case .sharedContainer(let appGroupName): return "\(appGroupName)" } } - + static public func ==(lhs: Directory, rhs: Directory) -> Bool { switch (lhs, rhs) { - case (.documents, .documents), (.caches, .caches), (.applicationSupport, .applicationSupport), (.temporary, .temporary): + #if os(tvOS) + #else + case (.documents, .documents), (.applicationSupport, .applicationSupport): return true case (let .sharedContainer(appGroupName: name1), let .sharedContainer(appGroupName: name2)): return name1 == name2 + #endif + case (.caches, .caches), (.temporary, .temporary): + return true default: return false } } - + } } diff --git a/Sources/DiskErrors.h b/Sources/DiskErrors.h new file mode 100644 index 0000000..73b106b --- /dev/null +++ b/Sources/DiskErrors.h @@ -0,0 +1,24 @@ +// +// DiskErrors.h +// Disk +// +// Created by Sven Titgemeyer on 18.10.18. +// Copyright © 2018 Saoud Rizwan. All rights reserved. +// + +#import + +/// Domain for Disk Errors. +/// +/// Define Errors in Objective-C to get better Bridging between Swift/Objective-C. +/// Errors are imported as `DiskError` in Swift. +extern NSErrorDomain const DiskErrorDomain; +typedef NS_ERROR_ENUM(DiskErrorDomain, DiskError) { + DiskErrorNoFileFound = 0, + DiskErrorSerialization = 1, + DiskErrorDeserialization = 2, + DiskErrorInvalidFileName = 3, + DiskErrorCouldNotAccessTemporaryDirectory = 4, + DiskErrorCouldNotAccessUserDomainMask = 5, + DiskErrorCouldNotAccessSharedContainer = 6 +}; diff --git a/Sources/DiskErrors.m b/Sources/DiskErrors.m new file mode 100644 index 0000000..5b4983b --- /dev/null +++ b/Sources/DiskErrors.m @@ -0,0 +1,11 @@ +// +// DiskErrors.m +// Disk +// +// Created by Sven Titgemeyer on 18.10.18. +// Copyright © 2018 Saoud Rizwan. All rights reserved. +// + +#import "DiskErrors.h" + +NSErrorDomain const DiskErrorDomain = @"DiskErrorDomain"; diff --git a/Tests/DiskTests.swift b/Tests/DiskTests.swift index 5eedb72..3a99767 100644 --- a/Tests/DiskTests.swift +++ b/Tests/DiskTests.swift @@ -805,7 +805,8 @@ class DiskTests: XCTestCase { try Disk.append(oneMessage, to: "Folder/", in: .documents) let _ = try Disk.retrieve("Folder/", from: .documents, as: [Message].self) } catch let error as NSError { - XCTAssert(error.code == Disk.ErrorCode.invalidFileName.rawValue) + XCTAssert(error is DiskError) + XCTAssert(error.code == DiskError.invalidFileName.rawValue) } }