├── tags.sketch
├── johhny-logo.sketch
├── Johnny
├── johnny-logo.png
├── Extensions
│ ├── watchOS
│ │ └── WatchKit+Johnny.swift
│ ├── UIButton+Johnny.swift
│ ├── UIColor+Johnny.swift
│ ├── UIImage+Johnny.swift
│ ├── macOS
│ │ └── AppKit+Johnny.swift
│ ├── UIImageView+Johnny.swift
│ └── common
│ │ └── Foundation+Johnny.swift
├── Log.swift
├── Johnny.h
├── Info.plist
├── Memory.swift
├── Johnny.swift
└── Disk.swift
├── Johnny tvOS
├── tvOS.modulemap
├── Johnny tvOS.h
└── Info.plist
├── Johnny macOS
├── macOS.modulemap
├── Johnny macOS.h
└── Info.plist
├── Johnny watchOS
├── watchOS.modulemap
├── Johnny watchOS.h
└── Info.plist
├── Johnny.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcshareddata
│ └── xcschemes
│ │ ├── Johnny tvOS.xcscheme
│ │ ├── Johnny macOS.xcscheme
│ │ ├── Johnny watchOS.xcscheme
│ │ └── Johnny iOS.xcscheme
└── project.pbxproj
├── .gitignore
├── JohnnyTests
├── Info.plist
├── JohnnyMemoryTests.swift
└── JohnnyDiskTests.swift
├── LICENSE
├── Johnny.podspec
├── pod.svg
├── license.svg
├── language.svg
├── platform.svg
└── README.md
/tags.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zolomatok/Johnny/HEAD/tags.sketch
--------------------------------------------------------------------------------
/johhny-logo.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zolomatok/Johnny/HEAD/johhny-logo.sketch
--------------------------------------------------------------------------------
/Johnny/johnny-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zolomatok/Johnny/HEAD/Johnny/johnny-logo.png
--------------------------------------------------------------------------------
/Johnny tvOS/tvOS.modulemap:
--------------------------------------------------------------------------------
1 | framework module Johnny {
2 | umbrella header "Johnny tvOS.h"
3 |
4 | export *
5 | module * { export * }
6 | }
--------------------------------------------------------------------------------
/Johnny macOS/macOS.modulemap:
--------------------------------------------------------------------------------
1 | framework module Johnny {
2 | umbrella header "Johnny macOS.h"
3 |
4 | export *
5 | module * { export * }
6 | }
--------------------------------------------------------------------------------
/Johnny watchOS/watchOS.modulemap:
--------------------------------------------------------------------------------
1 | framework module Johnny {
2 | umbrella header "Johnny watchOS.h"
3 |
4 | export *
5 | module * { export * }
6 | }
--------------------------------------------------------------------------------
/Johnny.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Johnny/Extensions/watchOS/WatchKit+Johnny.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WatchKit+Johnny.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 7/4/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | //import WatchKit
11 |
--------------------------------------------------------------------------------
/Johnny.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Johnny/Log.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Log.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 6/27/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct Log {
12 |
13 | fileprivate static let Tag = "[JOHNNY]"
14 | static func log(_ message: String, _ error: Error) {
15 | #if DEBUG
16 | NSLog(Tag + " " + message + ":" + (error as NSError).description)
17 | #endif
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Johnny/Extensions/UIButton+Johnny.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIButton+Johnny.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 6/30/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIButton {
12 |
13 | open func imageWithURL(_ url: String?, placeholder: UIImage? = nil, completion: ((_ image: UIImage?)->Void)? = nil) {
14 | self.imageView?.imageWithURL(url, placeholder: placeholder, completion: completion)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## OS X Finder
2 | .DS_Store
3 |
4 | ## Build generated
5 | build/
6 | DerivedData
7 |
8 | ## Various settings
9 | *.pbxuser
10 | !default.pbxuser
11 | *.mode1v3
12 | !default.mode1v3
13 | *.mode2v3
14 | !default.mode2v3
15 | *.perspectivev3
16 | !default.perspectivev3
17 | xcuserdata
18 |
19 | ## Other
20 | *.xccheckout
21 | *.moved-aside
22 | *.xcuserstate
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 |
29 | # Swift Package Manager
30 | .build/
31 |
32 | # CocoaPods
33 | Pods/
--------------------------------------------------------------------------------
/Johnny/Johnny.h:
--------------------------------------------------------------------------------
1 | //
2 | // Johnny.h
3 | // Johnny
4 | //
5 | // Created by Zolo on 6/30/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for Johnny.
12 | FOUNDATION_EXPORT double JohnnyVersionNumber;
13 |
14 | //! Project version string for Johnny.
15 | FOUNDATION_EXPORT const unsigned char JohnnyVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Johnny tvOS/Johnny tvOS.h:
--------------------------------------------------------------------------------
1 | //
2 | // Johnny tvOS.h
3 | // Johnny tvOS
4 | //
5 | // Created by Zolo on 6/30/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for Johnny tvOS.
12 | FOUNDATION_EXPORT double Johnny_tvOSVersionNumber;
13 |
14 | //! Project version string for Johnny tvOS.
15 | FOUNDATION_EXPORT const unsigned char Johnny_tvOSVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Johnny macOS/Johnny macOS.h:
--------------------------------------------------------------------------------
1 | //
2 | // Johnny macOS.h
3 | // Johnny macOS
4 | //
5 | // Created by Zolo on 6/30/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for Johnny macOS.
12 | FOUNDATION_EXPORT double Johnny_macOSVersionNumber;
13 |
14 | //! Project version string for Johnny macOS.
15 | FOUNDATION_EXPORT const unsigned char Johnny_macOSVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Johnny watchOS/Johnny watchOS.h:
--------------------------------------------------------------------------------
1 | //
2 | // Johnny watchOS.h
3 | // Johnny watchOS
4 | //
5 | // Created by Zolo on 6/30/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for Johnny watchOS.
12 | FOUNDATION_EXPORT double Johnny_watchOSVersionNumber;
13 |
14 | //! Project version string for Johnny watchOS.
15 | FOUNDATION_EXPORT const unsigned char Johnny_watchOSVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/JohnnyTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Johnny/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 3.0.5
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Johnny tvOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 3.0.5
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Johnny watchOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 3.0.5
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Johnny/Memory.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Memory.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 6/26/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 |
12 | class Memory: NSCache {
13 |
14 | override init() {
15 | super.init()
16 | #if UIKIT_COMPATIBLE && !WATCHKIT
17 | NotificationCenter.default.addObserver(self, selector: #selector(removeAllObjects), name: .UIApplicationDidReceiveMemoryWarning, object: nil)
18 | #endif
19 | }
20 |
21 | subscript(key: String) -> AnyObject? {
22 |
23 | get {
24 | return self.object(forKey: key as AnyObject)
25 | }
26 |
27 | set(newValue) {
28 | if let newValue = newValue {
29 | self.setObject(newValue, forKey: key as AnyObject)
30 | } else {
31 | self.removeObject(forKey: key as AnyObject)
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Johnny/Extensions/UIColor+Johnny.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Extension-UIColor.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 6/30/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | open class Color: Codable {
12 | let colorString: String
13 | public init?(color: UIColor?) {
14 | guard let color = color else { return nil }
15 | guard let components = color.cgColor.components else { return nil }
16 | colorString = "\(components[0]), \(components[1]), \(components[2]), \(components[3])"
17 | }
18 |
19 | open func uiColor() -> UIColor {
20 | let components = colorString.components(separatedBy: ", ")
21 | return UIColor(red: CGFloat((components[0] as NSString).floatValue),
22 | green: CGFloat((components[1] as NSString).floatValue),
23 | blue: CGFloat((components[2] as NSString).floatValue),
24 | alpha: CGFloat((components[3] as NSString).floatValue))
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Johnny macOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 3.0.5
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSHumanReadableCopyright
24 | Copyright © 2016 Zoltán Matók. All rights reserved.
25 | NSPrincipalClass
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Zoltán Matók
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Johnny.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "Johnny"
3 | s.version = "3.0.5"
4 | s.summary = "Melodic Caching in Swift"
5 | s.homepage = "https://github.com/zolomatok/Johnny"
6 | s.license = { :type => "MIT" }
7 | s.authors = { "Zoltán Matók" => "bellamycpt@gmail.com" }
8 |
9 | s.source = { :git => "https://github.com/zolomatok/Johnny.git", :tag => "3.0.5"}
10 | s.requires_arc = true
11 | s.module_name = 'Johnny'
12 | s.swift_version = '4.0'
13 |
14 | s.osx.deployment_target = "10.10"
15 | s.ios.deployment_target = "8.0"
16 | s.tvos.deployment_target = "9.0"
17 | s.watchos.deployment_target = "2.0"
18 |
19 | s.osx.source_files = 'Johnny/*.swift', 'Johnny/Extensions/common/*.swift', 'Johnny/Extensions/macOS/*.swift'
20 | s.ios.source_files = 'Johnny/*.swift', 'Johnny/Extensions/*.swift', 'Johnny/Extensions/common/*.swift'
21 | s.tvos.source_files = 'Johnny/*.swift', 'Johnny/Extensions/*.swift', 'Johnny/Extensions/common/*.swift'
22 | s.watchos.source_files = 'Johnny/*.swift', 'Johnny/Extensions/common/*.swift', 'Johnny/Extensions/UIColor.swift', 'Johnny/Extensions/UIImage.swift'
23 |
24 | s.osx.frameworks = 'AppKit', 'Foundation'
25 | s.ios.frameworks = 'UIKit', 'Foundation'
26 | s.tvos.frameworks = 'UIKit', 'Foundation'
27 | end
28 |
--------------------------------------------------------------------------------
/Johnny/Extensions/UIImage+Johnny.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+Johhny.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 6/30/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | #if WATCHKIT
11 | import WatchKit
12 | #endif
13 |
14 | // See: https://github.com/AFNetworking/AFNetworking/issues/2572#issuecomment-115854482
15 | private let imgLock = NSLock()
16 | open class Image: Codable {
17 | let data: Data
18 | public init?(image: UIImage?) {
19 | guard let image = image else { return nil }
20 | data = UIImageJPEGRepresentation(image, 1.0)!
21 | }
22 |
23 | open func uiImage() -> UIImage {
24 | imgLock.lock()
25 | let img = UIImage(data: data)!
26 | imgLock.unlock()
27 | return img
28 | }
29 | }
30 |
31 |
32 | extension UIImage {
33 |
34 | func hasAlpha() -> Bool {
35 |
36 | guard let alpha = self.cgImage?.alphaInfo else {
37 | return false
38 | }
39 |
40 | switch alpha {
41 | case .first, .last, .premultipliedFirst, .premultipliedLast, .alphaOnly:
42 | return true
43 | case .none, .noneSkipFirst, .noneSkipLast:
44 | return false
45 | }
46 | }
47 |
48 |
49 | func scaledToSize(_ toSize: CGSize) -> UIImage {
50 | UIGraphicsBeginImageContextWithOptions(toSize, !hasAlpha(), 0.0)
51 | draw(in: CGRect(x: 0, y: 0, width: toSize.width, height: toSize.height))
52 | let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
53 | UIGraphicsEndImageContext()
54 | return resizedImage!
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/pod.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/license.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/language.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Johnny/Extensions/macOS/AppKit+Johnny.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppKit+Johnny.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 7/4/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import AppKit
11 |
12 |
13 | // See: https://github.com/AFNetworking/AFNetworking/issues/2572#issuecomment-115854482
14 | private let imgLock = NSLock()
15 | class Image: Codable {
16 | let data: Data
17 | init?(image: NSImage?) {
18 | guard let image = image else { return nil }
19 | guard let d = image.tiffRepresentation else { return nil }
20 | data = d
21 | }
22 |
23 | func nsImage() -> NSImage {
24 | imgLock.lock()
25 | let img = NSImage(data: data)!
26 | imgLock.unlock()
27 | return img
28 | }
29 | }
30 |
31 |
32 | extension NSImageView {
33 |
34 | open func imageWithURL(_ url: String?, placeholder: NSImage? = nil, completion: ((_ image: NSImage?)->Void)? = nil) {
35 |
36 | // Handle nil
37 | guard let url = url else {
38 | completion?(nil)
39 | return
40 | }
41 |
42 |
43 | // Set placeholder
44 | if let placeholder = placeholder {
45 | self.image = placeholder
46 | }
47 |
48 |
49 | // Get cache
50 | Johnny.pull(url) { (cached: Image?) in
51 |
52 |
53 | // Return cached value
54 | if let cached = cached {
55 | if completion == nil { self.image = cached.nsImage() }
56 | else { completion?(cached.nsImage()) }
57 | return
58 | }
59 |
60 |
61 | // Download from URL
62 | var img: NSImage?
63 | DispatchQueue.global(qos: .background).async {
64 | let data = try? Data(contentsOf: URL(string: url)!)
65 | if let data = data {
66 | img = NSImage(data: data)
67 | }
68 |
69 | DispatchQueue.main.async {
70 | // Save to cache & return
71 | if img != nil { Johnny.cache(Image(image: img), key: url) }
72 | if completion == nil {
73 | self.image = img
74 | }
75 | else { completion?(img) }
76 |
77 | }
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/platform.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Johnny/Extensions/UIImageView+Johnny.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIImageView+Johnny.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 6/27/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIImageView {
12 |
13 | open func imageWithURL(_ url: String?, placeholder: UIImage? = nil, completion: ((_ image: UIImage?)->Void)? = nil) {
14 |
15 | // Handle nil
16 | guard let url = url else {
17 | completion?(nil)
18 | return
19 | }
20 |
21 |
22 | // Set placeholder
23 | if let placeholder = placeholder {
24 | self.image = placeholder
25 | }
26 |
27 |
28 | // Get cache
29 | Johnny.pull(url) { (cached: Image?) in
30 |
31 |
32 | // Return cached value
33 | if let cached = cached {
34 | if completion == nil { self.image = cached.uiImage() }
35 | else { completion?(cached.uiImage()) }
36 | return
37 | }
38 |
39 |
40 | // Download from URL
41 | var img: UIImage?
42 | DispatchQueue.global(qos: .background).async {
43 | let data = try? Data(contentsOf: URL(string: url)!)
44 | if let data = data {
45 | img = UIImage(data: data)
46 | // img = self.resizeImage(img)
47 | }
48 |
49 | DispatchQueue.main.async {
50 | // Save to cache & return
51 | if let img = img { Johnny.cache(Image(image: img), key: url) }
52 | if completion == nil {
53 | self.image = img
54 | }
55 | else { completion?(img) }
56 | }
57 | }
58 | }
59 | }
60 |
61 |
62 | fileprivate func resizeImage(_ img: UIImage?) -> UIImage? {
63 |
64 | guard let img = img else { return nil }
65 |
66 |
67 | // Get target size
68 | var targetSize: CGSize
69 | switch self.contentMode {
70 | case .scaleToFill:
71 | targetSize = bounds.size
72 | case .scaleAspectFit:
73 | targetSize = img.size.aspectFitSize(bounds.size)
74 | case .scaleAspectFill:
75 | targetSize = img.size.aspectFillSize(bounds.size)
76 | default:
77 | return img
78 | }
79 | assert(bounds.size.width > 0 && bounds.size.height > 0, "Expected non-zero size.")
80 |
81 |
82 | // Avoid unnecessary computations
83 | if (targetSize.width == img.size.width && targetSize.height == img.size.height) {
84 | return img
85 | }
86 |
87 |
88 | // Resize
89 | let resizedImage = img.scaledToSize(targetSize)
90 | return resizedImage
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Johnny.xcodeproj/xcshareddata/xcschemes/Johnny tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Johnny.xcodeproj/xcshareddata/xcschemes/Johnny macOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Johnny.xcodeproj/xcshareddata/xcschemes/Johnny watchOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Johnny/Extensions/common/Foundation+Johnny.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Foundation+Johnny.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 7/4/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import CoreGraphics
11 |
12 | protocol Cachable: Codable {}
13 |
14 | extension CGSize {
15 |
16 | func aspectFillSize(_ size: CGSize) -> CGSize {
17 | let scaleWidth = size.width / self.width
18 | let scaleHeight = size.height / self.height
19 | let scale = max(scaleWidth, scaleHeight)
20 |
21 | let resultSize = CGSize(width: self.width * scale, height: self.height * scale)
22 | return CGSize(width: ceil(resultSize.width), height: ceil(resultSize.height))
23 | }
24 |
25 | func aspectFitSize(_ size: CGSize) -> CGSize {
26 | let targetAspect = size.width / size.height
27 | let sourceAspect = self.width / self.height
28 | var resultSize = size
29 |
30 | if (targetAspect > sourceAspect) {
31 | resultSize.width = size.height * sourceAspect
32 | }
33 | else {
34 | resultSize.height = size.width / sourceAspect
35 | }
36 | return CGSize(width: ceil(resultSize.width), height: ceil(resultSize.height))
37 | }
38 | }
39 |
40 |
41 | extension FileManager {
42 |
43 | func enumerateContentsOfDirectoryAtPath(_ path: String, orderedByProperty property: String, ascending: Bool, usingBlock block: (URL, Int, inout Bool) -> Void ) {
44 |
45 | let directoryURL = URL(fileURLWithPath: path)
46 | do {
47 | let contents = try self.contentsOfDirectory(at: directoryURL, includingPropertiesForKeys: [URLResourceKey(rawValue: property)], options: FileManager.DirectoryEnumerationOptions())
48 | let sortedContents = contents.sorted(by: {(URL1: URL, URL2: URL) -> Bool in
49 |
50 | // Maybe there's a better way to do this. See: http://stackoverflow.com/questions/25502914/comparing-anyobject-in-swift
51 |
52 | var value1 : AnyObject?
53 | do {
54 | try (URL1 as NSURL).getResourceValue(&value1, forKey: URLResourceKey(rawValue: property));
55 | } catch {
56 | return true
57 | }
58 | var value2 : AnyObject?
59 | do {
60 | try (URL2 as NSURL).getResourceValue(&value2, forKey: URLResourceKey(rawValue: property));
61 | } catch {
62 | return false
63 | }
64 |
65 | if let string1 = value1 as? String, let string2 = value2 as? String {
66 | return ascending ? string1 < string2 : string2 < string1
67 | }
68 |
69 | if let date1 = value1 as? Date, let date2 = value2 as? Date {
70 | return ascending ? date1 < date2 : date2 < date1
71 | }
72 |
73 | if let number1 = value1 as? NSNumber, let number2 = value2 as? NSNumber {
74 | return ascending ? number1 < number2 : number2 < number1
75 | }
76 |
77 | return false
78 | })
79 |
80 | for (i, v) in sortedContents.enumerated() {
81 | var stop : Bool = false
82 | block(v, i, &stop)
83 | if stop { break }
84 | }
85 |
86 | } catch {
87 | print("Failed to list directory", error as NSError)
88 | }
89 | }
90 |
91 | }
92 |
93 | func < (lhs: NSNumber, rhs: NSNumber) -> Bool {
94 | return lhs.compare(rhs) == ComparisonResult.orderedAscending
95 | }
96 |
--------------------------------------------------------------------------------
/Johnny/Johnny.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Johnny.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 6/26/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | #if UIKIT_COMPATIBLE
11 | import UIKit
12 | #endif
13 |
14 |
15 | // Used to add T to NSCache
16 | class Shell : NSObject {
17 | let value: Any?
18 | init(value: Any?) {
19 | self.value = value
20 | }
21 | }
22 |
23 |
24 |
25 | open class Johnny {
26 |
27 | static let memory = Memory()
28 | static let disk = Disk()
29 |
30 |
31 | // MARK: - In
32 | /**
33 | Caches a Storable object
34 |
35 | - parameter value: The value to be cached
36 | - parameter key: The key for pulling the object from the cache
37 | */
38 | open class func cache(_ value: T?, key: String, library: Bool = false) {
39 | guard let value = value else { return }
40 |
41 | // Store in memory
42 | memory[key] = Shell(value: value)
43 |
44 | // Store in disk
45 | DispatchQueue.global(qos: .background).async {
46 | let d = try? JSONEncoder().encode(value)
47 | guard let data = d else { return }
48 | disk[key, library] = data
49 | }
50 | }
51 |
52 |
53 | // MARK: - Delete
54 | /**
55 | Delete a Storable object
56 |
57 | - parameter key: The key for deleting the object from the cache
58 | */
59 | open class func delete(_ key: String, library: Bool = false) {
60 | memory[key] = nil
61 | disk[key, library] = nil
62 | }
63 |
64 |
65 |
66 | // MARK: - Out
67 | /**
68 | Retrieves a Storable object for a given key
69 |
70 | - parameter key: The key for pulling the object from the cache
71 |
72 | - returns: The stored object, nil if not found
73 | */
74 | open class func pull(_ key: String, library: Bool = false) -> T? {
75 |
76 | // Check memory
77 | if let value = (memory[key] as? Shell)?.value as? T { return value }
78 |
79 |
80 | // Check disk
81 | if let data = disk[key, library] {
82 |
83 | let value = try? JSONDecoder().decode(T.self, from: data)
84 | if let value = value { memory[key] = Shell(value: value) }
85 | return value
86 | }
87 |
88 | return nil
89 | }
90 |
91 |
92 | // MARK: - Async Out
93 | /**
94 | Asyncronously retrieves a Storable object for a given key
95 |
96 | - parameter key: The key for pulling the object from the cache
97 |
98 | - returns: The stored object, nil if not found
99 | */
100 | open class func pull(_ key: String, library: Bool = false, completion: ((_ value: T?)->Void)? = nil ) {
101 |
102 | // Check memory
103 | if let value = (memory[key] as? Shell)?.value as? T {
104 | completion?(value)
105 | return
106 | }
107 |
108 |
109 | // Check disk
110 | var value: T?
111 | DispatchQueue.global(qos: .background).async {
112 | let data = disk[key, library]
113 | if data != nil {
114 | value = try? JSONDecoder().decode(T.self, from: data!)
115 | }
116 |
117 | DispatchQueue.main.async {
118 | guard let value = value else { completion?(nil); return }
119 |
120 | memory[key] = Shell(value: value)
121 | completion?(value)
122 | }
123 | }
124 | }
125 |
126 |
127 |
128 | // MARK: - Clear
129 | /**
130 | Nukes the entire cache from memory & disk
131 | */
132 | @objc open class func nuke() {
133 | memory.removeAllObjects()
134 | disk.nuke(nil)
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/Johnny.xcodeproj/xcshareddata/xcschemes/Johnny iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
65 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
90 |
91 |
92 |
93 |
95 |
96 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | 
4 | 
5 |
6 | Johnny is a generic caching library written for Swift 4.
7 |
8 | ## Features
9 | **Johnny can cache any model object that conforms to the `Cachable` protocol.**
10 |
11 | - [x] Out-of-the-box support:
12 | - String, Bool, Int, UInt, Int64, UInt64, Float, Double
13 | - URL, Data, Date
14 | - UIImage, UIColor **by wrapping them in an Image or Color wrapper class respectively**
15 | - Arrays, Dictionaries and Sets of the above
16 | - [x] Multiplatform, supporting iOS, macOS, tvOS & watchOS
17 | - [x] First-level memory cache using `NSCache`
18 | - [x] Second-level LRU disk cache
19 | - [x] Disk access in background thread (always when saving, optionally when fetching)
20 | - [x] Syncronous & Asynchronous API support
21 | - [x] Automatic cache eviction on memory warnings & disk capacity reached
22 | - [x] Unit tested
23 | - [x] Concise, well-structured code to encourage contributions
24 |
25 | Extra ❤️ for images:
26 | - [x] `func setImageWithURL` extension on UIImageView, UIButton & NSImageView, optimized for cell reuse
27 |
28 | ## Usage
29 |
30 | ### Caching ###
31 | ```swift
32 | Johnny.cache(user, key: "LocalUser")
33 |
34 | let imgage = UIImage(named: "awesomeness")
35 | Johnny.cache(Image(image), key: "Image") // Caching a UIImage. UIColor objects must be wrapped in the Color wrapper class the same way.
36 |
37 | // You can flag a value to be stored in the Library instead of the Caches folder if you don't want it to be automatically purged:
38 | Johnny.cache(Date(), key: "FirstStart", library: true)
39 | ```
40 |
41 | ### Pulling ###
42 |
43 | ```swift
44 | // The type of the retrived value must be explicitly stated for the compiler.
45 | let date: Date? = Johnny.pull("FirstStart")
46 |
47 | // If you know you are retrieving a large object (> 1.5 MB) you can do it asynchronously
48 | Johnny.pull("4KImage") { (image: Image?) in
49 | let img = image.uiImage()
50 | }
51 | ```
52 |
53 | ### Removing ###
54 | ```swift
55 | Johnny.remove("LocalUser")
56 | ```
57 |
58 |
59 | ## Examples
60 |
61 | ### Collections ###
62 |
63 | You can cache any collection of items conforming to the Storable protocol (most standard library data types already do)
64 |
65 | ```swift
66 | let array: [String] = ["Folsom", "Prison", "Blues"]
67 | let stringSet: Set = ["I've", "been", "everywhere"]
68 | // In case of dictionaries, the value must explicitly conform to Storable (so [String: AnyObject] does not work, while [String: Double] does)
69 | let dictionary: [String: String] = ["first": "Solitary", "second": "man"]
70 |
71 | Johnny.cache(array, key: "folsom")
72 | Johnny.cache(stringSet, key: "everywhere")
73 | Johnny.cache(dictionary, key: "solitary")
74 | ```
75 |
76 | ### Custom types ###
77 |
78 | Due to current Swift limitations, since the Storable protocol has an `associatedType`, conformance must be added through an extension.
79 | `class User: Storable` will not work.
80 |
81 |
82 | ```swift
83 | struct User {
84 |
85 | enum Badassery: String { case Total }
86 |
87 | var name: String?
88 | var uid: Int
89 | var badassery: Badassery
90 | }
91 |
92 |
93 | extension User: Storable {
94 | typealias Result = User
95 |
96 | static func fromData(data: NSData) -> User.Result? {
97 | let dict = try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as! [NSObject: AnyObject]
98 |
99 | let user = User()
100 | user.uid = dict["identification"] as! Int
101 | user.name = dict["name"] as? String
102 | user.badassery = Badassery(rawValue: dict["badassery"] as! String)!
103 | return user
104 | }
105 |
106 | func toData() -> NSData {
107 | let json = ["identification": uid, "name": name, "badassery": badassery.rawValue]
108 | return try! NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions())
109 | }
110 | }
111 | ```
112 |
113 | **Using it with Johnny:**
114 |
115 |
116 | ```swift
117 | let lily = User(name: "Lily", uid: 84823682, badassery: .Total)
118 | Johnny.cache(lily, key: "Lily")
119 |
120 | let cachedLily: User = Johnny.pull("Lily")
121 | ```
122 |
123 | ## Requirements
124 | - iOS 8.0+
125 | - macOS 10.10+
126 | - tvOS 9.0+
127 | - watchOS 2.0+
128 | - Swift 4.0
129 |
130 | ## Install
131 |
132 | **CocoaPods**
133 |
134 | ```
135 | pod 'Johnny'
136 | ```
137 |
138 | **Carthage**
139 |
140 | ```
141 | github "zolomatok/Johnny"
142 | ```
143 |
144 | **Manual**
145 | - Clone the project
146 | - Select the scheme (platform) and build
147 | - Drag Johnny.framework to your project
148 | - In the project settings under your target's General tab, scroll down and add Johhny to the ```Embedded Binaries``` section if it's not already added.
149 |
150 |
151 | ## Attribution
152 | I'd like to thank the creators of [Pantry](https://github.com/nickoneill/Pantry) and [Haneke](https://github.com/Haneke/HanekeSwift) as those projects provided much of the inspiration and some code. Johnny was dreamed up to be the best of both worlds.
153 |
154 | ## License
155 | Johnny is released under the MIT license. See LICENSE for details.
156 |
--------------------------------------------------------------------------------
/Johnny/Disk.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Disk.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 6/26/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Disk {
12 |
13 | fileprivate let cachePath = (NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("io.johhny")
14 | fileprivate let libraryPath = (NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.libraryDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("io.johhny")
15 | fileprivate var size: UInt64 = 0
16 | fileprivate var capacity = UINT64_MAX
17 | fileprivate var diskQueue = DispatchQueue(label: "io.johhny.disk")
18 |
19 |
20 | // MARK: - Init
21 | init() {
22 | createDirectory()
23 |
24 | diskQueue.async {
25 | self.calculateSize()
26 | }
27 |
28 | #if UIKIT_COMPATIBLE && !WATCHKIT
29 | NotificationCenter.default.addObserver(self, selector: #selector(nuke), name: .UIApplicationDidReceiveMemoryWarning, object: nil)
30 | #endif
31 | }
32 |
33 |
34 | // MARK: - Operations
35 | subscript(key: String) -> Data? {
36 | get { return get(key) }
37 | set(newValue) {
38 | diskQueue.async {
39 | if newValue != nil { self.add(key, newValue: newValue!) }
40 | else { self.remove(key) }
41 | }
42 | }
43 | }
44 |
45 | subscript(key: String, library: Bool) -> Data? {
46 | get { return get(key, library: library) }
47 | set(newValue) {
48 | diskQueue.async {
49 | if newValue != nil { self.add(key, newValue: newValue!, library: library) }
50 | else { self.remove(key, library: library) }
51 | }
52 | }
53 | }
54 |
55 |
56 | fileprivate func get(_ key: String, library: Bool = false) -> Data? {
57 | let path = getPath(key, library: library)
58 | let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: Data.ReadingOptions())
59 | updateAccessDate(path)
60 | return data
61 | }
62 |
63 |
64 | fileprivate func add(_ key: String, newValue: Data, library: Bool = false) {
65 | createDirectory()
66 |
67 | let path = getPath(key, library: library)
68 | let pastAttributes = try? FileManager.default.attributesOfItem(atPath: path) as NSDictionary
69 | do {
70 | try newValue.write(to: URL(fileURLWithPath: path), options: .atomicWrite)
71 | if let attributes = pastAttributes {
72 | self.substractSize(attributes.fileSize())
73 | }
74 | size += UInt64(newValue.count)
75 | controlSize()
76 | } catch {
77 | if isNoSuchFileError(error as NSError) { Log.log("Failed to write key \(key)", error) }
78 | }
79 | }
80 |
81 | fileprivate func remove(_ key: String, library: Bool = false) {
82 |
83 | // Only proceed if file exists, otherwise, the whole containing dir will be removed
84 | guard FileManager.default.fileExists(atPath: getPath(key, library: library), isDirectory: nil) == true else {
85 | return
86 | }
87 |
88 | do {
89 | let attributes : NSDictionary = try FileManager.default.attributesOfItem(atPath: library ? libraryPath : cachePath) as NSDictionary
90 | let fileSize = attributes.fileSize()
91 | print("JOHNNY REMOVING PATH: ", getPath(key, library: library))
92 | try FileManager.default.removeItem(atPath: getPath(key, library: library))
93 | substractSize(fileSize)
94 | } catch {
95 | if isNoSuchFileError(error as NSError) { Log.log("File remove error", error) }
96 | }
97 | }
98 |
99 |
100 | @objc func nuke(libraryToo: Bool = false, _ completion: (()->Void)? = nil) {
101 | diskQueue.async {
102 |
103 | if libraryToo {
104 | let contents = try? FileManager.default.contentsOfDirectory(atPath: self.libraryPath)
105 | contents?.forEach({ (fileName) in
106 | let filePath = (self.libraryPath as NSString).appendingPathComponent(fileName)
107 | _ = try? FileManager.default.removeItem(atPath: filePath)
108 | })
109 | }
110 |
111 | let contents = try? FileManager.default.contentsOfDirectory(atPath: self.cachePath)
112 | contents?.forEach({ (fileName) in
113 | let filePath = (self.cachePath as NSString).appendingPathComponent(fileName)
114 | _ = try? FileManager.default.removeItem(atPath: filePath)
115 | })
116 |
117 | self.calculateSize()
118 |
119 | DispatchQueue.main.async {
120 | completion?()
121 | }
122 | }
123 | }
124 |
125 |
126 |
127 | // MARK: - Maintenance
128 | func getPath(_ key: String, library: Bool = false) -> String {
129 | let escapedFilename = [ "\0":"%00", ":":"%3A", "/":"%2F" ]
130 | .reduce(key.components(separatedBy: "%").joined(separator: "%25")) {
131 | str, m in str.components(separatedBy: m.0).joined(separator: m.1) }
132 | return ((library ? libraryPath : cachePath) as NSString).appendingPathComponent(escapedFilename)
133 | }
134 |
135 | fileprivate func createDirectory() {
136 |
137 | // Cache
138 | var isDir: ObjCBool = false
139 | let exists = FileManager.default.fileExists(atPath: cachePath, isDirectory: &isDir)
140 | if !exists || !isDir.boolValue {
141 | try! FileManager.default.createDirectory(atPath: cachePath, withIntermediateDirectories: true, attributes: nil)
142 | }
143 |
144 | // Library
145 | var isDirLib: ObjCBool = false
146 | let existsLib = FileManager.default.fileExists(atPath: libraryPath, isDirectory: &isDirLib)
147 | if !existsLib || !isDirLib.boolValue {
148 | try! FileManager.default.createDirectory(atPath: libraryPath, withIntermediateDirectories: true, attributes: nil)
149 | }
150 | }
151 |
152 | fileprivate func calculateSize() {
153 | size = 0
154 |
155 | do {
156 | let contents = try FileManager.default.contentsOfDirectory(atPath: cachePath)
157 | for fileName in contents {
158 | let p = (cachePath as NSString).appendingPathComponent(fileName)
159 | do {
160 | let attributes : NSDictionary = try FileManager.default.attributesOfItem(atPath: p) as NSDictionary
161 | size += attributes.fileSize()
162 | } catch {
163 | if self.isNoSuchFileError(error as NSError) { Log.log("Failed to read file size of \(p)", error) }
164 | }
165 | }
166 | } catch {
167 | if self.isNoSuchFileError(error as NSError) { Log.log("Failed to list directory", error) }
168 | }
169 | }
170 |
171 |
172 | fileprivate func controlSize() {
173 |
174 | if size <= capacity { return }
175 |
176 | let fileManager = FileManager.default
177 | fileManager.enumerateContentsOfDirectoryAtPath(cachePath, orderedByProperty: URLResourceKey.contentModificationDateKey.rawValue, ascending: true) { (URL : Foundation.URL, _, stop : inout Bool) -> Void in
178 |
179 | self[(URL.path as NSString).deletingLastPathComponent] = nil
180 | stop = self.size <= self.capacity
181 | }
182 | }
183 |
184 |
185 | fileprivate func substractSize(_ s : UInt64) {
186 | size = size >= s ? size-s : 0
187 | }
188 |
189 |
190 | fileprivate func updateAccessDate(_ path: String) {
191 | diskQueue.async {
192 | let now = Date()
193 | do {
194 | try FileManager.default.setAttributes([FileAttributeKey.modificationDate : now], ofItemAtPath: path)
195 | } catch {
196 | if self.isNoSuchFileError(error as NSError) { Log.log("Failed to update access date", error) }
197 | }
198 | }
199 | }
200 |
201 |
202 | fileprivate func isNoSuchFileError(_ error : NSError?) -> Bool {
203 | if let error = error {
204 | return NSCocoaErrorDomain == error.domain && error.code == NSFileReadNoSuchFileError
205 | }
206 | return false
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/JohnnyTests/JohnnyMemoryTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // JohnnyTests.swift
3 | // JohnnyTests
4 | //
5 | // Created by Zolo on 7/27/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import Johnny
11 |
12 | class JohnnyMemoryTests: XCTestCase {
13 |
14 | private lazy var __once: () = {
15 | let cachesPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0]
16 | let johhny = "io.johhny"
17 | let path = (cachesPath as NSString).appendingPathComponent(johhny)
18 | let paths = try? FileManager.default.contentsOfDirectory(atPath: path)
19 | if let paths = paths {
20 | for p in paths {
21 | let _ = try? FileManager.default.removeItem(atPath: p)
22 | }
23 | }
24 | }()
25 |
26 | override func setUp() {
27 | super.setUp()
28 | _ = self.__once
29 | }
30 |
31 | override func tearDown() { super.tearDown() }
32 |
33 |
34 | func testDefaultTypes() {
35 | let string: String = "Heresy grows from idleness"
36 | let bool: Bool = true
37 | let int: Int = 1
38 | let int64: Int64 = 2
39 | let uint: UInt = 3
40 | let uint64: UInt64 = 4
41 | let float: Float = 10.2
42 | let double: Double = 20.6
43 |
44 | let ip = Bundle(for: type(of: self)).resourcePath! + "/johnny-logo.png"
45 | let image = Image(image: UIImage(contentsOfFile: ip)!)
46 | let data = image!.data
47 | let date: Date = Date(timeIntervalSince1970: 1459355217)
48 | let color: Color = Color(color: UIColor.blue)!
49 |
50 |
51 | Johnny.cache(string, key: "testString")
52 | Johnny.cache(bool, key: "testBool")
53 | Johnny.cache(int, key: "testInt")
54 | Johnny.cache(int64, key: "testInt64")
55 | Johnny.cache(uint, key: "testUInt")
56 | Johnny.cache(uint64, key: "testUInt64")
57 | Johnny.cache(float, key: "testFloat")
58 | Johnny.cache(double, key: "testDouble")
59 | Johnny.cache(image, key: "testImage")
60 | Johnny.cache(data, key: "testData")
61 | Johnny.cache(date, key: "testDate")
62 | Johnny.cache(color, key: "testColor")
63 |
64 |
65 | if let value: String = Johnny.pull("testString") {
66 | XCTAssert(value == "Heresy grows from idleness", "default string was incorrect")
67 | } else {
68 | XCTFail("no default string could be unpacked")
69 | }
70 |
71 | if let value: Bool = Johnny.pull("testBool") {
72 | XCTAssert(value == true, "default bool was incorrect")
73 | } else {
74 | XCTFail("no default bool could be unpacked")
75 | }
76 |
77 | if let value: Int = Johnny.pull("testInt") {
78 | XCTAssert(value == 1, "default int was incorrect")
79 | } else {
80 | XCTFail("no default int could be unpacked")
81 | }
82 |
83 | if let value: Int64 = Johnny.pull("testInt64") {
84 | XCTAssert(value == 2, "default int64 was incorrect")
85 | } else {
86 | XCTFail("no default int64 could be unpacked")
87 | }
88 |
89 | if let value: UInt = Johnny.pull("testUInt") {
90 | XCTAssert(value == 3, "default uint was incorrect")
91 | } else {
92 | XCTFail("no default uint could be unpacked")
93 | }
94 |
95 | if let value: UInt64 = Johnny.pull("testUInt64") {
96 | XCTAssert(value == 4, "default uint64 was incorrect")
97 | } else {
98 | XCTFail("no default uint64 could be unpacked")
99 | }
100 |
101 | if let value: Float = Johnny.pull("testFloat") {
102 | XCTAssert(value == 10.2, "default float was incorrect")
103 | } else {
104 | XCTFail("no default float could be unpacked")
105 | }
106 |
107 | if let value: Double = Johnny.pull("testDouble") {
108 | XCTAssert(value == 20.6, "default Double was incorrect")
109 | } else {
110 | XCTFail("no default Double could be unpacked")
111 | }
112 |
113 | if let value: Image = Johnny.pull("testImage") {
114 | XCTAssert(value.data == data, "default Image was incorrect")
115 | } else {
116 | XCTFail("no default Image could be unpacked")
117 | }
118 |
119 | if let value: Data = Johnny.pull("testData") {
120 | XCTAssert(value == data, "default Data was incorrect")
121 | } else {
122 | XCTFail("no default Data could be unpacked")
123 | }
124 |
125 | if let value: Date = Johnny.pull("testDate") {
126 | XCTAssert(value.timeIntervalSince1970 == 1459355217 , "default Date was incorrect")
127 | } else {
128 | XCTFail("no default Date could be unpacked")
129 | }
130 |
131 | if let value: Color = Johnny.pull("testColor") {
132 | XCTAssert(value.uiColor() == UIColor.blue, "default Color was incorrect")
133 | } else {
134 | XCTFail("no default Color could be unpacked")
135 | }
136 | }
137 |
138 |
139 | func testOptionalDefaultTypes() {
140 | let string: String? = "Heresy grows from idleness"
141 | let int: Int? = 1
142 | let int64: Int64? = 2
143 | let uint: UInt? = 3
144 | let uint64: UInt64? = 4
145 | let float: Float? = 10.2
146 | let double: Double? = 20.6
147 |
148 | let ip = Bundle(for: type(of: self)).resourcePath! + "/johnny-logo.png"
149 | let image = Image(image: UIImage(contentsOfFile: ip))
150 | let data: Data? = image?.data
151 | let date: Date? = Date(timeIntervalSince1970: 1459355217)
152 | let color: Color? = Color(color: UIColor.blue)
153 |
154 |
155 | Johnny.cache(string, key: "testStringOptional")
156 | Johnny.cache(int, key: "testIntOptional")
157 | Johnny.cache(int64, key: "testInt64Optional")
158 | Johnny.cache(uint, key: "testUIntOptional")
159 | Johnny.cache(uint64, key: "testUInt64Optional")
160 | Johnny.cache(float, key: "testFloatOptional")
161 | Johnny.cache(double, key: "testDoubleOptional")
162 | Johnny.cache(image, key: "testImageOptional")
163 | Johnny.cache(data, key: "testDataOptional")
164 | Johnny.cache(date, key: "testDateOptional")
165 | Johnny.cache(color, key: "testColorOptional")
166 |
167 |
168 | if let value: String = Johnny.pull("testStringOptional") {
169 | XCTAssert(value == "Heresy grows from idleness", "default optional string was incorrect")
170 | } else {
171 | XCTFail("no default optional string could be unpacked")
172 | }
173 |
174 | if let value: Int = Johnny.pull("testIntOptional") {
175 | XCTAssert(value == 1, "default optional int was incorrect")
176 | } else {
177 | XCTFail("no default optional int could be unpacked")
178 | }
179 |
180 | if let value: Int64 = Johnny.pull("testInt64Optional") {
181 | XCTAssert(value == 2, "default optional int64 was incorrect")
182 | } else {
183 | XCTFail("no default optional int64 could be unpacked")
184 | }
185 |
186 | if let value: UInt = Johnny.pull("testUIntOptional") {
187 | XCTAssert(value == 3, "default optional uint was incorrect")
188 | } else {
189 | XCTFail("no default optional uint could be unpacked")
190 | }
191 |
192 | if let value: UInt64 = Johnny.pull("testUInt64Optional") {
193 | XCTAssert(value == 4, "default optional uint64 was incorrect")
194 | } else {
195 | XCTFail("no default optional uint64 could be unpacked")
196 | }
197 |
198 | if let value: Float = Johnny.pull("testFloatOptional") {
199 | XCTAssert(value == 10.2, "default optional float was incorrect")
200 | } else {
201 | XCTFail("no default optional float could be unpacked")
202 | }
203 |
204 | if let value: Double = Johnny.pull("testDoubleOptional") {
205 | XCTAssert(value == 20.6, "default optional Double was incorrect")
206 | } else {
207 | XCTFail("no default optional Double could be unpacked")
208 | }
209 |
210 | if let value: Image = Johnny.pull("testImageOptional") {
211 | XCTAssert(value.data == data, "default optional Image was incorrect")
212 | } else {
213 | XCTFail("no default optional Image could be unpacked")
214 | }
215 |
216 | if let value: Data = Johnny.pull("testDataOptional") {
217 | XCTAssert(value == data, "default optional Data was incorrect")
218 | } else {
219 | XCTFail("no default optional Data could be unpacked")
220 | }
221 |
222 | if let value: Date = Johnny.pull("testDateOptional") {
223 | XCTAssert(value.timeIntervalSince1970 == 1459355217 , "default optional Date was incorrect")
224 | } else {
225 | XCTFail("no default optional Date could be unpacked")
226 | }
227 |
228 | if let value: Color = Johnny.pull("testColorOptional") {
229 | XCTAssert(value.uiColor() == UIColor.blue, "default optional Color was incorrect")
230 | } else {
231 | XCTFail("no default optional Color could be unpacked")
232 | }
233 | }
234 |
235 |
236 | func testCollections() {
237 |
238 | let ip = Bundle(for: type(of: self)).resourcePath! + "/johnny-logo.png"
239 | let image = Image(image: UIImage(contentsOfFile: ip)!)
240 | let data = image!.data
241 |
242 | let stringArray: [String] = ["Heresy", "grows", "from", "idleness"]
243 | let intArray: [Int] = [1,2]
244 | let dataArray: [Data] = [data]
245 |
246 | let stringMap: [String: String] = ["first": "Heresy", "second": "grows"]
247 | let intMap: [String: Int] = ["first": 1, "second": 2]
248 | let dataMap: [String: Data] = ["first": data]
249 |
250 | let stringSet: Set = ["Heresy", "grows", "from", "idleness"]
251 | let intSet: Set = [1,2]
252 | let dataSet: Set = [data]
253 |
254 |
255 | Johnny.cache(stringArray, key: "testStringArray")
256 | Johnny.cache(intArray, key: "testIntArray")
257 | Johnny.cache(dataArray, key: "testDataArray")
258 | Johnny.cache(stringMap, key: "testStringMap")
259 | Johnny.cache(intMap, key: "testIntMap")
260 | Johnny.cache(dataMap, key: "testDataMap")
261 | Johnny.cache(stringSet, key: "testStringSet")
262 | Johnny.cache(intSet, key: "testIntSet")
263 | Johnny.cache(dataSet, key: "testDataSet")
264 |
265 |
266 | if let value: [String] = Johnny.pull("testStringArray") {
267 | XCTAssert(value == ["Heresy", "grows", "from", "idleness"], "default string array was incorrect")
268 | } else {
269 | XCTFail("no default string array could be unpacked")
270 | }
271 |
272 | if let value: [Int] = Johnny.pull("testIntArray") {
273 | XCTAssert(value == [1,2], "default int array was incorrect")
274 | } else {
275 | XCTFail("no default int array could be unpacked")
276 | }
277 |
278 | if let value: [Data] = Johnny.pull("testDataArray") {
279 | XCTAssert(value == [data], "default int array was incorrect")
280 | } else {
281 | XCTFail("no default int array could be unpacked")
282 | }
283 |
284 | if let value: [String: String] = Johnny.pull("testStringMap") {
285 | XCTAssert(value == ["first": "Heresy", "second": "grows"], "default string map was incorrect")
286 | } else {
287 | XCTFail("no default string map could be unpacked")
288 | }
289 |
290 | if let value: [String: Int] = Johnny.pull("testIntMap") {
291 | XCTAssert(value == ["first": 1, "second": 2], "default int map was incorrect")
292 | } else {
293 | XCTFail("no default int map could be unpacked")
294 | }
295 |
296 | if let value: [String: Data] = Johnny.pull("testDataMap") {
297 | XCTAssert(value == ["first": data], "default data map was incorrect")
298 | } else {
299 | XCTFail("no default data map could be unpacked")
300 | }
301 |
302 | if let value: Set = Johnny.pull("testStringSet") {
303 | XCTAssert(value == ["Heresy", "grows", "from", "idleness"], "default string set was incorrect")
304 | } else {
305 | XCTFail("no default string set could be unpacked")
306 | }
307 |
308 | if let value: Set = Johnny.pull("testIntSet") {
309 | XCTAssert(value == [1,2], "default int set was incorrect")
310 | } else {
311 | XCTFail("no default int set could be unpacked")
312 | }
313 |
314 | if let value: Set = Johnny.pull("testDataSet") {
315 | XCTAssert(value == [data], "default int set was incorrect")
316 | } else {
317 | XCTFail("no default int set could be unpacked")
318 | }
319 | }
320 |
321 |
322 | func testOptionalCollections() {
323 | let ip = Bundle(for: type(of: self)).resourcePath! + "/johnny-logo.png"
324 | let image = Image(image: UIImage(contentsOfFile: ip)!)
325 | let data = image!.data
326 |
327 | let stringArray: [String]? = ["Heresy", "grows", "from", "idleness"]
328 | let intArray: [Int]? = [1,2]
329 | let dataArray: [Data]? = [data]
330 |
331 | let stringMap: [String: String]? = ["first": "Heresy", "second": "grows"]
332 | let intMap: [String: Int]? = ["first": 1, "second": 2]
333 | let dataMap: [String: Data]? = ["first": data]
334 |
335 | let stringSet: Set? = ["Heresy", "grows", "from", "idleness"]
336 | let intSet: Set? = [1,2]
337 | let dataSet: Set? = [data]
338 |
339 |
340 | Johnny.cache(stringArray, key: "testStringArrayOptional")
341 | Johnny.cache(intArray, key: "testIntArrayOptional")
342 | Johnny.cache(dataArray, key: "testDataArrayOptional")
343 | Johnny.cache(stringMap, key: "testStringMapOptional")
344 | Johnny.cache(intMap, key: "testIntMapOptional")
345 | Johnny.cache(dataMap, key: "testDataMapOptional")
346 | Johnny.cache(stringSet, key: "testStringSetOptional")
347 | Johnny.cache(intSet, key: "testIntSetOptional")
348 | Johnny.cache(dataSet, key: "testDataSetOptional")
349 |
350 |
351 | if let value: [String] = Johnny.pull("testStringArrayOptional") {
352 | XCTAssert(value == ["Heresy", "grows", "from", "idleness"], "default optional string array was incorrect")
353 | } else {
354 | XCTFail("no default optional string array could be unpacked")
355 | }
356 |
357 | if let value: [Int] = Johnny.pull("testIntArrayOptional") {
358 | XCTAssert(value == [1,2], "default optional int array was incorrect")
359 | } else {
360 | XCTFail("no default optional int array could be unpacked")
361 | }
362 |
363 | if let value: [Data] = Johnny.pull("testDataArrayOptional") {
364 | XCTAssert(value == [data], "default optional int array was incorrect")
365 | } else {
366 | XCTFail("no default optional int array could be unpacked")
367 | }
368 |
369 | if let value: [String: String] = Johnny.pull("testStringMapOptional") {
370 | XCTAssert(value == ["first": "Heresy", "second": "grows"], "default optional string map was incorrect")
371 | } else {
372 | XCTFail("no default optional string map could be unpacked")
373 | }
374 |
375 | if let value: [String: Int] = Johnny.pull("testIntMapOptional") {
376 | XCTAssert(value == ["first": 1, "second": 2], "default optional int map was incorrect")
377 | } else {
378 | XCTFail("no default optional int map could be unpacked")
379 | }
380 |
381 | if let value: [String: Data] = Johnny.pull("testDataMapOptional") {
382 | XCTAssert(value == ["first": data], "default optional data map was incorrect")
383 | } else {
384 | XCTFail("no default optional data map could be unpacked")
385 | }
386 |
387 | if let value: Set = Johnny.pull("testStringSetOptional") {
388 | XCTAssert(value == ["Heresy", "grows", "from", "idleness"], "default optional string set was incorrect")
389 | } else {
390 | XCTFail("no default optional string set could be unpacked")
391 | }
392 |
393 | if let value: Set = Johnny.pull("testIntSetOptional") {
394 | XCTAssert(value == [1,2], "default optional int set was incorrect")
395 | } else {
396 | XCTFail("no default optional int set could be unpacked")
397 | }
398 |
399 | if let value: Set = Johnny.pull("testDataSetOptional") {
400 | XCTAssert(value == [data], "default optional int set was incorrect")
401 | } else {
402 | XCTFail("no default optional int set could be unpacked")
403 | }
404 | }
405 |
406 |
407 | func testStorables() {
408 | let spacemarine: Ultramarine = Ultramarine()
409 | Johnny.cache(spacemarine, key: "spacemarine")
410 |
411 | if let spacemarine: Ultramarine = Johnny.pull("spacemarine") {
412 | XCTAssert(spacemarine.identification == 84823682 && spacemarine.badassery == Ultramarine.Badassery.Total, "storable object was incorrect")
413 | } else {
414 | XCTFail("no Storable object could be unpacked")
415 | }
416 |
417 | // let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
418 | // dispatch_after(delayTime, dispatch_get_main_queue()) {
419 | // Johnny.memory.removeAllObjects()
420 | //
421 | //
422 | // }
423 | }
424 |
425 |
426 | func testOptionalStorables() {
427 | let spacemarine: Ultramarine? = Ultramarine()
428 | Johnny.cache(spacemarine, key: "spacemarine")
429 |
430 | if let spacemarine: Ultramarine = Johnny.pull("spacemarine") {
431 | XCTAssert(spacemarine.identification == 84823682 && spacemarine.badassery == Ultramarine.Badassery.Total, "storable object was incorrect")
432 | } else {
433 | XCTFail("no Storable object could be unpacked")
434 | }
435 | }
436 | }
437 |
438 |
439 | class Ultramarine: Cachable {
440 |
441 | enum Badassery: String, Cachable {
442 | case Total
443 | }
444 |
445 | var identification: Int = 84823682
446 | var badassery = Badassery.Total
447 | }
448 |
--------------------------------------------------------------------------------
/JohnnyTests/JohnnyDiskTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // JohnnyDiskTests.swift
3 | // Johnny
4 | //
5 | // Created by Zolo on 7/27/16.
6 | // Copyright © 2016 Zoltán Matók. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | import XCTest
12 | @testable import Johnny
13 |
14 | class JohnnyDiskTests: XCTestCase {
15 |
16 | private lazy var __once: () = {
17 | let cachesPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0]
18 | let johhny = "io.johhny"
19 | let path = (cachesPath as NSString).appendingPathComponent(johhny)
20 | let paths = try? FileManager.default.contentsOfDirectory(atPath: path)
21 | if let paths = paths {
22 | for p in paths {
23 | let _ = try? FileManager.default.removeItem(atPath: p)
24 | }
25 | }
26 | }()
27 |
28 | var token: Int = 0
29 | var disk = Disk()
30 |
31 | override func setUp() {
32 | super.setUp()
33 | _ = self.__once
34 | }
35 |
36 | override func tearDown() { super.tearDown() }
37 |
38 |
39 | func testDefaultTypes() {
40 | let string: String = "Heresy grows from idleness"
41 | let int: Int = 1
42 | let int64: Int64 = 2
43 | let uint: UInt = 3
44 | let uint64: UInt64 = 4
45 | let float: Float = 10.2
46 | let double: Double = 20.6
47 |
48 | let ip = Bundle(for: type(of: self)).resourcePath! + "/johnny-logo.png"
49 | let image = Image(image: UIImage(contentsOfFile: ip)!)
50 | let data = image!.data
51 | let date: Date = Date(timeIntervalSince1970: 1459355217)
52 | let color = Color(color: UIColor.blue)
53 |
54 |
55 | Johnny.cache(string, key: "testString")
56 | Johnny.cache(int, key: "testInt")
57 | Johnny.cache(int64, key: "testInt64")
58 | Johnny.cache(uint, key: "testUInt")
59 | Johnny.cache(uint64, key: "testUInt64")
60 | Johnny.cache(float, key: "testFloat")
61 | Johnny.cache(double, key: "testDouble")
62 | Johnny.cache(image, key: "testImage")
63 | Johnny.cache(data, key: "testData")
64 | Johnny.cache(date, key: "testDate")
65 | Johnny.cache(color, key: "testColor")
66 |
67 |
68 | RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
69 |
70 |
71 | if let value: String = Johnny.pull("testString") {
72 | XCTAssert(value == "Heresy grows from idleness", "default string was incorrect")
73 | } else {
74 | XCTFail("no default string could be unpacked")
75 | }
76 |
77 | if let value: Int = Johnny.pull("testInt") {
78 | XCTAssert(value == 1, "default int was incorrect")
79 | } else {
80 | XCTFail("no default int could be unpacked")
81 | }
82 |
83 | if let value: Int64 = Johnny.pull("testInt64") {
84 | XCTAssert(value == 2, "default int64 was incorrect")
85 | } else {
86 | XCTFail("no default int64 could be unpacked")
87 | }
88 |
89 | if let value: UInt = Johnny.pull("testUInt") {
90 | XCTAssert(value == 3, "default uint was incorrect")
91 | } else {
92 | XCTFail("no default uint could be unpacked")
93 | }
94 |
95 | if let value: UInt64 = Johnny.pull("testUInt64") {
96 | XCTAssert(value == 4, "default uint64 was incorrect")
97 | } else {
98 | XCTFail("no default uint64 could be unpacked")
99 | }
100 |
101 | if let value: Float = Johnny.pull("testFloat") {
102 | XCTAssert(value == 10.2, "default float was incorrect")
103 | } else {
104 | XCTFail("no default float could be unpacked")
105 | }
106 |
107 | if let value: Double = Johnny.pull("testDouble") {
108 | XCTAssert(value == 20.6, "default Double was incorrect")
109 | } else {
110 | XCTFail("no default Double could be unpacked")
111 | }
112 |
113 | if let value: Image = Johnny.pull("testImage") {
114 | XCTAssert(value.data == data, "default Image was incorrect")
115 | } else {
116 | XCTFail("no default Image could be unpacked")
117 | }
118 |
119 | if let value: Data = Johnny.pull("testData") {
120 | XCTAssert(value == data, "default Data was incorrect")
121 | } else {
122 | XCTFail("no default Data could be unpacked")
123 | }
124 |
125 | if let value: Date = Johnny.pull("testDate") {
126 | XCTAssert(value.timeIntervalSince1970 == 1459355217 , "default Date was incorrect")
127 | } else {
128 | XCTFail("no default Date could be unpacked")
129 | }
130 |
131 | if let value: Color = Johnny.pull("testColor") {
132 | XCTAssert(value.uiColor() == UIColor.blue, "default Color was incorrect")
133 | } else {
134 | XCTFail("no default Color could be unpacked")
135 | }
136 | }
137 |
138 |
139 | func testOptionalDefaultTypes() {
140 | let string: String? = "Heresy grows from idleness"
141 | let int: Int? = 1
142 | let int64: Int64? = 2
143 | let uint: UInt? = 3
144 | let uint64: UInt64? = 4
145 | let float: Float? = 10.2
146 | let double: Double? = 20.6
147 |
148 | let ip = Bundle(for: type(of: self)).resourcePath! + "/johnny-logo.png"
149 | let image = Image(image: UIImage(contentsOfFile: ip))
150 | let data: Data? = image?.data
151 | let date: Date? = Date(timeIntervalSince1970: 1459355217)
152 | let color: Color? = Color(color: UIColor.blue)
153 |
154 |
155 | Johnny.cache(string, key: "testStringOptional")
156 | Johnny.cache(int, key: "testIntOptional")
157 | Johnny.cache(int64, key: "testInt64Optional")
158 | Johnny.cache(uint, key: "testUIntOptional")
159 | Johnny.cache(uint64, key: "testUInt64Optional")
160 | Johnny.cache(float, key: "testFloatOptional")
161 | Johnny.cache(double, key: "testDoubleOptional")
162 | Johnny.cache(image, key: "testImageOptional")
163 | Johnny.cache(data, key: "testDataOptional")
164 | Johnny.cache(date, key: "testDateOptional")
165 | Johnny.cache(color, key: "testColorOptional")
166 |
167 |
168 | RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
169 |
170 |
171 | if let value: String = Johnny.pull("testStringOptional") {
172 | XCTAssert(value == "Heresy grows from idleness", "default optional string was incorrect")
173 | } else {
174 | XCTFail("no default optional string could be unpacked")
175 | }
176 |
177 | if let value: Int = Johnny.pull("testIntOptional") {
178 | XCTAssert(value == 1, "default optional int was incorrect")
179 | } else {
180 | XCTFail("no default optional int could be unpacked")
181 | }
182 |
183 | if let value: Int64 = Johnny.pull("testInt64Optional") {
184 | XCTAssert(value == 2, "default optional int64 was incorrect")
185 | } else {
186 | XCTFail("no default optional int64 could be unpacked")
187 | }
188 |
189 | if let value: UInt = Johnny.pull("testUIntOptional") {
190 | XCTAssert(value == 3, "default optional uint was incorrect")
191 | } else {
192 | XCTFail("no default optional uint could be unpacked")
193 | }
194 |
195 | if let value: UInt64 = Johnny.pull("testUInt64Optional") {
196 | XCTAssert(value == 4, "default optional uint64 was incorrect")
197 | } else {
198 | XCTFail("no default optional uint64 could be unpacked")
199 | }
200 |
201 | if let value: Float = Johnny.pull("testFloatOptional") {
202 | XCTAssert(value == 10.2, "default optional float was incorrect")
203 | } else {
204 | XCTFail("no default optional float could be unpacked")
205 | }
206 |
207 | if let value: Double = Johnny.pull("testDoubleOptional") {
208 | XCTAssert(value == 20.6, "default optional Double was incorrect")
209 | } else {
210 | XCTFail("no default optional Double could be unpacked")
211 | }
212 |
213 | if let value: Image = Johnny.pull("testImageOptional") {
214 | XCTAssert(value.data == data, "default optional Image was incorrect")
215 | } else {
216 | XCTFail("no default optional Image could be unpacked")
217 | }
218 |
219 | if let value: Data = Johnny.pull("testDataOptional") {
220 | XCTAssert(value == data, "default optional Data was incorrect")
221 | } else {
222 | XCTFail("no default optional Data could be unpacked")
223 | }
224 |
225 | if let value: Date = Johnny.pull("testDateOptional") {
226 | XCTAssert(value.timeIntervalSince1970 == 1459355217 , "default optional Date was incorrect")
227 | } else {
228 | XCTFail("no default optional Date could be unpacked")
229 | }
230 |
231 | if let value: Color = Johnny.pull("testColorOptional") {
232 | XCTAssert(value.uiColor() == UIColor.blue, "default optional Color was incorrect")
233 | } else {
234 | XCTFail("no default optional Color could be unpacked")
235 | }
236 | }
237 |
238 |
239 | func testCollections() {
240 |
241 | let ip = Bundle(for: type(of: self)).resourcePath! + "/johnny-logo.png"
242 | let image = Image(image: UIImage(contentsOfFile: ip)!)
243 | let data = image!.data
244 |
245 | let stringArray: [String] = ["Heresy", "grows", "from", "idleness"]
246 | let intArray: [Int] = [1,2]
247 | let dataArray: [Data] = [data]
248 |
249 | let stringMap: [String: String] = ["first": "Heresy", "second": "grows"]
250 | let intMap: [String: Int] = ["first": 1, "second": 2]
251 | let dataMap: [String: Data] = ["first": data]
252 |
253 | let stringSet: Set = ["Heresy", "grows", "from", "idleness"]
254 | let intSet: Set = [1,2]
255 | let dataSet: Set = [data]
256 |
257 |
258 | Johnny.cache(stringArray, key: "testStringArray")
259 | Johnny.cache(intArray, key: "testIntArray")
260 | Johnny.cache(dataArray, key: "testDataArray")
261 | Johnny.cache(stringMap, key: "testStringMap")
262 | Johnny.cache(intMap, key: "testIntMap")
263 | Johnny.cache(dataMap, key: "testDataMap")
264 | Johnny.cache(stringSet, key: "testStringSet")
265 | Johnny.cache(intSet, key: "testIntSet")
266 | Johnny.cache(dataSet, key: "testDataSet")
267 |
268 |
269 | RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
270 |
271 |
272 | if let value: [String] = Johnny.pull("testStringArray") {
273 | XCTAssert(value == ["Heresy", "grows", "from", "idleness"], "default string array was incorrect")
274 | } else {
275 | XCTFail("no default string array could be unpacked")
276 | }
277 |
278 | if let value: [Int] = Johnny.pull("testIntArray") {
279 | XCTAssert(value == [1,2], "default int array was incorrect")
280 | } else {
281 | XCTFail("no default int array could be unpacked")
282 | }
283 |
284 | if let value: [Data] = Johnny.pull("testDataArray") {
285 | XCTAssert(value == [data], "default int array was incorrect")
286 | } else {
287 | XCTFail("no default int array could be unpacked")
288 | }
289 |
290 | if let value: [String: String] = Johnny.pull("testStringMap") {
291 | XCTAssert(value == ["first": "Heresy", "second": "grows"], "default string map was incorrect")
292 | } else {
293 | XCTFail("no default string map could be unpacked")
294 | }
295 |
296 | if let value: [String: Int] = Johnny.pull("testIntMap") {
297 | XCTAssert(value == ["first": 1, "second": 2], "default int map was incorrect")
298 | } else {
299 | XCTFail("no default int map could be unpacked")
300 | }
301 |
302 | if let value: [String: Data] = Johnny.pull("testDataMap") {
303 | XCTAssert(value == ["first": data], "default data map was incorrect")
304 | } else {
305 | XCTFail("no default data map could be unpacked")
306 | }
307 |
308 | if let value: Set = Johnny.pull("testStringSet") {
309 | XCTAssert(value == ["Heresy", "grows", "from", "idleness"], "default string set was incorrect")
310 | } else {
311 | XCTFail("no default string set could be unpacked")
312 | }
313 |
314 | if let value: Set = Johnny.pull("testIntSet") {
315 | XCTAssert(value == [1,2], "default int set was incorrect")
316 | } else {
317 | XCTFail("no default int set could be unpacked")
318 | }
319 |
320 | if let value: Set = Johnny.pull("testDataSet") {
321 | XCTAssert(value == [data], "default int set was incorrect")
322 | } else {
323 | XCTFail("no default int set could be unpacked")
324 | }
325 | }
326 |
327 |
328 | func testOptionalCollections() {
329 | let ip = Bundle(for: type(of: self)).resourcePath! + "/johnny-logo.png"
330 | let image = Image(image: UIImage(contentsOfFile: ip)!)
331 | let data = image!.data
332 |
333 | let stringArray: [String]? = ["Heresy", "grows", "from", "idleness"]
334 | let intArray: [Int]? = [1,2]
335 | let dataArray: [Data]? = [data]
336 |
337 | let stringMap: [String: String]? = ["first": "Heresy", "second": "grows"]
338 | let intMap: [String: Int]? = ["first": 1, "second": 2]
339 | let dataMap: [String: Data]? = ["first": data]
340 |
341 | let stringSet: Set? = ["Heresy", "grows", "from", "idleness"]
342 | let intSet: Set? = [1,2]
343 | let dataSet: Set? = [data]
344 |
345 |
346 | Johnny.cache(stringArray, key: "testStringArrayOptional")
347 | Johnny.cache(intArray, key: "testIntArrayOptional")
348 | Johnny.cache(dataArray, key: "testDataArrayOptional")
349 | Johnny.cache(stringMap, key: "testStringMapOptional")
350 | Johnny.cache(intMap, key: "testIntMapOptional")
351 | Johnny.cache(dataMap, key: "testDataMapOptional")
352 | Johnny.cache(stringSet, key: "testStringSetOptional")
353 | Johnny.cache(intSet, key: "testIntSetOptional")
354 | Johnny.cache(dataSet, key: "testDataSetOptional")
355 |
356 |
357 | RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
358 |
359 |
360 | if let value: [String] = Johnny.pull("testStringArrayOptional") {
361 | XCTAssert(value == ["Heresy", "grows", "from", "idleness"], "default optional string array was incorrect")
362 | } else {
363 | XCTFail("no default optional string array could be unpacked")
364 | }
365 |
366 | if let value: [Int] = Johnny.pull("testIntArrayOptional") {
367 | XCTAssert(value == [1,2], "default optional int array was incorrect")
368 | } else {
369 | XCTFail("no default optional int array could be unpacked")
370 | }
371 |
372 | if let value: [Data] = Johnny.pull("testDataArrayOptional") {
373 | XCTAssert(value == [data], "default optional int array was incorrect")
374 | } else {
375 | XCTFail("no default optional int array could be unpacked")
376 | }
377 |
378 | if let value: [String: String] = Johnny.pull("testStringMapOptional") {
379 | XCTAssert(value == ["first": "Heresy", "second": "grows"], "default optional string map was incorrect")
380 | } else {
381 | XCTFail("no default optional string map could be unpacked")
382 | }
383 |
384 | if let value: [String: Int] = Johnny.pull("testIntMapOptional") {
385 | XCTAssert(value == ["first": 1, "second": 2], "default optional int map was incorrect")
386 | } else {
387 | XCTFail("no default optional int map could be unpacked")
388 | }
389 |
390 | if let value: [String: Data] = Johnny.pull("testDataMapOptional") {
391 | XCTAssert(value == ["first": data], "default optional data map was incorrect")
392 | } else {
393 | XCTFail("no default optional data map could be unpacked")
394 | }
395 |
396 | if let value: Set = Johnny.pull("testStringSetOptional") {
397 | XCTAssert(value == ["Heresy", "grows", "from", "idleness"], "default optional string set was incorrect")
398 | } else {
399 | XCTFail("no default optional string set could be unpacked")
400 | }
401 |
402 | if let value: Set = Johnny.pull("testIntSetOptional") {
403 | XCTAssert(value == [1,2], "default optional int set was incorrect")
404 | } else {
405 | XCTFail("no default optional int set could be unpacked")
406 | }
407 |
408 | if let value: Set = Johnny.pull("testDataSetOptional") {
409 | XCTAssert(value == [data], "default optional int set was incorrect")
410 | } else {
411 | XCTFail("no default optional int set could be unpacked")
412 | }
413 | }
414 |
415 |
416 | func testStorables() {
417 | let spacemarine: Ultramarine = Ultramarine()
418 | Johnny.cache(spacemarine, key: "spacemarine")
419 |
420 |
421 | RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
422 |
423 |
424 | if let spacemarine: Ultramarine = Johnny.pull("spacemarine") {
425 | XCTAssert(spacemarine.identification == 84823682 && spacemarine.badassery == Ultramarine.Badassery.Total, "storable object was incorrect")
426 | } else {
427 | XCTFail("no Storable object could be unpacked")
428 | }
429 | }
430 |
431 |
432 | func testOptionalStorables() {
433 | let spacemarine: Ultramarine? = Ultramarine()
434 | Johnny.cache(spacemarine, key: "spacemarine")
435 |
436 |
437 | RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
438 |
439 |
440 | if let spacemarine: Ultramarine = Johnny.pull("spacemarine") {
441 | XCTAssert(spacemarine.identification == 84823682 && spacemarine.badassery == Ultramarine.Badassery.Total, "storable object was incorrect")
442 | } else {
443 | XCTFail("no Storable object could be unpacked")
444 | }
445 | }
446 |
447 | func testDeletion() {
448 | let key = "testString"
449 | Johnny.cache("Heresy grows from idleness", key: key)
450 | DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
451 | Johnny.delete(key)
452 | if let _: String = Johnny.pull(key) {
453 | XCTFail("no Storable object could be unpacked")
454 | } else {
455 | XCTAssert(true)
456 | }
457 | }
458 | }
459 |
460 | func testLibrary() {
461 | let x = expectation(description: "Object was stored in the Library")
462 | let key = "testString"
463 | disk[key, true] = "And we shall no know fear".data(using: .utf8)
464 |
465 | DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
466 | self.disk.nuke()
467 | DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
468 | XCTAssert(self.disk[key, true] != nil, "Object was not stored in the library")
469 | x.fulfill()
470 | }
471 | }
472 |
473 | waitForExpectations(timeout: 3) { (e) in }
474 | }
475 |
476 | func testNuke() {
477 | let key = "testString"
478 | disk[key, true] = "And we shall no know fear".data(using: .utf8)
479 | disk.nuke(libraryToo: true)
480 | XCTAssert(disk[key] == nil, "Nuke didn't clear the library")
481 | }
482 | }
483 |
--------------------------------------------------------------------------------
/Johnny.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | F3036D361D2584A80056BCE4 /* UIButton+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB051D25634F005B30AB /* UIButton+Johnny.swift */; };
11 | F3036D371D2584B00056BCE4 /* UIImage+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB061D25634F005B30AB /* UIImage+Johnny.swift */; };
12 | F3036D381D2584C30056BCE4 /* UIImage+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB061D25634F005B30AB /* UIImage+Johnny.swift */; };
13 | F30F64911D46A27500EDD75F /* WatchKit+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359013F1D2A9C9A00868171 /* WatchKit+Johnny.swift */; };
14 | F30F64921D46A39A00EDD75F /* UIButton+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB051D25634F005B30AB /* UIButton+Johnny.swift */; };
15 | F319959D1D48D60200429F83 /* JohnnyDiskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F319959C1D48D60200429F83 /* JohnnyDiskTests.swift */; };
16 | F3382FB91D2594D3009C2110 /* UIColor+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3382FB81D2594D3009C2110 /* UIColor+Johnny.swift */; };
17 | F3382FBA1D2594D8009C2110 /* UIColor+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3382FB81D2594D3009C2110 /* UIColor+Johnny.swift */; };
18 | F3382FBB1D2594D9009C2110 /* UIColor+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3382FB81D2594D3009C2110 /* UIColor+Johnny.swift */; };
19 | F35901381D2A7DEC00868171 /* Foundation+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F35901371D2A7DEC00868171 /* Foundation+Johnny.swift */; };
20 | F35901391D2A7DF100868171 /* Foundation+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F35901371D2A7DEC00868171 /* Foundation+Johnny.swift */; };
21 | F359013A1D2A7DF200868171 /* Foundation+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F35901371D2A7DEC00868171 /* Foundation+Johnny.swift */; };
22 | F359013B1D2A7DF200868171 /* Foundation+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F35901371D2A7DEC00868171 /* Foundation+Johnny.swift */; };
23 | F359013E1D2A822400868171 /* AppKit+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359013C1D2A820900868171 /* AppKit+Johnny.swift */; };
24 | F37A20541D48A042007603F5 /* JohnnyMemoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F37A20531D48A042007603F5 /* JohnnyMemoryTests.swift */; };
25 | F37A20561D48A042007603F5 /* Johnny.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3E4CAF31D256069005B30AB /* Johnny.framework */; };
26 | F37A205F1D48AC39007603F5 /* johnny-logo.png in Resources */ = {isa = PBXBuildFile; fileRef = F35901881D2AA55400868171 /* johnny-logo.png */; };
27 | F37A20601D48AC3A007603F5 /* johnny-logo.png in Resources */ = {isa = PBXBuildFile; fileRef = F35901881D2AA55400868171 /* johnny-logo.png */; };
28 | F3E4CAF71D256069005B30AB /* Johnny.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E4CAF61D256069005B30AB /* Johnny.h */; settings = {ATTRIBUTES = (Public, ); }; };
29 | F3E4CB0B1D25634F005B30AB /* Disk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB001D25634F005B30AB /* Disk.swift */; };
30 | F3E4CB101D25634F005B30AB /* UIImage+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB061D25634F005B30AB /* UIImage+Johnny.swift */; };
31 | F3E4CB111D25634F005B30AB /* UIImageView+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB071D25634F005B30AB /* UIImageView+Johnny.swift */; };
32 | F3E4CB121D25634F005B30AB /* Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB081D25634F005B30AB /* Johnny.swift */; };
33 | F3E4CB131D25634F005B30AB /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB091D25634F005B30AB /* Log.swift */; };
34 | F3E4CB141D25634F005B30AB /* Memory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB0A1D25634F005B30AB /* Memory.swift */; };
35 | F3E4CB341D2572FC005B30AB /* Johnny macOS.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E4CB331D2572FC005B30AB /* Johnny macOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
36 | F3E4CB411D2573CD005B30AB /* Johnny tvOS.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E4CB401D2573CD005B30AB /* Johnny tvOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
37 | F3E4CB4E1D2573FF005B30AB /* Johnny watchOS.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E4CB4D1D2573FF005B30AB /* Johnny watchOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
38 | F3E4CB531D25754C005B30AB /* Johnny.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E4CAF61D256069005B30AB /* Johnny.h */; };
39 | F3E4CB541D25754C005B30AB /* Johnny.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E4CAF61D256069005B30AB /* Johnny.h */; };
40 | F3E4CB551D25754D005B30AB /* Johnny.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E4CAF61D256069005B30AB /* Johnny.h */; };
41 | F3E4CB561D257552005B30AB /* Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB081D25634F005B30AB /* Johnny.swift */; };
42 | F3E4CB571D257552005B30AB /* Memory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB0A1D25634F005B30AB /* Memory.swift */; };
43 | F3E4CB581D257552005B30AB /* Disk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB001D25634F005B30AB /* Disk.swift */; };
44 | F3E4CB591D257553005B30AB /* Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB081D25634F005B30AB /* Johnny.swift */; };
45 | F3E4CB5A1D257553005B30AB /* Memory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB0A1D25634F005B30AB /* Memory.swift */; };
46 | F3E4CB5B1D257553005B30AB /* Disk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB001D25634F005B30AB /* Disk.swift */; };
47 | F3E4CB5C1D257554005B30AB /* Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB081D25634F005B30AB /* Johnny.swift */; };
48 | F3E4CB5D1D257554005B30AB /* Memory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB0A1D25634F005B30AB /* Memory.swift */; };
49 | F3E4CB5E1D257554005B30AB /* Disk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB001D25634F005B30AB /* Disk.swift */; };
50 | F3E4CB6A1D25755E005B30AB /* UIImageView+Johnny.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB071D25634F005B30AB /* UIImageView+Johnny.swift */; };
51 | F3E4CB711D25756A005B30AB /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB091D25634F005B30AB /* Log.swift */; };
52 | F3E4CB721D25756B005B30AB /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB091D25634F005B30AB /* Log.swift */; };
53 | F3E4CB731D25756B005B30AB /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E4CB091D25634F005B30AB /* Log.swift */; };
54 | /* End PBXBuildFile section */
55 |
56 | /* Begin PBXContainerItemProxy section */
57 | F37A20571D48A042007603F5 /* PBXContainerItemProxy */ = {
58 | isa = PBXContainerItemProxy;
59 | containerPortal = F3E4CAEA1D256069005B30AB /* Project object */;
60 | proxyType = 1;
61 | remoteGlobalIDString = F3E4CAF21D256069005B30AB;
62 | remoteInfo = "Johnny iOS";
63 | };
64 | /* End PBXContainerItemProxy section */
65 |
66 | /* Begin PBXFileReference section */
67 | F3036D321D257FC50056BCE4 /* macOS.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = macOS.modulemap; sourceTree = ""; };
68 | F319959C1D48D60200429F83 /* JohnnyDiskTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JohnnyDiskTests.swift; sourceTree = ""; };
69 | F31E2FE21D49F10B009EE3F1 /* johhny-logo.sketch */ = {isa = PBXFileReference; lastKnownFileType = file; path = "johhny-logo.sketch"; sourceTree = SOURCE_ROOT; };
70 | F31E2FE41D4A1016009EE3F1 /* tags.sketch */ = {isa = PBXFileReference; lastKnownFileType = file; path = tags.sketch; sourceTree = SOURCE_ROOT; };
71 | F31E2FE51D4A1061009EE3F1 /* language.svg */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = language.svg; sourceTree = SOURCE_ROOT; };
72 | F31E2FE61D4A1061009EE3F1 /* license.svg */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = license.svg; sourceTree = SOURCE_ROOT; };
73 | F31E2FE71D4A1061009EE3F1 /* platform.svg */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = platform.svg; sourceTree = SOURCE_ROOT; };
74 | F31E2FE81D4A1061009EE3F1 /* pod.svg */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = pod.svg; sourceTree = SOURCE_ROOT; };
75 | F33542F91D258A3D00E3026F /* tvOS.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = tvOS.modulemap; sourceTree = ""; };
76 | F3382FB71D259384009C2110 /* watchOS.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = watchOS.modulemap; sourceTree = ""; };
77 | F3382FB81D2594D3009C2110 /* UIColor+Johnny.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Johnny.swift"; sourceTree = ""; };
78 | F35901371D2A7DEC00868171 /* Foundation+Johnny.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Foundation+Johnny.swift"; sourceTree = ""; };
79 | F359013C1D2A820900868171 /* AppKit+Johnny.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AppKit+Johnny.swift"; sourceTree = ""; };
80 | F359013F1D2A9C9A00868171 /* WatchKit+Johnny.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "WatchKit+Johnny.swift"; sourceTree = ""; };
81 | F35901881D2AA55400868171 /* johnny-logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "johnny-logo.png"; sourceTree = ""; };
82 | F359018B1D2AC51500868171 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; };
83 | F359018D1D2AC65800868171 /* Johnny.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = Johnny.podspec; sourceTree = SOURCE_ROOT; };
84 | F37A20511D48A042007603F5 /* JohnnyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JohnnyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
85 | F37A20531D48A042007603F5 /* JohnnyMemoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JohnnyMemoryTests.swift; sourceTree = ""; };
86 | F37A20551D48A042007603F5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
87 | F3E4CAF31D256069005B30AB /* Johnny.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Johnny.framework; sourceTree = BUILT_PRODUCTS_DIR; };
88 | F3E4CAF61D256069005B30AB /* Johnny.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Johnny.h; sourceTree = ""; };
89 | F3E4CAF81D256069005B30AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
90 | F3E4CB001D25634F005B30AB /* Disk.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Disk.swift; sourceTree = ""; };
91 | F3E4CB051D25634F005B30AB /* UIButton+Johnny.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIButton+Johnny.swift"; sourceTree = ""; };
92 | F3E4CB061D25634F005B30AB /* UIImage+Johnny.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Johnny.swift"; sourceTree = ""; };
93 | F3E4CB071D25634F005B30AB /* UIImageView+Johnny.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+Johnny.swift"; sourceTree = ""; };
94 | F3E4CB081D25634F005B30AB /* Johnny.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Johnny.swift; sourceTree = ""; };
95 | F3E4CB091D25634F005B30AB /* Log.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = ""; };
96 | F3E4CB0A1D25634F005B30AB /* Memory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Memory.swift; sourceTree = ""; };
97 | F3E4CB311D2572FC005B30AB /* Johnny.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Johnny.framework; sourceTree = BUILT_PRODUCTS_DIR; };
98 | F3E4CB331D2572FC005B30AB /* Johnny macOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Johnny macOS.h"; sourceTree = ""; };
99 | F3E4CB351D2572FC005B30AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
100 | F3E4CB3E1D2573CD005B30AB /* Johnny.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Johnny.framework; sourceTree = BUILT_PRODUCTS_DIR; };
101 | F3E4CB401D2573CD005B30AB /* Johnny tvOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Johnny tvOS.h"; sourceTree = ""; };
102 | F3E4CB421D2573CD005B30AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
103 | F3E4CB4B1D2573FF005B30AB /* Johnny.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Johnny.framework; sourceTree = BUILT_PRODUCTS_DIR; };
104 | F3E4CB4D1D2573FF005B30AB /* Johnny watchOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Johnny watchOS.h"; sourceTree = ""; };
105 | F3E4CB4F1D2573FF005B30AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
106 | /* End PBXFileReference section */
107 |
108 | /* Begin PBXFrameworksBuildPhase section */
109 | F37A204E1D48A042007603F5 /* Frameworks */ = {
110 | isa = PBXFrameworksBuildPhase;
111 | buildActionMask = 2147483647;
112 | files = (
113 | F37A20561D48A042007603F5 /* Johnny.framework in Frameworks */,
114 | );
115 | runOnlyForDeploymentPostprocessing = 0;
116 | };
117 | F3E4CAEF1D256069005B30AB /* Frameworks */ = {
118 | isa = PBXFrameworksBuildPhase;
119 | buildActionMask = 2147483647;
120 | files = (
121 | );
122 | runOnlyForDeploymentPostprocessing = 0;
123 | };
124 | F3E4CB2D1D2572FC005B30AB /* Frameworks */ = {
125 | isa = PBXFrameworksBuildPhase;
126 | buildActionMask = 2147483647;
127 | files = (
128 | );
129 | runOnlyForDeploymentPostprocessing = 0;
130 | };
131 | F3E4CB3A1D2573CD005B30AB /* Frameworks */ = {
132 | isa = PBXFrameworksBuildPhase;
133 | buildActionMask = 2147483647;
134 | files = (
135 | );
136 | runOnlyForDeploymentPostprocessing = 0;
137 | };
138 | F3E4CB471D2573FF005B30AB /* Frameworks */ = {
139 | isa = PBXFrameworksBuildPhase;
140 | buildActionMask = 2147483647;
141 | files = (
142 | );
143 | runOnlyForDeploymentPostprocessing = 0;
144 | };
145 | /* End PBXFrameworksBuildPhase section */
146 |
147 | /* Begin PBXGroup section */
148 | F359018C1D2AC51E00868171 /* Configuration */ = {
149 | isa = PBXGroup;
150 | children = (
151 | F3E4CAF81D256069005B30AB /* Info.plist */,
152 | F359018B1D2AC51500868171 /* README.md */,
153 | F359018D1D2AC65800868171 /* Johnny.podspec */,
154 | F35901881D2AA55400868171 /* johnny-logo.png */,
155 | F31E2FE21D49F10B009EE3F1 /* johhny-logo.sketch */,
156 | F31E2FE41D4A1016009EE3F1 /* tags.sketch */,
157 | F31E2FE51D4A1061009EE3F1 /* language.svg */,
158 | F31E2FE61D4A1061009EE3F1 /* license.svg */,
159 | F31E2FE71D4A1061009EE3F1 /* platform.svg */,
160 | F31E2FE81D4A1061009EE3F1 /* pod.svg */,
161 | );
162 | name = Configuration;
163 | sourceTree = "";
164 | };
165 | F37A20521D48A042007603F5 /* JohnnyTests */ = {
166 | isa = PBXGroup;
167 | children = (
168 | F37A20531D48A042007603F5 /* JohnnyMemoryTests.swift */,
169 | F319959C1D48D60200429F83 /* JohnnyDiskTests.swift */,
170 | F37A20551D48A042007603F5 /* Info.plist */,
171 | );
172 | path = JohnnyTests;
173 | sourceTree = "";
174 | };
175 | F3D0533D1D47E26A00D9AA84 /* common */ = {
176 | isa = PBXGroup;
177 | children = (
178 | F35901371D2A7DEC00868171 /* Foundation+Johnny.swift */,
179 | );
180 | path = common;
181 | sourceTree = "";
182 | };
183 | F3D0533F1D47E26A00D9AA84 /* macOS */ = {
184 | isa = PBXGroup;
185 | children = (
186 | F359013C1D2A820900868171 /* AppKit+Johnny.swift */,
187 | );
188 | path = macOS;
189 | sourceTree = "";
190 | };
191 | F3D053411D47E26A00D9AA84 /* watchOS */ = {
192 | isa = PBXGroup;
193 | children = (
194 | F359013F1D2A9C9A00868171 /* WatchKit+Johnny.swift */,
195 | );
196 | path = watchOS;
197 | sourceTree = "";
198 | };
199 | F3E4CAE91D256069005B30AB = {
200 | isa = PBXGroup;
201 | children = (
202 | F3E4CAF51D256069005B30AB /* Johnny */,
203 | F3E4CB321D2572FC005B30AB /* Johnny macOS */,
204 | F3E4CB3F1D2573CD005B30AB /* Johnny tvOS */,
205 | F3E4CB4C1D2573FF005B30AB /* Johnny watchOS */,
206 | F37A20521D48A042007603F5 /* JohnnyTests */,
207 | F3E4CAF41D256069005B30AB /* Products */,
208 | );
209 | sourceTree = "";
210 | };
211 | F3E4CAF41D256069005B30AB /* Products */ = {
212 | isa = PBXGroup;
213 | children = (
214 | F3E4CAF31D256069005B30AB /* Johnny.framework */,
215 | F3E4CB311D2572FC005B30AB /* Johnny.framework */,
216 | F3E4CB3E1D2573CD005B30AB /* Johnny.framework */,
217 | F3E4CB4B1D2573FF005B30AB /* Johnny.framework */,
218 | F37A20511D48A042007603F5 /* JohnnyTests.xctest */,
219 | );
220 | name = Products;
221 | sourceTree = "";
222 | };
223 | F3E4CAF51D256069005B30AB /* Johnny */ = {
224 | isa = PBXGroup;
225 | children = (
226 | F3E4CAF61D256069005B30AB /* Johnny.h */,
227 | F3E4CB081D25634F005B30AB /* Johnny.swift */,
228 | F3E4CB0A1D25634F005B30AB /* Memory.swift */,
229 | F3E4CB001D25634F005B30AB /* Disk.swift */,
230 | F3E4CB011D25634F005B30AB /* Extensions */,
231 | F3E4CB091D25634F005B30AB /* Log.swift */,
232 | F359018C1D2AC51E00868171 /* Configuration */,
233 | );
234 | path = Johnny;
235 | sourceTree = "";
236 | };
237 | F3E4CB011D25634F005B30AB /* Extensions */ = {
238 | isa = PBXGroup;
239 | children = (
240 | F3D0533D1D47E26A00D9AA84 /* common */,
241 | F3D0533F1D47E26A00D9AA84 /* macOS */,
242 | F3D053411D47E26A00D9AA84 /* watchOS */,
243 | F3E4CB051D25634F005B30AB /* UIButton+Johnny.swift */,
244 | F3382FB81D2594D3009C2110 /* UIColor+Johnny.swift */,
245 | F3E4CB061D25634F005B30AB /* UIImage+Johnny.swift */,
246 | F3E4CB071D25634F005B30AB /* UIImageView+Johnny.swift */,
247 | );
248 | path = Extensions;
249 | sourceTree = "";
250 | };
251 | F3E4CB321D2572FC005B30AB /* Johnny macOS */ = {
252 | isa = PBXGroup;
253 | children = (
254 | F3E4CB331D2572FC005B30AB /* Johnny macOS.h */,
255 | F3E4CB351D2572FC005B30AB /* Info.plist */,
256 | F3036D321D257FC50056BCE4 /* macOS.modulemap */,
257 | );
258 | path = "Johnny macOS";
259 | sourceTree = "";
260 | };
261 | F3E4CB3F1D2573CD005B30AB /* Johnny tvOS */ = {
262 | isa = PBXGroup;
263 | children = (
264 | F3E4CB401D2573CD005B30AB /* Johnny tvOS.h */,
265 | F3E4CB421D2573CD005B30AB /* Info.plist */,
266 | F33542F91D258A3D00E3026F /* tvOS.modulemap */,
267 | );
268 | path = "Johnny tvOS";
269 | sourceTree = "";
270 | };
271 | F3E4CB4C1D2573FF005B30AB /* Johnny watchOS */ = {
272 | isa = PBXGroup;
273 | children = (
274 | F3E4CB4D1D2573FF005B30AB /* Johnny watchOS.h */,
275 | F3E4CB4F1D2573FF005B30AB /* Info.plist */,
276 | F3382FB71D259384009C2110 /* watchOS.modulemap */,
277 | );
278 | path = "Johnny watchOS";
279 | sourceTree = "";
280 | };
281 | /* End PBXGroup section */
282 |
283 | /* Begin PBXHeadersBuildPhase section */
284 | F3E4CAF01D256069005B30AB /* Headers */ = {
285 | isa = PBXHeadersBuildPhase;
286 | buildActionMask = 2147483647;
287 | files = (
288 | F3E4CAF71D256069005B30AB /* Johnny.h in Headers */,
289 | );
290 | runOnlyForDeploymentPostprocessing = 0;
291 | };
292 | F3E4CB2E1D2572FC005B30AB /* Headers */ = {
293 | isa = PBXHeadersBuildPhase;
294 | buildActionMask = 2147483647;
295 | files = (
296 | F3E4CB341D2572FC005B30AB /* Johnny macOS.h in Headers */,
297 | F3E4CB531D25754C005B30AB /* Johnny.h in Headers */,
298 | );
299 | runOnlyForDeploymentPostprocessing = 0;
300 | };
301 | F3E4CB3B1D2573CD005B30AB /* Headers */ = {
302 | isa = PBXHeadersBuildPhase;
303 | buildActionMask = 2147483647;
304 | files = (
305 | F3E4CB541D25754C005B30AB /* Johnny.h in Headers */,
306 | F3E4CB411D2573CD005B30AB /* Johnny tvOS.h in Headers */,
307 | );
308 | runOnlyForDeploymentPostprocessing = 0;
309 | };
310 | F3E4CB481D2573FF005B30AB /* Headers */ = {
311 | isa = PBXHeadersBuildPhase;
312 | buildActionMask = 2147483647;
313 | files = (
314 | F3E4CB551D25754D005B30AB /* Johnny.h in Headers */,
315 | F3E4CB4E1D2573FF005B30AB /* Johnny watchOS.h in Headers */,
316 | );
317 | runOnlyForDeploymentPostprocessing = 0;
318 | };
319 | /* End PBXHeadersBuildPhase section */
320 |
321 | /* Begin PBXNativeTarget section */
322 | F37A20501D48A042007603F5 /* JohnnyTests */ = {
323 | isa = PBXNativeTarget;
324 | buildConfigurationList = F37A205B1D48A042007603F5 /* Build configuration list for PBXNativeTarget "JohnnyTests" */;
325 | buildPhases = (
326 | F37A204D1D48A042007603F5 /* Sources */,
327 | F37A204E1D48A042007603F5 /* Frameworks */,
328 | F37A204F1D48A042007603F5 /* Resources */,
329 | );
330 | buildRules = (
331 | );
332 | dependencies = (
333 | F37A20581D48A042007603F5 /* PBXTargetDependency */,
334 | );
335 | name = JohnnyTests;
336 | productName = JohnnyTests;
337 | productReference = F37A20511D48A042007603F5 /* JohnnyTests.xctest */;
338 | productType = "com.apple.product-type.bundle.unit-test";
339 | };
340 | F3E4CAF21D256069005B30AB /* Johnny iOS */ = {
341 | isa = PBXNativeTarget;
342 | buildConfigurationList = F3E4CAFB1D256069005B30AB /* Build configuration list for PBXNativeTarget "Johnny iOS" */;
343 | buildPhases = (
344 | F3E4CAEE1D256069005B30AB /* Sources */,
345 | F3E4CAEF1D256069005B30AB /* Frameworks */,
346 | F3E4CAF01D256069005B30AB /* Headers */,
347 | F3E4CAF11D256069005B30AB /* Resources */,
348 | );
349 | buildRules = (
350 | );
351 | dependencies = (
352 | );
353 | name = "Johnny iOS";
354 | productName = Johnny;
355 | productReference = F3E4CAF31D256069005B30AB /* Johnny.framework */;
356 | productType = "com.apple.product-type.framework";
357 | };
358 | F3E4CB301D2572FC005B30AB /* Johnny macOS */ = {
359 | isa = PBXNativeTarget;
360 | buildConfigurationList = F3E4CB381D2572FC005B30AB /* Build configuration list for PBXNativeTarget "Johnny macOS" */;
361 | buildPhases = (
362 | F3E4CB2C1D2572FC005B30AB /* Sources */,
363 | F3E4CB2D1D2572FC005B30AB /* Frameworks */,
364 | F3E4CB2E1D2572FC005B30AB /* Headers */,
365 | F3E4CB2F1D2572FC005B30AB /* Resources */,
366 | );
367 | buildRules = (
368 | );
369 | dependencies = (
370 | );
371 | name = "Johnny macOS";
372 | productName = "Johnny macOS";
373 | productReference = F3E4CB311D2572FC005B30AB /* Johnny.framework */;
374 | productType = "com.apple.product-type.framework";
375 | };
376 | F3E4CB3D1D2573CD005B30AB /* Johnny tvOS */ = {
377 | isa = PBXNativeTarget;
378 | buildConfigurationList = F3E4CB431D2573CD005B30AB /* Build configuration list for PBXNativeTarget "Johnny tvOS" */;
379 | buildPhases = (
380 | F3E4CB391D2573CD005B30AB /* Sources */,
381 | F3E4CB3A1D2573CD005B30AB /* Frameworks */,
382 | F3E4CB3B1D2573CD005B30AB /* Headers */,
383 | F3E4CB3C1D2573CD005B30AB /* Resources */,
384 | );
385 | buildRules = (
386 | );
387 | dependencies = (
388 | );
389 | name = "Johnny tvOS";
390 | productName = "Johnny tvOS";
391 | productReference = F3E4CB3E1D2573CD005B30AB /* Johnny.framework */;
392 | productType = "com.apple.product-type.framework";
393 | };
394 | F3E4CB4A1D2573FF005B30AB /* Johnny watchOS */ = {
395 | isa = PBXNativeTarget;
396 | buildConfigurationList = F3E4CB501D2573FF005B30AB /* Build configuration list for PBXNativeTarget "Johnny watchOS" */;
397 | buildPhases = (
398 | F3E4CB461D2573FF005B30AB /* Sources */,
399 | F3E4CB471D2573FF005B30AB /* Frameworks */,
400 | F3E4CB481D2573FF005B30AB /* Headers */,
401 | F3E4CB491D2573FF005B30AB /* Resources */,
402 | );
403 | buildRules = (
404 | );
405 | dependencies = (
406 | );
407 | name = "Johnny watchOS";
408 | productName = "Johnny watchOS";
409 | productReference = F3E4CB4B1D2573FF005B30AB /* Johnny.framework */;
410 | productType = "com.apple.product-type.framework";
411 | };
412 | /* End PBXNativeTarget section */
413 |
414 | /* Begin PBXProject section */
415 | F3E4CAEA1D256069005B30AB /* Project object */ = {
416 | isa = PBXProject;
417 | attributes = {
418 | LastSwiftUpdateCheck = 0730;
419 | LastUpgradeCheck = 1010;
420 | ORGANIZATIONNAME = "Zoltán Matók";
421 | TargetAttributes = {
422 | F37A20501D48A042007603F5 = {
423 | CreatedOnToolsVersion = 7.3.1;
424 | LastSwiftMigration = 0900;
425 | };
426 | F3E4CAF21D256069005B30AB = {
427 | CreatedOnToolsVersion = 7.3.1;
428 | DevelopmentTeam = 83655RR9FZ;
429 | LastSwiftMigration = 0900;
430 | };
431 | F3E4CB301D2572FC005B30AB = {
432 | CreatedOnToolsVersion = 7.3.1;
433 | LastSwiftMigration = 0820;
434 | };
435 | F3E4CB3D1D2573CD005B30AB = {
436 | CreatedOnToolsVersion = 7.3.1;
437 | DevelopmentTeam = 83655RR9FZ;
438 | LastSwiftMigration = 0820;
439 | };
440 | F3E4CB4A1D2573FF005B30AB = {
441 | CreatedOnToolsVersion = 7.3.1;
442 | DevelopmentTeam = 83655RR9FZ;
443 | LastSwiftMigration = 0820;
444 | };
445 | };
446 | };
447 | buildConfigurationList = F3E4CAED1D256069005B30AB /* Build configuration list for PBXProject "Johnny" */;
448 | compatibilityVersion = "Xcode 3.2";
449 | developmentRegion = English;
450 | hasScannedForEncodings = 0;
451 | knownRegions = (
452 | English,
453 | en,
454 | );
455 | mainGroup = F3E4CAE91D256069005B30AB;
456 | productRefGroup = F3E4CAF41D256069005B30AB /* Products */;
457 | projectDirPath = "";
458 | projectRoot = "";
459 | targets = (
460 | F3E4CAF21D256069005B30AB /* Johnny iOS */,
461 | F3E4CB301D2572FC005B30AB /* Johnny macOS */,
462 | F3E4CB3D1D2573CD005B30AB /* Johnny tvOS */,
463 | F3E4CB4A1D2573FF005B30AB /* Johnny watchOS */,
464 | F37A20501D48A042007603F5 /* JohnnyTests */,
465 | );
466 | };
467 | /* End PBXProject section */
468 |
469 | /* Begin PBXResourcesBuildPhase section */
470 | F37A204F1D48A042007603F5 /* Resources */ = {
471 | isa = PBXResourcesBuildPhase;
472 | buildActionMask = 2147483647;
473 | files = (
474 | F37A20601D48AC3A007603F5 /* johnny-logo.png in Resources */,
475 | );
476 | runOnlyForDeploymentPostprocessing = 0;
477 | };
478 | F3E4CAF11D256069005B30AB /* Resources */ = {
479 | isa = PBXResourcesBuildPhase;
480 | buildActionMask = 2147483647;
481 | files = (
482 | F37A205F1D48AC39007603F5 /* johnny-logo.png in Resources */,
483 | );
484 | runOnlyForDeploymentPostprocessing = 0;
485 | };
486 | F3E4CB2F1D2572FC005B30AB /* Resources */ = {
487 | isa = PBXResourcesBuildPhase;
488 | buildActionMask = 2147483647;
489 | files = (
490 | );
491 | runOnlyForDeploymentPostprocessing = 0;
492 | };
493 | F3E4CB3C1D2573CD005B30AB /* Resources */ = {
494 | isa = PBXResourcesBuildPhase;
495 | buildActionMask = 2147483647;
496 | files = (
497 | );
498 | runOnlyForDeploymentPostprocessing = 0;
499 | };
500 | F3E4CB491D2573FF005B30AB /* Resources */ = {
501 | isa = PBXResourcesBuildPhase;
502 | buildActionMask = 2147483647;
503 | files = (
504 | );
505 | runOnlyForDeploymentPostprocessing = 0;
506 | };
507 | /* End PBXResourcesBuildPhase section */
508 |
509 | /* Begin PBXSourcesBuildPhase section */
510 | F37A204D1D48A042007603F5 /* Sources */ = {
511 | isa = PBXSourcesBuildPhase;
512 | buildActionMask = 2147483647;
513 | files = (
514 | F319959D1D48D60200429F83 /* JohnnyDiskTests.swift in Sources */,
515 | F37A20541D48A042007603F5 /* JohnnyMemoryTests.swift in Sources */,
516 | );
517 | runOnlyForDeploymentPostprocessing = 0;
518 | };
519 | F3E4CAEE1D256069005B30AB /* Sources */ = {
520 | isa = PBXSourcesBuildPhase;
521 | buildActionMask = 2147483647;
522 | files = (
523 | F3E4CB111D25634F005B30AB /* UIImageView+Johnny.swift in Sources */,
524 | F35901381D2A7DEC00868171 /* Foundation+Johnny.swift in Sources */,
525 | F3E4CB131D25634F005B30AB /* Log.swift in Sources */,
526 | F3036D361D2584A80056BCE4 /* UIButton+Johnny.swift in Sources */,
527 | F3382FB91D2594D3009C2110 /* UIColor+Johnny.swift in Sources */,
528 | F3E4CB121D25634F005B30AB /* Johnny.swift in Sources */,
529 | F3E4CB0B1D25634F005B30AB /* Disk.swift in Sources */,
530 | F3E4CB141D25634F005B30AB /* Memory.swift in Sources */,
531 | F3E4CB101D25634F005B30AB /* UIImage+Johnny.swift in Sources */,
532 | );
533 | runOnlyForDeploymentPostprocessing = 0;
534 | };
535 | F3E4CB2C1D2572FC005B30AB /* Sources */ = {
536 | isa = PBXSourcesBuildPhase;
537 | buildActionMask = 2147483647;
538 | files = (
539 | F3E4CB711D25756A005B30AB /* Log.swift in Sources */,
540 | F35901391D2A7DF100868171 /* Foundation+Johnny.swift in Sources */,
541 | F359013E1D2A822400868171 /* AppKit+Johnny.swift in Sources */,
542 | F3E4CB581D257552005B30AB /* Disk.swift in Sources */,
543 | F3E4CB571D257552005B30AB /* Memory.swift in Sources */,
544 | F3E4CB561D257552005B30AB /* Johnny.swift in Sources */,
545 | );
546 | runOnlyForDeploymentPostprocessing = 0;
547 | };
548 | F3E4CB391D2573CD005B30AB /* Sources */ = {
549 | isa = PBXSourcesBuildPhase;
550 | buildActionMask = 2147483647;
551 | files = (
552 | F359013A1D2A7DF200868171 /* Foundation+Johnny.swift in Sources */,
553 | F30F64921D46A39A00EDD75F /* UIButton+Johnny.swift in Sources */,
554 | F3E4CB721D25756B005B30AB /* Log.swift in Sources */,
555 | F3382FBA1D2594D8009C2110 /* UIColor+Johnny.swift in Sources */,
556 | F3E4CB5B1D257553005B30AB /* Disk.swift in Sources */,
557 | F3036D381D2584C30056BCE4 /* UIImage+Johnny.swift in Sources */,
558 | F3E4CB5A1D257553005B30AB /* Memory.swift in Sources */,
559 | F3E4CB591D257553005B30AB /* Johnny.swift in Sources */,
560 | F3E4CB6A1D25755E005B30AB /* UIImageView+Johnny.swift in Sources */,
561 | );
562 | runOnlyForDeploymentPostprocessing = 0;
563 | };
564 | F3E4CB461D2573FF005B30AB /* Sources */ = {
565 | isa = PBXSourcesBuildPhase;
566 | buildActionMask = 2147483647;
567 | files = (
568 | F359013B1D2A7DF200868171 /* Foundation+Johnny.swift in Sources */,
569 | F3E4CB731D25756B005B30AB /* Log.swift in Sources */,
570 | F30F64911D46A27500EDD75F /* WatchKit+Johnny.swift in Sources */,
571 | F3E4CB5E1D257554005B30AB /* Disk.swift in Sources */,
572 | F3382FBB1D2594D9009C2110 /* UIColor+Johnny.swift in Sources */,
573 | F3036D371D2584B00056BCE4 /* UIImage+Johnny.swift in Sources */,
574 | F3E4CB5D1D257554005B30AB /* Memory.swift in Sources */,
575 | F3E4CB5C1D257554005B30AB /* Johnny.swift in Sources */,
576 | );
577 | runOnlyForDeploymentPostprocessing = 0;
578 | };
579 | /* End PBXSourcesBuildPhase section */
580 |
581 | /* Begin PBXTargetDependency section */
582 | F37A20581D48A042007603F5 /* PBXTargetDependency */ = {
583 | isa = PBXTargetDependency;
584 | target = F3E4CAF21D256069005B30AB /* Johnny iOS */;
585 | targetProxy = F37A20571D48A042007603F5 /* PBXContainerItemProxy */;
586 | };
587 | /* End PBXTargetDependency section */
588 |
589 | /* Begin XCBuildConfiguration section */
590 | F37A20591D48A042007603F5 /* Debug */ = {
591 | isa = XCBuildConfiguration;
592 | buildSettings = {
593 | INFOPLIST_FILE = JohnnyTests/Info.plist;
594 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
595 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
596 | PRODUCT_BUNDLE_IDENTIFIER = ZoltanMatok.JohnnyTests;
597 | PRODUCT_NAME = "$(TARGET_NAME)";
598 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
599 | SWIFT_VERSION = 4.0;
600 | };
601 | name = Debug;
602 | };
603 | F37A205A1D48A042007603F5 /* Release */ = {
604 | isa = XCBuildConfiguration;
605 | buildSettings = {
606 | INFOPLIST_FILE = JohnnyTests/Info.plist;
607 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
608 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
609 | PRODUCT_BUNDLE_IDENTIFIER = ZoltanMatok.JohnnyTests;
610 | PRODUCT_NAME = "$(TARGET_NAME)";
611 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
612 | SWIFT_VERSION = 4.0;
613 | };
614 | name = Release;
615 | };
616 | F3E4CAF91D256069005B30AB /* Debug */ = {
617 | isa = XCBuildConfiguration;
618 | buildSettings = {
619 | ALWAYS_SEARCH_USER_PATHS = NO;
620 | CLANG_ANALYZER_NONNULL = YES;
621 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
622 | CLANG_CXX_LIBRARY = "libc++";
623 | CLANG_ENABLE_MODULES = YES;
624 | CLANG_ENABLE_OBJC_ARC = YES;
625 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
626 | CLANG_WARN_BOOL_CONVERSION = YES;
627 | CLANG_WARN_COMMA = YES;
628 | CLANG_WARN_CONSTANT_CONVERSION = YES;
629 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
630 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
631 | CLANG_WARN_EMPTY_BODY = YES;
632 | CLANG_WARN_ENUM_CONVERSION = YES;
633 | CLANG_WARN_INFINITE_RECURSION = YES;
634 | CLANG_WARN_INT_CONVERSION = YES;
635 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
636 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
637 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
638 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
639 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
640 | CLANG_WARN_STRICT_PROTOTYPES = YES;
641 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
642 | CLANG_WARN_UNREACHABLE_CODE = YES;
643 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
644 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
645 | COPY_PHASE_STRIP = NO;
646 | CURRENT_PROJECT_VERSION = 1;
647 | DEBUG_INFORMATION_FORMAT = dwarf;
648 | ENABLE_STRICT_OBJC_MSGSEND = YES;
649 | ENABLE_TESTABILITY = YES;
650 | GCC_C_LANGUAGE_STANDARD = gnu99;
651 | GCC_DYNAMIC_NO_PIC = NO;
652 | GCC_NO_COMMON_BLOCKS = YES;
653 | GCC_OPTIMIZATION_LEVEL = 0;
654 | GCC_PREPROCESSOR_DEFINITIONS = (
655 | "DEBUG=1",
656 | "$(inherited)",
657 | );
658 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
659 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
660 | GCC_WARN_UNDECLARED_SELECTOR = YES;
661 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
662 | GCC_WARN_UNUSED_FUNCTION = YES;
663 | GCC_WARN_UNUSED_VARIABLE = YES;
664 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
665 | MTL_ENABLE_DEBUG_INFO = YES;
666 | ONLY_ACTIVE_ARCH = YES;
667 | SDKROOT = iphoneos;
668 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
669 | TARGETED_DEVICE_FAMILY = "1,2";
670 | VERSIONING_SYSTEM = "apple-generic";
671 | VERSION_INFO_PREFIX = "";
672 | };
673 | name = Debug;
674 | };
675 | F3E4CAFA1D256069005B30AB /* Release */ = {
676 | isa = XCBuildConfiguration;
677 | buildSettings = {
678 | ALWAYS_SEARCH_USER_PATHS = NO;
679 | CLANG_ANALYZER_NONNULL = YES;
680 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
681 | CLANG_CXX_LIBRARY = "libc++";
682 | CLANG_ENABLE_MODULES = YES;
683 | CLANG_ENABLE_OBJC_ARC = YES;
684 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
685 | CLANG_WARN_BOOL_CONVERSION = YES;
686 | CLANG_WARN_COMMA = YES;
687 | CLANG_WARN_CONSTANT_CONVERSION = YES;
688 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
689 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
690 | CLANG_WARN_EMPTY_BODY = YES;
691 | CLANG_WARN_ENUM_CONVERSION = YES;
692 | CLANG_WARN_INFINITE_RECURSION = YES;
693 | CLANG_WARN_INT_CONVERSION = YES;
694 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
695 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
696 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
697 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
698 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
699 | CLANG_WARN_STRICT_PROTOTYPES = YES;
700 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
701 | CLANG_WARN_UNREACHABLE_CODE = YES;
702 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
703 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
704 | COPY_PHASE_STRIP = NO;
705 | CURRENT_PROJECT_VERSION = 1;
706 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
707 | ENABLE_NS_ASSERTIONS = NO;
708 | ENABLE_STRICT_OBJC_MSGSEND = YES;
709 | GCC_C_LANGUAGE_STANDARD = gnu99;
710 | GCC_NO_COMMON_BLOCKS = YES;
711 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
712 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
713 | GCC_WARN_UNDECLARED_SELECTOR = YES;
714 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
715 | GCC_WARN_UNUSED_FUNCTION = YES;
716 | GCC_WARN_UNUSED_VARIABLE = YES;
717 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
718 | MTL_ENABLE_DEBUG_INFO = NO;
719 | SDKROOT = iphoneos;
720 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
721 | TARGETED_DEVICE_FAMILY = "1,2";
722 | VALIDATE_PRODUCT = YES;
723 | VERSIONING_SYSTEM = "apple-generic";
724 | VERSION_INFO_PREFIX = "";
725 | };
726 | name = Release;
727 | };
728 | F3E4CAFC1D256069005B30AB /* Debug */ = {
729 | isa = XCBuildConfiguration;
730 | buildSettings = {
731 | CLANG_ENABLE_MODULES = YES;
732 | CODE_SIGN_IDENTITY = "iPhone Developer";
733 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
734 | DEFINES_MODULE = YES;
735 | DEVELOPMENT_TEAM = 83655RR9FZ;
736 | DYLIB_COMPATIBILITY_VERSION = 1;
737 | DYLIB_CURRENT_VERSION = 1;
738 | DYLIB_INSTALL_NAME_BASE = "@rpath";
739 | INFOPLIST_FILE = Johnny/Info.plist;
740 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
741 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
742 | OTHER_SWIFT_FLAGS = "$(inherited) -DUIKIT_COMPATIBLE";
743 | PRODUCT_BUNDLE_IDENTIFIER = ZoltanMatok.Johnny;
744 | PRODUCT_NAME = Johnny;
745 | SKIP_INSTALL = YES;
746 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
747 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
748 | SWIFT_VERSION = 4.0;
749 | };
750 | name = Debug;
751 | };
752 | F3E4CAFD1D256069005B30AB /* Release */ = {
753 | isa = XCBuildConfiguration;
754 | buildSettings = {
755 | CLANG_ENABLE_MODULES = YES;
756 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
757 | DEFINES_MODULE = YES;
758 | DYLIB_COMPATIBILITY_VERSION = 1;
759 | DYLIB_CURRENT_VERSION = 1;
760 | DYLIB_INSTALL_NAME_BASE = "@rpath";
761 | INFOPLIST_FILE = Johnny/Info.plist;
762 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
763 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
764 | OTHER_SWIFT_FLAGS = "$(inherited) -DUIKIT_COMPATIBLE";
765 | PRODUCT_BUNDLE_IDENTIFIER = ZoltanMatok.Johnny;
766 | PRODUCT_NAME = Johnny;
767 | SKIP_INSTALL = YES;
768 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
769 | SWIFT_VERSION = 4.0;
770 | };
771 | name = Release;
772 | };
773 | F3E4CB361D2572FC005B30AB /* Debug */ = {
774 | isa = XCBuildConfiguration;
775 | buildSettings = {
776 | CODE_SIGN_IDENTITY = "";
777 | COMBINE_HIDPI_IMAGES = YES;
778 | DEFINES_MODULE = YES;
779 | DEVELOPMENT_TEAM = "";
780 | DYLIB_COMPATIBILITY_VERSION = 1;
781 | DYLIB_CURRENT_VERSION = 1;
782 | DYLIB_INSTALL_NAME_BASE = "@rpath";
783 | FRAMEWORK_VERSION = A;
784 | INFOPLIST_FILE = "Johnny macOS/Info.plist";
785 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
786 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
787 | MACOSX_DEPLOYMENT_TARGET = 10.10;
788 | MODULEMAP_FILE = "$(SRCROOT)/Johnny macOS/macOS.modulemap";
789 | PRODUCT_BUNDLE_IDENTIFIER = "ZoltanMatok.Johnny-macOS";
790 | PRODUCT_NAME = Johnny;
791 | SDKROOT = macosx;
792 | SKIP_INSTALL = YES;
793 | SWIFT_VERSION = 4.0;
794 | };
795 | name = Debug;
796 | };
797 | F3E4CB371D2572FC005B30AB /* Release */ = {
798 | isa = XCBuildConfiguration;
799 | buildSettings = {
800 | CODE_SIGN_IDENTITY = "";
801 | COMBINE_HIDPI_IMAGES = YES;
802 | DEFINES_MODULE = YES;
803 | DYLIB_COMPATIBILITY_VERSION = 1;
804 | DYLIB_CURRENT_VERSION = 1;
805 | DYLIB_INSTALL_NAME_BASE = "@rpath";
806 | FRAMEWORK_VERSION = A;
807 | INFOPLIST_FILE = "Johnny macOS/Info.plist";
808 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
809 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
810 | MACOSX_DEPLOYMENT_TARGET = 10.10;
811 | MODULEMAP_FILE = "$(SRCROOT)/Johnny macOS/macOS.modulemap";
812 | PRODUCT_BUNDLE_IDENTIFIER = "ZoltanMatok.Johnny-macOS";
813 | PRODUCT_NAME = Johnny;
814 | SDKROOT = macosx;
815 | SKIP_INSTALL = YES;
816 | SWIFT_VERSION = 4.0;
817 | };
818 | name = Release;
819 | };
820 | F3E4CB441D2573CD005B30AB /* Debug */ = {
821 | isa = XCBuildConfiguration;
822 | buildSettings = {
823 | CODE_SIGN_IDENTITY = "";
824 | DEFINES_MODULE = YES;
825 | DEVELOPMENT_TEAM = 83655RR9FZ;
826 | DYLIB_COMPATIBILITY_VERSION = 1;
827 | DYLIB_CURRENT_VERSION = 1;
828 | DYLIB_INSTALL_NAME_BASE = "@rpath";
829 | INFOPLIST_FILE = "Johnny tvOS/Info.plist";
830 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
831 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
832 | MODULEMAP_FILE = "$(SRCROOT)/Johnny tvOS/tvOS.modulemap";
833 | OTHER_SWIFT_FLAGS = "-DUIKIT_COMPATIBLE $(inherited)";
834 | PRODUCT_BUNDLE_IDENTIFIER = "ZoltanMatok.Johnny-tvOS";
835 | PRODUCT_NAME = Johnny;
836 | SDKROOT = appletvos;
837 | SKIP_INSTALL = YES;
838 | SWIFT_VERSION = 4.0;
839 | TARGETED_DEVICE_FAMILY = 3;
840 | TVOS_DEPLOYMENT_TARGET = 9.0;
841 | };
842 | name = Debug;
843 | };
844 | F3E4CB451D2573CD005B30AB /* Release */ = {
845 | isa = XCBuildConfiguration;
846 | buildSettings = {
847 | CODE_SIGN_IDENTITY = "";
848 | DEFINES_MODULE = YES;
849 | DYLIB_COMPATIBILITY_VERSION = 1;
850 | DYLIB_CURRENT_VERSION = 1;
851 | DYLIB_INSTALL_NAME_BASE = "@rpath";
852 | INFOPLIST_FILE = "Johnny tvOS/Info.plist";
853 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
854 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
855 | MODULEMAP_FILE = "$(SRCROOT)/Johnny tvOS/tvOS.modulemap";
856 | OTHER_SWIFT_FLAGS = "-DUIKIT_COMPATIBLE $(inherited)";
857 | PRODUCT_BUNDLE_IDENTIFIER = "ZoltanMatok.Johnny-tvOS";
858 | PRODUCT_NAME = Johnny;
859 | SDKROOT = appletvos;
860 | SKIP_INSTALL = YES;
861 | SWIFT_VERSION = 4.0;
862 | TARGETED_DEVICE_FAMILY = 3;
863 | TVOS_DEPLOYMENT_TARGET = 9.0;
864 | };
865 | name = Release;
866 | };
867 | F3E4CB511D2573FF005B30AB /* Debug */ = {
868 | isa = XCBuildConfiguration;
869 | buildSettings = {
870 | APPLICATION_EXTENSION_API_ONLY = YES;
871 | CODE_SIGN_IDENTITY = "";
872 | DEFINES_MODULE = YES;
873 | DEVELOPMENT_TEAM = 83655RR9FZ;
874 | DYLIB_COMPATIBILITY_VERSION = 1;
875 | DYLIB_CURRENT_VERSION = 1;
876 | DYLIB_INSTALL_NAME_BASE = "@rpath";
877 | INFOPLIST_FILE = "Johnny watchOS/Info.plist";
878 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
879 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
880 | MODULEMAP_FILE = "$(SRCROOT)/Johnny watchOS/watchOS.modulemap";
881 | OTHER_SWIFT_FLAGS = "-DUIKIT_COMPATIBLE $(inherited) -DWATCHKIT";
882 | PRODUCT_BUNDLE_IDENTIFIER = "ZoltanMatok.Johnny-watchOS";
883 | PRODUCT_NAME = Johnny;
884 | SDKROOT = watchos;
885 | SKIP_INSTALL = YES;
886 | SWIFT_VERSION = 4.0;
887 | TARGETED_DEVICE_FAMILY = 4;
888 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
889 | };
890 | name = Debug;
891 | };
892 | F3E4CB521D2573FF005B30AB /* Release */ = {
893 | isa = XCBuildConfiguration;
894 | buildSettings = {
895 | APPLICATION_EXTENSION_API_ONLY = YES;
896 | CODE_SIGN_IDENTITY = "";
897 | DEFINES_MODULE = YES;
898 | DYLIB_COMPATIBILITY_VERSION = 1;
899 | DYLIB_CURRENT_VERSION = 1;
900 | DYLIB_INSTALL_NAME_BASE = "@rpath";
901 | INFOPLIST_FILE = "Johnny watchOS/Info.plist";
902 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
903 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
904 | MODULEMAP_FILE = "$(SRCROOT)/Johnny watchOS/watchOS.modulemap";
905 | OTHER_SWIFT_FLAGS = "-DUIKIT_COMPATIBLE $(inherited) -DWATCHKIT";
906 | PRODUCT_BUNDLE_IDENTIFIER = "ZoltanMatok.Johnny-watchOS";
907 | PRODUCT_NAME = Johnny;
908 | SDKROOT = watchos;
909 | SKIP_INSTALL = YES;
910 | SWIFT_VERSION = 4.0;
911 | TARGETED_DEVICE_FAMILY = 4;
912 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
913 | };
914 | name = Release;
915 | };
916 | /* End XCBuildConfiguration section */
917 |
918 | /* Begin XCConfigurationList section */
919 | F37A205B1D48A042007603F5 /* Build configuration list for PBXNativeTarget "JohnnyTests" */ = {
920 | isa = XCConfigurationList;
921 | buildConfigurations = (
922 | F37A20591D48A042007603F5 /* Debug */,
923 | F37A205A1D48A042007603F5 /* Release */,
924 | );
925 | defaultConfigurationIsVisible = 0;
926 | defaultConfigurationName = Release;
927 | };
928 | F3E4CAED1D256069005B30AB /* Build configuration list for PBXProject "Johnny" */ = {
929 | isa = XCConfigurationList;
930 | buildConfigurations = (
931 | F3E4CAF91D256069005B30AB /* Debug */,
932 | F3E4CAFA1D256069005B30AB /* Release */,
933 | );
934 | defaultConfigurationIsVisible = 0;
935 | defaultConfigurationName = Release;
936 | };
937 | F3E4CAFB1D256069005B30AB /* Build configuration list for PBXNativeTarget "Johnny iOS" */ = {
938 | isa = XCConfigurationList;
939 | buildConfigurations = (
940 | F3E4CAFC1D256069005B30AB /* Debug */,
941 | F3E4CAFD1D256069005B30AB /* Release */,
942 | );
943 | defaultConfigurationIsVisible = 0;
944 | defaultConfigurationName = Release;
945 | };
946 | F3E4CB381D2572FC005B30AB /* Build configuration list for PBXNativeTarget "Johnny macOS" */ = {
947 | isa = XCConfigurationList;
948 | buildConfigurations = (
949 | F3E4CB361D2572FC005B30AB /* Debug */,
950 | F3E4CB371D2572FC005B30AB /* Release */,
951 | );
952 | defaultConfigurationIsVisible = 0;
953 | defaultConfigurationName = Release;
954 | };
955 | F3E4CB431D2573CD005B30AB /* Build configuration list for PBXNativeTarget "Johnny tvOS" */ = {
956 | isa = XCConfigurationList;
957 | buildConfigurations = (
958 | F3E4CB441D2573CD005B30AB /* Debug */,
959 | F3E4CB451D2573CD005B30AB /* Release */,
960 | );
961 | defaultConfigurationIsVisible = 0;
962 | defaultConfigurationName = Release;
963 | };
964 | F3E4CB501D2573FF005B30AB /* Build configuration list for PBXNativeTarget "Johnny watchOS" */ = {
965 | isa = XCConfigurationList;
966 | buildConfigurations = (
967 | F3E4CB511D2573FF005B30AB /* Debug */,
968 | F3E4CB521D2573FF005B30AB /* Release */,
969 | );
970 | defaultConfigurationIsVisible = 0;
971 | defaultConfigurationName = Release;
972 | };
973 | /* End XCConfigurationList section */
974 | };
975 | rootObject = F3E4CAEA1D256069005B30AB /* Project object */;
976 | }
977 |
--------------------------------------------------------------------------------