├── Cartfile ├── Cartfile.lock ├── Vendor └── HockeySDK-iOS │ └── BuildAgent ├── Coins ├── Resources │ ├── Settings.bundle │ │ ├── en.lproj │ │ │ └── Root.strings │ │ └── Root.plist │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── iPad.png │ │ │ ├── iPad@2x.png │ │ │ ├── Settings.png │ │ │ ├── Spotlight.png │ │ │ ├── iPhone@2x.png │ │ │ ├── iPhone@3x.png │ │ │ ├── Settings@2x.png │ │ │ ├── Settings@3x.png │ │ │ ├── Spotlight@2x.png │ │ │ ├── Spotlight@3x.png │ │ │ ├── Settings@2x-1.png │ │ │ ├── Spotlight@2x-1.png │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ ├── iPad Landscape.png │ │ │ ├── iPad Portrait.png │ │ │ ├── iPad Landscape@2x.png │ │ │ ├── iPad Portrait@2x.png │ │ │ ├── 4" iPhone Portrait@2x.png │ │ │ ├── 3.5" iPhone Portrait@2x.png │ │ │ ├── 4.7" iPhone Portrait@2x.png │ │ │ ├── 5.5" iPhone Landscape@3x.png │ │ │ ├── 5.5" iPhone Portrait@3x.png │ │ │ └── Contents.json │ ├── en.lproj │ │ └── Localizable.strings │ ├── Coins.entitlements │ ├── Coins-Info.plist │ └── currencies.json ├── Other Sources │ └── Coins-Bridging-Header.h └── Classes │ ├── PullToRefreshView.swift │ ├── TickingButton.swift │ ├── TextField.swift │ ├── NSDate+Coins.swift │ ├── TableViewCell.swift │ ├── CurrencyPickerTableViewController.swift │ ├── AppDelegate.swift │ └── ValueViewController.swift ├── .gitignore ├── Coins.xcworkspace └── contents.xcworkspacedata ├── Podfile ├── Coins.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── Coins Today ├── Classes │ ├── BTCTodayValueView.h │ ├── BTCTodayViewController.h │ ├── BTCTodayValueView.m │ └── BTCTodayViewController.m └── Resources │ ├── Coins Today.entitlements │ └── Info.plist ├── CoinsKit ├── Classes │ ├── NSUserDefaults+Coins.h │ ├── CoinsKit.h │ ├── BTCConversionProvider.h │ ├── BTCValueView.h │ ├── NSUserDefaults+Coins.m │ ├── BTCPreferences.h │ ├── BTCDefines.h │ ├── BTCDefines.m │ ├── BTCConversionProvider.m │ ├── BTCPreferences.m │ └── BTCValueView.m ├── CoinsKit.h ├── CoinsKit.swift └── Info.plist ├── Podfile.lock ├── LICENSE ├── Changelog.markdown └── Readme.markdown /Cartfile: -------------------------------------------------------------------------------- 1 | github "soffes/GradientView" 2 | -------------------------------------------------------------------------------- /Cartfile.lock: -------------------------------------------------------------------------------- 1 | github "soffes/GradientView" "v2.0" 2 | -------------------------------------------------------------------------------- /Vendor/HockeySDK-iOS/BuildAgent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Vendor/HockeySDK-iOS/BuildAgent -------------------------------------------------------------------------------- /Coins/Resources/Settings.bundle/en.lproj/Root.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Settings.bundle/en.lproj/Root.strings -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *xcuserdata/ 3 | *.mode1v3 4 | *.pbxuser 5 | *.moved-aside/ 6 | Pods 7 | xcshareddata 8 | Carthage.build 9 | Carthage.checkout 10 | -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/iPad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/iPad.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/iPad@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/iPad@2x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/Settings.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/Spotlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/Spotlight.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/iPhone@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/iPhone@2x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/iPhone@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/iPhone@3x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/Settings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/Settings@2x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/Settings@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/Settings@3x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/Spotlight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/Spotlight@2x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/Spotlight@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/Spotlight@3x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/Settings@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/Settings@2x-1.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/Spotlight@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/AppIcon.appiconset/Spotlight@2x-1.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/LaunchImage.launchimage/iPad Landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/LaunchImage.launchimage/iPad Landscape.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/LaunchImage.launchimage/iPad Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/LaunchImage.launchimage/iPad Portrait.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/LaunchImage.launchimage/iPad Landscape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/LaunchImage.launchimage/iPad Landscape@2x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/LaunchImage.launchimage/iPad Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/LaunchImage.launchimage/iPad Portrait@2x.png -------------------------------------------------------------------------------- /Coins.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | 3 | platform :ios, '8.0' 4 | 5 | target 'Coins' do 6 | pod 'HockeySDK' 7 | pod 'SSPullToRefresh' 8 | pod 'Mixpanel' 9 | end 10 | -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/LaunchImage.launchimage/4" iPhone Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/LaunchImage.launchimage/4" iPhone Portrait@2x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/LaunchImage.launchimage/3.5" iPhone Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/LaunchImage.launchimage/3.5" iPhone Portrait@2x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/LaunchImage.launchimage/4.7" iPhone Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/LaunchImage.launchimage/4.7" iPhone Portrait@2x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/LaunchImage.launchimage/5.5" iPhone Landscape@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/LaunchImage.launchimage/5.5" iPhone Landscape@3x.png -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/LaunchImage.launchimage/5.5" iPhone Portrait@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/coins/HEAD/Coins/Resources/Images.xcassets/LaunchImage.launchimage/5.5" iPhone Portrait@3x.png -------------------------------------------------------------------------------- /Coins.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Coins/Other Sources/Coins-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import 6 | #import 7 | #import 8 | -------------------------------------------------------------------------------- /Coins Today/Classes/BTCTodayValueView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTCTodayValueView.h 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 9/17/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | @import CoinsKit; 10 | 11 | @interface BTCTodayValueView : BTCValueView 12 | @end 13 | -------------------------------------------------------------------------------- /Coins Today/Classes/BTCTodayViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTCTodayViewController.h 3 | // Coins Today 4 | // 5 | // Created by Sam Soffes on 9/17/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface BTCTodayViewController : UIViewController 12 | @end 13 | -------------------------------------------------------------------------------- /CoinsKit/Classes/NSUserDefaults+Coins.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSUserDefaults+Coins.h 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 9/17/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | @interface NSUserDefaults (Coins) 12 | 13 | + (instancetype)btc_sharedDefaults; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /CoinsKit/Classes/CoinsKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoinsKit.h 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 9/17/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | #import "BTCPreferences.h" 10 | #import "BTCConversionProvider.h" 11 | #import "BTCValueView.h" 12 | #import "BTCDefines.h" 13 | 14 | #import "NSUserDefaults+Coins.h" 15 | -------------------------------------------------------------------------------- /Coins/Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | Coins 4 | 5 | Created by Sam Soffes on 12/20/13. 6 | Copyright (c) 2013-2014 Nothing Magical, Inc. All rights reserved. 7 | */ 8 | 9 | "CURRENCY" = "Currency"; 10 | "DONE" = "Done"; 11 | "UPDATING" = "Updating…"; 12 | "UPDATED_FORMAT" = "Updated %@"; 13 | "NEVER_UPDATED" = "Never updated"; 14 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - HockeySDK (3.6.1) 3 | - Mixpanel (2.6.0): 4 | - Mixpanel/MPCategoryHelpers (= 2.6.0) 5 | - Mixpanel/MPCategoryHelpers (2.6.0) 6 | - SSPullToRefresh (1.2.0) 7 | 8 | DEPENDENCIES: 9 | - HockeySDK 10 | - Mixpanel 11 | - SSPullToRefresh 12 | 13 | SPEC CHECKSUMS: 14 | HockeySDK: 15b24068466aa5ee421eed0cc1d58428d698edf6 15 | Mixpanel: e919d14f07a34ee01f81f97e535b7a240af2f793 16 | SSPullToRefresh: bb513a1ccbf08fdd67e4139bc1bbe3fc2ed34228 17 | 18 | COCOAPODS: 0.35.0 19 | -------------------------------------------------------------------------------- /CoinsKit/Classes/BTCConversionProvider.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTCConversionProvider.h 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 12/20/13. 6 | // Copyright (c) 2013-2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface BTCConversionProvider : NSObject 12 | 13 | + (instancetype)sharedProvider; 14 | 15 | - (void)getConversionRates:(void(^)(NSDictionary *conversionRates, UIBackgroundFetchResult result))completion; 16 | - (NSDictionary *)latestConversionRates; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /CoinsKit/Classes/BTCValueView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTCValueView.h 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 4/23/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface BTCValueView : UIView 12 | 13 | @property (nonatomic) NSDictionary *conversionRates; 14 | 15 | @property (nonatomic, readonly) UIButton *valueButton; 16 | @property (nonatomic, readonly) UIButton *quantityButton; 17 | 18 | - (CGFloat)verticalSpacing; 19 | - (void)setupViews; 20 | - (void)setupConstraints; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Coins/Resources/Coins.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | com.apple.developer.ubiquity-kvstore-identifier 8 | $(TeamIdentifierPrefix)group.com.nothingmagical.coins 9 | com.apple.security.application-groups 10 | 11 | group.com.nothingmagical.coins 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /CoinsKit/CoinsKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoinsKit.h 3 | // CoinsKit 4 | // 5 | // Created by Sam Soffes on 11/26/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for CoinsKit. 12 | FOUNDATION_EXPORT double CoinsKitVersionNumber; 13 | 14 | //! Project version string for CoinsKit. 15 | FOUNDATION_EXPORT const unsigned char CoinsKitVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /CoinsKit/Classes/NSUserDefaults+Coins.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSUserDefaults+Coins.m 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 9/17/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | #import "NSUserDefaults+Coins.h" 10 | 11 | @implementation NSUserDefaults (Coins) 12 | 13 | + (instancetype)btc_sharedDefaults { 14 | static NSUserDefaults *defaults; 15 | static dispatch_once_t onceToken; 16 | dispatch_once(&onceToken, ^{ 17 | defaults = [[self alloc] initWithSuiteName:@"group.com.nothingmagical.coins"]; 18 | }); 19 | return defaults; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Coins Today/Resources/Coins Today.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | com.apple.developer.ubiquity-kvstore-identifier 8 | $(TeamIdentifierPrefix)group.com.nothingmagical.coins 9 | com.apple.security.application-groups 10 | 11 | group.com.nothingmagical.coins 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /CoinsKit/Classes/BTCPreferences.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTCPreferences.h 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 9/17/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | @interface BTCPreferences : NSObject 12 | 13 | + (instancetype)sharedPreferences; 14 | 15 | - (void)registerDefaults:(NSDictionary *)defaults; 16 | - (id)objectForKey:(NSString *)key; 17 | - (double)doubleForKey:(NSString *)key; 18 | - (void)setObject:(id)object forKey:(NSString *)key; 19 | - (void)removeObjectForKey:(NSString *)key; 20 | 21 | - (void)synchronize; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /CoinsKit/Classes/BTCDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTCDefines.h 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 12/20/13. 6 | // Copyright (c) 2013-2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | #ifndef BTCDEFINES 10 | #define BTCDEFINES 1 11 | 12 | @import Foundation; 13 | 14 | extern NSString *const kBTCSelectedCurrencyKey; 15 | extern NSString *const kBTCNumberOfCoinsKey; 16 | extern NSString *const kBTCControlsHiddenKey; 17 | extern NSString *const kBTCAutomaticallyRefreshKey; 18 | extern NSString *const kBTCDisableSleepKey; 19 | 20 | extern NSString *const kBTCCurrencyDidChangeNotificationName; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /CoinsKit/Classes/BTCDefines.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTCDefines.m 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 12/20/13. 6 | // Copyright (c) 2013-2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | #import "BTCDefines.h" 10 | 11 | NSString *const kBTCSelectedCurrencyKey = @"BTCSelectedCurrency"; 12 | NSString *const kBTCNumberOfCoinsKey = @"BTCNumberOfCoins"; 13 | NSString *const kBTCControlsHiddenKey = @"BTCControlsHidden"; 14 | NSString *const kBTCAutomaticallyRefreshKey = @"BTCAutomaticallyRefresh"; 15 | NSString *const kBTCDisableSleepKey = @"BTCDisableSleep"; 16 | 17 | NSString *const kBTCCurrencyDidChangeNotificationName = @"BTCCurrencyDidChangeNotification"; 18 | -------------------------------------------------------------------------------- /CoinsKit/CoinsKit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CoinsKit.swift 3 | // CoinsKit 4 | // 5 | // Created by Sam Soffes on 11/25/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public struct CoinsKit { 12 | public static let blueColor: UIColor = { 13 | return UIColor(red: 0.129, green: 0.455, blue: 0.627, alpha: 1.0) 14 | }() 15 | 16 | public static let purpleColor: UIColor = { 17 | return UIColor(red: 0.369, green: 0.173, blue: 0.6, alpha: 1.0) 18 | }() 19 | 20 | public static let isPad = UIDevice.currentDevice().userInterfaceIdiom == .Pad 21 | } 22 | 23 | public func LocalizedString(key: String, comment: String = "") -> String { 24 | return NSLocalizedString(key, comment: comment) 25 | } 26 | 27 | public let LayoutPriorityRequired = UILayoutPriority(1000) 28 | public let LayoutPriorityDefaultLow = UILayoutPriority(250) 29 | -------------------------------------------------------------------------------- /CoinsKit/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.nothingmagical.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Coins/Classes/PullToRefreshView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PullToRefreshView.swift 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 11/26/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PullToRefreshView: SSPullToRefreshView { 12 | 13 | // MARK: - Initializers 14 | 15 | override init(scrollView: UIScrollView!, delegate: SSPullToRefreshViewDelegate!) { 16 | super.init(scrollView: scrollView, delegate: delegate) 17 | 18 | defaultContentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0) 19 | 20 | let contentView = SSPullToRefreshSimpleContentView() 21 | contentView.statusLabel.textColor = UIColor(white: 1, alpha: 0.8) 22 | contentView.statusLabel.font = UIFont(name: "Avenir-Light", size: 12) 23 | contentView.activityIndicatorView.activityIndicatorViewStyle = .White 24 | self.contentView = contentView 25 | } 26 | 27 | override init(frame: CGRect) { 28 | super.init(frame: frame) 29 | } 30 | 31 | required init(coder aDecoder: NSCoder) { 32 | fatalError("init(coder:) has not been implemented") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Coins Today/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Coins 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | com.nothingmagical.coins.today 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0.2 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 6 25 | NSExtension 26 | 27 | NSExtensionPointIdentifier 28 | com.apple.widget-extension 29 | NSExtensionPrincipalClass 30 | BTCTodayViewController 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2014 Nothing Magical Inc., http://nothingmagical.com 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Changelog.markdown: -------------------------------------------------------------------------------- 1 | # Coins Changelog 2 | 3 | Version history for [Coins for iOS](http://getcoinsapp.com). 4 | 5 | ## Version 1.1.3 6 | *Unrelased* 7 | 8 | * Fix a bug causing your bitcoin quanity to get reset for some users 9 | * Other improvements 10 | 11 | 12 | ## Version 1.1.2 13 | *Released October 23, 2014* 14 | 15 | Bug fixes for today widget 16 | 17 | 18 | ## Version 1.1.1 19 | *Released October 6, 2014* 20 | 21 | * Fix typing decimals 22 | * Other bug fixes 23 | 24 | 25 | ## Version 1.1 26 | *Released September 19, 2014* 27 | 28 | * Added support for iPhone 6 & iPhone 6 Plus 29 | * New today widget for iOS 8 30 | * New iCloud sync 31 | * Automatically refresh in the background 32 | 33 | 34 | ## Version 1.0.3 35 | *Released April 24, 2014* 36 | 37 | Bug fixes 38 | 39 | 40 | ## Version 1.0.1 41 | *Released January 11, 2014* 42 | 43 | * Automatically refresh when you come back to the app 44 | * Use 0 as the placeholder when entering your BTC 45 | * Fix a few rounding bugs 46 | * Added pull to refresh 47 | * Larger text on iPad 48 | * Fixed a bug that would prompt you to enter your BTC if you have less than one. 49 | 50 | 51 | ## Version 1.0 52 | *Released January 3, 2014* 53 | 54 | Initial release. 55 | -------------------------------------------------------------------------------- /Coins/Classes/TickingButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TickingButton.swift 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 11/25/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoinsKit 11 | 12 | class TickingButton: UIButton { 13 | 14 | // MARK: - Properties 15 | 16 | var ticking = false 17 | 18 | var date: NSDate? { 19 | didSet { 20 | tick() 21 | } 22 | } 23 | 24 | var format: String = "" { 25 | didSet { 26 | tick() 27 | } 28 | } 29 | 30 | var timer: NSTimer? 31 | 32 | 33 | // MARK: - Public 34 | 35 | func startTicking() { 36 | ticking = true 37 | let timer = NSTimer(timeInterval: 1, target: self, selector: "tick", userInfo: nil, repeats: true) 38 | NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes) 39 | self.timer = timer 40 | } 41 | 42 | func stopTicking() { 43 | if !ticking { 44 | return 45 | } 46 | 47 | ticking = false 48 | timer?.invalidate() 49 | timer = nil 50 | } 51 | 52 | func tick() { 53 | var title = LocalizedString("NEVER_UPDATED") 54 | if let date = date { 55 | // This is gross 56 | title = (format as NSString).stringByReplacingOccurrencesOfString("%@", withString: date.timeAgoInWords) 57 | } 58 | setTitle(title, forState: .Normal) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Readme.markdown: -------------------------------------------------------------------------------- 1 | # Coins 2 | 3 | A simple app to see how much your wallet is worth. It's like [Shares](http://getsharesapp.com) but for Bitcoin. 4 | 5 | 6 | ## Building 7 | 8 | You’ll need [CocoaPods](http://cocoapods.org) to build Coins. See their [getting start guide](http://guides.cocoapods.org/using/getting-started.html#getting-started) if you don’t already have CocoaPods. 9 | 10 | You'll also need [Carthage](https://github.com/Carthage/Carthage). See their [installation guide](https://github.com/Carthage/Carthage#installing-carthage) if you don't already have Carthage installed. (Eventually, I'd love to just have Carthage instead of both.) 11 | 12 | Xcode 6.0 or higher is required. 13 | 14 | Simply run `pod install`, `carthage update`, open `Coins.xcworkspace`, and build the *Coins* target to run the app. 15 | 16 | 17 | ## Related Repos 18 | 19 | * [Coins Website](https://github.com/nothingmagical/getcoinsapp.com) 20 | * [Coins for Android](https://github.com/nothingmagical/coins-android) 21 | 22 | 23 | ## License 24 | 25 | Coins is released under the [MIT license](LICENSE). While the license says you can do whatever you want with it, I'd apprecaite it if you don't release an exact copy to the App Store. This is released as an open source project primarily for educational purposes. That said, there's nothing stopping you from doing whatever you want with it. 26 | -------------------------------------------------------------------------------- /Coins/Resources/Settings.bundle/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | Title 9 | GENERAL 10 | Type 11 | PSGroupSpecifier 12 | 13 | 14 | DefaultValue 15 | 16 | Key 17 | BTCAutomaticallyRefresh 18 | Title 19 | AUTOMATICALLY_REFRESH 20 | Type 21 | PSToggleSwitchSpecifier 22 | 23 | 24 | DefaultValue 25 | 26 | Key 27 | BTCDisableSleep 28 | Title 29 | DISABLE_SLEEP 30 | Type 31 | PSToggleSwitchSpecifier 32 | 33 | 34 | Title 35 | ABOUT 36 | Type 37 | PSGroupSpecifier 38 | 39 | 40 | Type 41 | PSTitleValueSpecifier 42 | Title 43 | VERSION 44 | DefaultValue 45 | 46 | Key 47 | BTCVersion 48 | 49 | 50 | StringsTable 51 | Root 52 | 53 | 54 | -------------------------------------------------------------------------------- /Coins/Classes/TextField.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextField.swift 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 11/25/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TextField: UITextField { 12 | 13 | // MARK: - Initializers 14 | 15 | override convenience init() { 16 | self.init(frame: CGRectZero) 17 | } 18 | 19 | override init(frame: CGRect) { 20 | super.init(frame: frame) 21 | 22 | keyboardType = .DecimalPad 23 | font = UIFont(name: "Avenir-Light", size: 24) 24 | textColor = UIColor.whiteColor() 25 | textAlignment = .Center 26 | tintColor = UIColor.whiteColor() 27 | backgroundColor = UIColor(white: 1, alpha: 0.1) 28 | layer.cornerRadius = 5 29 | 30 | attributedPlaceholder = NSAttributedString(string: "0", attributes: [ 31 | NSForegroundColorAttributeName: UIColor(white: 1, alpha: 0.3), 32 | NSFontAttributeName: font 33 | ]) 34 | 35 | let suffix = UILabel(frame: CGRect(x: 0, y: 0, width: 60, height: 54)) 36 | suffix.text = "BTC" 37 | suffix.textColor = UIColor(white: 1, alpha: 0.3) 38 | suffix.font = font 39 | rightView = suffix 40 | rightViewMode = .Always 41 | } 42 | 43 | required init(coder aDecoder: NSCoder) { 44 | fatalError("init(coder:) has not been implemented") 45 | } 46 | 47 | 48 | // MARK: - UITextField 49 | 50 | override func textRectForBounds(bounds: CGRect) -> CGRect { 51 | return UIEdgeInsetsInsetRect(super.textRectForBounds(bounds), UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)) 52 | } 53 | 54 | override func editingRectForBounds(bounds: CGRect) -> CGRect { 55 | return textRectForBounds(bounds) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Settings@2x-1.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Settings@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Spotlight@2x-1.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Spotlight@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "iPhone@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "iPhone@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "Settings.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "Settings@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "Spotlight.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "Spotlight@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "iPad.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "iPad@2x.png", 73 | "scale" : "2x" 74 | } 75 | ], 76 | "info" : { 77 | "version" : 1, 78 | "author" : "xcode" 79 | } 80 | } -------------------------------------------------------------------------------- /Coins/Classes/NSDate+Coins.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+Coins.swift 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 11/25/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension NSDate { 12 | var timeAgoInWords: String { 13 | let intervalInSeconds = fabs(timeIntervalSinceNow) 14 | // let includeSeconds = true 15 | let intervalInMinutes = round(intervalInSeconds / 60.0) 16 | 17 | if intervalInMinutes >= 0 && intervalInMinutes <= 1 { 18 | // if !includeSeconds { 19 | // return intervalInMinutes <= 0 ? "less than a minute ago" : "1 minute ago" 20 | // } 21 | if intervalInSeconds >= 0 && intervalInSeconds < 10 { 22 | return "just now" 23 | } else if intervalInSeconds >= 10 && intervalInSeconds < 60 { 24 | return "\(Int(intervalInSeconds)) seconds ago" 25 | } else { 26 | return "1 minute ago" 27 | } 28 | } else if intervalInMinutes >= 2 && intervalInMinutes <= 44 { 29 | return "\(Int(intervalInMinutes)) minutes ago" 30 | } else if intervalInMinutes >= 45 && intervalInMinutes <= 89 { 31 | return "about 1 hour ago" 32 | } else if intervalInMinutes >= 90 && intervalInMinutes <= 1439 { 33 | return "\(Int(ceil(intervalInMinutes / 60.0))) hours ago" 34 | } else if intervalInMinutes >= 1440 && intervalInMinutes <= 2879 { 35 | return "1 day ago" 36 | } else if intervalInMinutes >= 2880 && intervalInMinutes <= 43199 { 37 | return "\(Int(ceil(intervalInMinutes / 1440.0))) days ago" 38 | } else if intervalInMinutes >= 43200 && intervalInMinutes <= 86399 { 39 | return "1 month ago" 40 | } else if intervalInMinutes >= 86400 && intervalInMinutes <= 525599 { 41 | return "\(Int(ceil(intervalInMinutes / 43200.0))) months ago" 42 | } else if intervalInMinutes >= 525600 && intervalInMinutes <= 1051199 { 43 | return "1 year ago" 44 | } 45 | 46 | return "\(Int(ceil(intervalInMinutes / 525600.0))) years ago" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Coins/Classes/TableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewCell.swift 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 11/25/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoinsKit 11 | 12 | class TableViewCell: UITableViewCell { 13 | 14 | // MARK: - Initializers 15 | 16 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 17 | super.init(style: .Value1, reuseIdentifier: reuseIdentifier) 18 | 19 | textLabel?.font = UIFont(name: "Avenir-Heavy", size: 18) 20 | textLabel?.textColor = UIColor(white: 0.4, alpha: 1) 21 | textLabel?.highlightedTextColor = UIColor.whiteColor() 22 | textLabel?.adjustsFontSizeToFitWidth = true 23 | 24 | if let detailTextLabel = detailTextLabel { 25 | detailTextLabel.font = UIFont(name: "Avenir-Book", size: 18) 26 | detailTextLabel.textColor = UIColor(white: 0.4, alpha: 0.5) 27 | detailTextLabel.highlightedTextColor = UIColor.whiteColor() 28 | } 29 | 30 | if UIDevice.currentDevice().userInterfaceIdiom == .Pad { 31 | let background = UIView() 32 | background.backgroundColor = UIColor(white: 1, alpha: 0.3) 33 | backgroundView = background 34 | } 35 | 36 | let selected = UIView() 37 | selected.backgroundColor = CoinsKit.blueColor 38 | selectedBackgroundView = selected 39 | } 40 | 41 | required init(coder aDecoder: NSCoder) { 42 | fatalError("init(coder:) has not been implemented") 43 | } 44 | 45 | 46 | // MARK: - UIView 47 | 48 | override func layoutSubviews() { 49 | super.layoutSubviews() 50 | 51 | if let textLabel = textLabel { 52 | var rect = textLabel.frame 53 | rect.size.width = min(rect.size.width, 240) 54 | textLabel.frame = rect 55 | } 56 | 57 | if let detailTextLabel = detailTextLabel { 58 | let size = contentView.bounds.size 59 | detailTextLabel.frame = CGRect(x: size.width - 70, y: 10, width: 60, height: size.height - 20) 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Coins/Resources/Coins-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.nothingmagical.coins 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.1.3 21 | CFBundleSignature 22 | ???? 23 | CFBundleURLTypes 24 | 25 | 26 | CFBundleTypeRole 27 | Editor 28 | CFBundleURLName 29 | coins 30 | CFBundleURLSchemes 31 | 32 | coins 33 | 34 | 35 | 36 | CFBundleVersion 37 | 17 38 | LSRequiresIPhoneOS 39 | 40 | UIBackgroundModes 41 | 42 | fetch 43 | 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UIStatusBarHidden 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | UIInterfaceOrientationPortraitUpsideDown 56 | 57 | UISupportedInterfaceOrientations~ipad 58 | 59 | UIInterfaceOrientationPortrait 60 | UIInterfaceOrientationPortraitUpsideDown 61 | UIInterfaceOrientationLandscapeLeft 62 | UIInterfaceOrientationLandscapeRight 63 | 64 | UIViewControllerBasedStatusBarAppearance 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /Coins/Resources/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "extent" : "full-screen", 5 | "idiom" : "iphone", 6 | "subtype" : "736h", 7 | "filename" : "5.5\" iPhone Portrait@3x.png", 8 | "minimum-system-version" : "8.0", 9 | "orientation" : "portrait", 10 | "scale" : "3x" 11 | }, 12 | { 13 | "extent" : "full-screen", 14 | "idiom" : "iphone", 15 | "subtype" : "736h", 16 | "filename" : "5.5\" iPhone Landscape@3x.png", 17 | "minimum-system-version" : "8.0", 18 | "orientation" : "landscape", 19 | "scale" : "3x" 20 | }, 21 | { 22 | "extent" : "full-screen", 23 | "idiom" : "iphone", 24 | "subtype" : "667h", 25 | "filename" : "4.7\" iPhone Portrait@2x.png", 26 | "minimum-system-version" : "8.0", 27 | "orientation" : "portrait", 28 | "scale" : "2x" 29 | }, 30 | { 31 | "orientation" : "portrait", 32 | "idiom" : "iphone", 33 | "extent" : "full-screen", 34 | "minimum-system-version" : "7.0", 35 | "filename" : "3.5\" iPhone Portrait@2x.png", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "extent" : "full-screen", 40 | "idiom" : "iphone", 41 | "subtype" : "retina4", 42 | "filename" : "4\" iPhone Portrait@2x.png", 43 | "minimum-system-version" : "7.0", 44 | "orientation" : "portrait", 45 | "scale" : "2x" 46 | }, 47 | { 48 | "orientation" : "portrait", 49 | "idiom" : "ipad", 50 | "extent" : "full-screen", 51 | "minimum-system-version" : "7.0", 52 | "filename" : "iPad Portrait.png", 53 | "scale" : "1x" 54 | }, 55 | { 56 | "orientation" : "landscape", 57 | "idiom" : "ipad", 58 | "extent" : "full-screen", 59 | "minimum-system-version" : "7.0", 60 | "filename" : "iPad Landscape.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "orientation" : "portrait", 65 | "idiom" : "ipad", 66 | "extent" : "full-screen", 67 | "minimum-system-version" : "7.0", 68 | "filename" : "iPad Portrait@2x.png", 69 | "scale" : "2x" 70 | }, 71 | { 72 | "orientation" : "landscape", 73 | "idiom" : "ipad", 74 | "extent" : "full-screen", 75 | "minimum-system-version" : "7.0", 76 | "filename" : "iPad Landscape@2x.png", 77 | "scale" : "2x" 78 | } 79 | ], 80 | "info" : { 81 | "version" : 1, 82 | "author" : "xcode" 83 | } 84 | } -------------------------------------------------------------------------------- /CoinsKit/Classes/BTCConversionProvider.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTCConversionProvider.m 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 12/20/13. 6 | // Copyright (c) 2013-2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | #import "BTCConversionProvider.h" 10 | #import "BTCPreferences.h" 11 | 12 | @implementation BTCConversionProvider 13 | 14 | static NSString *const BTCConversionProviderCacheKey = @"BTCConversion"; 15 | 16 | + (instancetype)sharedProvider { 17 | static BTCConversionProvider *provider = nil; 18 | static dispatch_once_t onceToken; 19 | dispatch_once(&onceToken, ^{ 20 | provider = [[self alloc] init]; 21 | }); 22 | 23 | return provider; 24 | } 25 | 26 | 27 | - (void)getConversionRates:(void (^)(NSDictionary *, UIBackgroundFetchResult))completion { 28 | NSURL *URL = [[NSURL alloc] initWithString:@"https://coinbase.com/api/v1/currencies/exchange_rates"]; 29 | NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL]; 30 | NSURLSessionDownloadTask *task = [[NSURLSession sharedSession] downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { 31 | BTCPreferences *preferences = [BTCPreferences sharedPreferences]; 32 | NSMutableDictionary *current = [[preferences objectForKey:BTCConversionProviderCacheKey] mutableCopy]; 33 | NSDictionary *conversions = current; 34 | 35 | UIBackgroundFetchResult result = UIBackgroundFetchResultFailed; 36 | 37 | if (response && [(NSHTTPURLResponse *)response statusCode] == 200) { 38 | NSData *data = [[NSData alloc] initWithContentsOfURL:location]; 39 | NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingOptions)kNilOptions error:nil]; 40 | 41 | NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; 42 | for (NSString *longKey in JSON) { 43 | if (![longKey hasPrefix:@"btc_to_"]) { 44 | continue; 45 | } 46 | 47 | NSString *key = [[longKey stringByReplacingOccurrencesOfString:@"btc_to_" withString:@""] uppercaseString]; 48 | dictionary[key] = @([JSON[longKey] doubleValue]); 49 | } 50 | 51 | [current removeObjectForKey:@"updatedAt"]; 52 | 53 | result = [current isEqualToDictionary:dictionary] ? UIBackgroundFetchResultNoData : UIBackgroundFetchResultNewData; 54 | 55 | dictionary[@"updatedAt"] = [NSDate date]; 56 | [preferences setObject:dictionary forKey:BTCConversionProviderCacheKey]; 57 | [preferences synchronize]; 58 | 59 | conversions = dictionary; 60 | } 61 | 62 | dispatch_async(dispatch_get_main_queue(), ^{ 63 | if (completion) { 64 | completion(conversions, result); 65 | } 66 | }); 67 | }]; 68 | 69 | [task resume]; 70 | } 71 | 72 | 73 | - (NSDictionary *)latestConversionRates { 74 | return [[BTCPreferences sharedPreferences] objectForKey:BTCConversionProviderCacheKey]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Coins Today/Classes/BTCTodayValueView.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTCTodayValueView.m 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 9/17/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | #import "BTCTodayValueView.h" 10 | 11 | @import NotificationCenter; 12 | 13 | @interface BTCTodayValueView () 14 | @property (nonatomic, readonly) UIVisualEffectView *effectView; 15 | @end 16 | 17 | @implementation BTCTodayValueView 18 | 19 | #pragma mark - Accessors 20 | 21 | @synthesize effectView = _effectView; 22 | 23 | - (UIVisualEffectView *)effectView { 24 | if (!_effectView) { 25 | _effectView = [[UIVisualEffectView alloc] initWithEffect:[UIVibrancyEffect notificationCenterVibrancyEffect]]; 26 | _effectView.translatesAutoresizingMaskIntoConstraints = NO; 27 | } 28 | return _effectView; 29 | } 30 | 31 | 32 | #pragma mark - UIView 33 | 34 | - (instancetype)initWithFrame:(CGRect)frame { 35 | if ((self = [super initWithFrame:frame])) { 36 | self.userInteractionEnabled = NO; 37 | } 38 | return self; 39 | } 40 | 41 | 42 | #pragma mark - BTCValueView 43 | 44 | - (void)setupViews { 45 | self.valueButton.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-Thin" size:40.0]; 46 | self.valueButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; 47 | [self addSubview:self.valueButton]; 48 | 49 | [self.quantityButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 50 | self.quantityButton.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:18.0]; 51 | self.quantityButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; 52 | [self.effectView.contentView addSubview:self.quantityButton]; 53 | [self addSubview:self.effectView]; 54 | } 55 | 56 | 57 | - (void)setupConstraints { 58 | NSDictionary *views = @{ 59 | @"valueButton": self.valueButton, 60 | @"quantityView": self.quantityButton, 61 | @"effectView": self.effectView 62 | }; 63 | 64 | CGFloat verticalSpacing = [self verticalSpacing]; 65 | 66 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[valueButton]-8-|" options:kNilOptions metrics:nil views:views]]; 67 | [self addConstraint:[NSLayoutConstraint constraintWithItem:self.valueButton attribute:NSLayoutAttributeBaseline relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:-verticalSpacing]]; 68 | 69 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[quantityView]|" options:kNilOptions metrics:nil views:views]]; 70 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[quantityView]|" options:kNilOptions metrics:nil views:views]]; 71 | 72 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[effectView]-8-|" options:kNilOptions metrics:nil views:views]]; 73 | [self addConstraint:[NSLayoutConstraint constraintWithItem:self.effectView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.valueButton attribute:NSLayoutAttributeBaseline multiplier:1.0 constant:verticalSpacing / 2.0]]; 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /Coins/Classes/CurrencyPickerTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CurrencyPickerTableViewController.swift 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 12/20/13. 6 | // Copyright (c) 2013-2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoinsKit 11 | 12 | class CurrencyPickerTableViewController: UITableViewController { 13 | 14 | // MARK: - Properties 15 | 16 | let currencies: [String: String] 17 | let order: [String] 18 | var selectedKey: String = BTCPreferences.sharedPreferences().objectForKey(kBTCSelectedCurrencyKey) as String 19 | 20 | 21 | // MARK: - Initializers 22 | 23 | override convenience init() { 24 | self.init(nibName: nil, bundle: nil) 25 | } 26 | 27 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { 28 | let path = NSBundle.mainBundle().pathForResource("currencies", ofType: "json")! 29 | let data = NSData(contentsOfFile: path)! 30 | let JSON = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as [String: AnyObject] 31 | currencies = JSON["currencies"] as [String: String] 32 | order = JSON["order"] as [String] 33 | 34 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 35 | } 36 | 37 | required init(coder aDecoder: NSCoder) { 38 | fatalError("init(coder:) has not been implemented") 39 | } 40 | 41 | 42 | // MARK: - UIViewController 43 | 44 | override func viewDidLoad() { 45 | super.viewDidLoad() 46 | 47 | title = LocalizedString("CURRENCY") 48 | 49 | tableView.registerClass(TableViewCell.self, forCellReuseIdentifier: "Cell") 50 | } 51 | 52 | override func viewWillAppear(animated: Bool) { 53 | super.viewWillAppear(animated) 54 | 55 | if let index = find(order, selectedKey) { 56 | let indexPath = NSIndexPath(forRow: index, inSection: 0) 57 | tableView.selectRowAtIndexPath(indexPath, animated: animated, scrollPosition: .Middle) 58 | } 59 | 60 | navigationController?.setNavigationBarHidden(false, animated: animated) 61 | } 62 | 63 | 64 | // MARK: - UITableViewDataSource 65 | 66 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 67 | return countElements(order) 68 | } 69 | 70 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 71 | let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as TableViewCell 72 | cell.selectionStyle = .Blue 73 | 74 | let key = order[indexPath.row] 75 | 76 | cell.textLabel?.text = currencies[key] 77 | cell.detailTextLabel?.text = key 78 | 79 | return cell 80 | } 81 | 82 | 83 | // MARK: - UITableViewDelegate 84 | 85 | override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 86 | let key = order[indexPath.row] 87 | let preferences = BTCPreferences.sharedPreferences() 88 | preferences.setObject(key, forKey: kBTCSelectedCurrencyKey) 89 | preferences.synchronize() 90 | 91 | NSNotificationCenter.defaultCenter().postNotificationName(kBTCCurrencyDidChangeNotificationName, object: key) 92 | navigationController?.popViewControllerAnimated(true) 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /CoinsKit/Classes/BTCPreferences.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTCPreferences.m 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 9/17/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | #import "BTCPreferences.h" 10 | #import "NSUserDefaults+Coins.h" 11 | 12 | @interface BTCPreferences () 13 | @property (nonatomic) NSDictionary *defaults; 14 | @end 15 | 16 | @implementation BTCPreferences 17 | 18 | #pragma mark - Accessors 19 | 20 | @synthesize defaults = _defaults; 21 | 22 | - (void)registerDefaults:(NSDictionary *)defaults { 23 | self.defaults = defaults; 24 | } 25 | 26 | 27 | - (id)objectForKey:(NSString *)key { 28 | id value = [[self defaultsStore] objectForKey:key]; 29 | if (value) { 30 | return value; 31 | } 32 | return self.defaults[key]; 33 | } 34 | 35 | 36 | - (double)doubleForKey:(NSString *)key { 37 | return [[self objectForKey:key] doubleValue]; 38 | } 39 | 40 | 41 | - (void)setObject:(id)object forKey:(NSString *)key { 42 | [[self defaultsStore] setObject:object forKey:key]; 43 | [[self iCloudStore] setObject:object forKey:key]; 44 | } 45 | 46 | 47 | - (void)removeObjectForKey:(NSString *)key { 48 | [[self defaultsStore] removeObjectForKey:key]; 49 | [[self iCloudStore] removeObjectForKey:key]; 50 | } 51 | 52 | 53 | - (void)synchronize { 54 | [[self iCloudStore] synchronize]; 55 | [[self defaultsStore] synchronize]; 56 | } 57 | 58 | 59 | #pragma mark - Singleton 60 | 61 | + (instancetype)sharedPreferences { 62 | static BTCPreferences *preferences; 63 | static dispatch_once_t onceToken; 64 | dispatch_once(&onceToken, ^{ 65 | preferences = [[self alloc] init]; 66 | }); 67 | return preferences; 68 | } 69 | 70 | 71 | #pragma mark - NSObject 72 | 73 | - (instancetype)init { 74 | if ((self = [super init])) { 75 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(iCloudStoreDidChange:) name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:nil]; 76 | } 77 | return self; 78 | } 79 | 80 | 81 | - (void)dealloc { 82 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 83 | } 84 | 85 | 86 | #pragma mark - Private 87 | 88 | - (NSUserDefaults *)defaultsStore { 89 | return [NSUserDefaults btc_sharedDefaults]; 90 | } 91 | 92 | 93 | - (NSUbiquitousKeyValueStore *)iCloudStore { 94 | return [NSUbiquitousKeyValueStore defaultStore]; 95 | } 96 | 97 | 98 | - (void)iCloudStoreDidChange:(NSNotification *)notification { 99 | NSDictionary *userInfo = [notification userInfo]; 100 | NSNumber *changeReason = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangeReasonKey]; 101 | NSInteger reason = -1; 102 | 103 | if (!changeReason) { 104 | return; 105 | } else { 106 | reason = [changeReason integerValue]; 107 | } 108 | 109 | if (reason == NSUbiquitousKeyValueStoreServerChange || reason == NSUbiquitousKeyValueStoreInitialSyncChange) { 110 | NSArray *changedKeys = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangedKeysKey]; 111 | NSUbiquitousKeyValueStore *store = [self iCloudStore]; 112 | 113 | for (NSString *key in changedKeys) { 114 | [[self defaultsStore] setObject:[store objectForKey:key] forKey:key]; 115 | } 116 | } 117 | } 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /Coins Today/Classes/BTCTodayViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTCTodayViewController.m 3 | // Coins Today 4 | // 5 | // Created by Sam Soffes on 9/17/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | #import "BTCTodayViewController.h" 10 | #import "BTCTodayValueView.h" 11 | 12 | @import CoinsKit; 13 | 14 | @import NotificationCenter; 15 | 16 | @interface BTCTodayViewController () 17 | @property (nonatomic, readonly) BTCValueView *valueView; 18 | @end 19 | 20 | @implementation BTCTodayViewController 21 | 22 | #pragma mark - Accessors 23 | 24 | @synthesize valueView = _valueView; 25 | 26 | - (BTCValueView *)valueView { 27 | if (!_valueView) { 28 | _valueView = [[BTCTodayValueView alloc] init]; 29 | _valueView.translatesAutoresizingMaskIntoConstraints = NO; 30 | _valueView.conversionRates = [[BTCConversionProvider sharedProvider] latestConversionRates]; 31 | } 32 | return _valueView; 33 | } 34 | 35 | 36 | #pragma mark - NSObject 37 | 38 | - (void)dealloc { 39 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 40 | } 41 | 42 | 43 | #pragma mark - UIViewController 44 | 45 | - (void)viewDidLoad { 46 | [super viewDidLoad]; 47 | 48 | [self.view addSubview:self.valueView]; 49 | 50 | NSDictionary *views = @{ @"valueView": self.valueView }; 51 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[valueView]|" options:kNilOptions metrics:nil views:views]]; 52 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[valueView(120)]|" options:kNilOptions metrics:nil views:views]]; 53 | 54 | UIControl *control = [[UIControl alloc] init]; 55 | control.frame = self.view.bounds; 56 | control.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 57 | [control addTarget:self action:@selector(openCoins:) forControlEvents:UIControlEventTouchUpInside]; 58 | [self.view addSubview:control]; 59 | 60 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(update) name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:nil]; 61 | } 62 | 63 | 64 | - (CGSize)preferredContentSize { 65 | return CGSizeMake(self.view.bounds.size.width, 88.0); 66 | } 67 | 68 | 69 | #pragma mark - Actions 70 | 71 | - (void)openCoins:(id)sender { 72 | [self.extensionContext openURL:[NSURL URLWithString:@"coins://open?ref=today"] completionHandler:nil]; 73 | } 74 | 75 | 76 | #pragma mark - Private 77 | 78 | - (void)update { 79 | self.valueView.conversionRates = [[BTCConversionProvider sharedProvider] latestConversionRates]; 80 | } 81 | 82 | 83 | #pragma mark - NCWidgetProviding 84 | 85 | - (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler { 86 | [[BTCConversionProvider sharedProvider] getConversionRates:^(NSDictionary *conversionRates, UIBackgroundFetchResult result) { 87 | [self update]; 88 | 89 | if (completionHandler) { 90 | completionHandler((NCUpdateResult)result); 91 | } 92 | }]; 93 | } 94 | 95 | 96 | - (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets { 97 | defaultMarginInsets.top = 8.0; 98 | defaultMarginInsets.bottom = 8.0; 99 | defaultMarginInsets.left += 2.0; 100 | return defaultMarginInsets; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /Coins/Classes/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 11/25/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoinsKit 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | // MARK: - Properties 16 | 17 | lazy var window: UIWindow = { 18 | let window = UIWindow(frame: UIScreen.mainScreen().bounds) 19 | window.backgroundColor = UIColor.blackColor() 20 | window.rootViewController = UINavigationController(rootViewController: BTCValueViewController()) 21 | return window 22 | }() 23 | 24 | 25 | // MARK: - Private 26 | 27 | private func configureAnalytics() { 28 | #if !DEBUG 29 | // Hockey 30 | BITHockeyManager.sharedHockeyManager().configureWithIdentifier("d0d82a50debc14c4fde0cb3430893bd6") 31 | BITHockeyManager.sharedHockeyManager().startManager() 32 | BITHockeyManager.sharedHockeyManager().authenticator.authenticateInstallation() 33 | 34 | // Mixpanel 35 | let mixpanel = Mixpanel.sharedInstanceWithToken("a487667944fcb1107bcaa025b3ca744c") 36 | mixpanel.showNetworkActivityIndicator = false 37 | #endif 38 | } 39 | 40 | private func configureAppearance() { 41 | let navigationBar = UINavigationBar.appearance() 42 | navigationBar.barTintColor = CoinsKit.blueColor 43 | navigationBar.tintColor = UIColor(white: 1, alpha: 0.5) 44 | navigationBar.titleTextAttributes = [ 45 | NSForegroundColorAttributeName: UIColor.whiteColor(), 46 | NSFontAttributeName: UIFont(name: "Avenir-Heavy", size: 20)! 47 | ] 48 | } 49 | 50 | 51 | private func configureDefaults() { 52 | let standardDefaults = NSUserDefaults.standardUserDefaults() 53 | standardDefaults.registerDefaults([ 54 | kBTCAutomaticallyRefreshKey: true, 55 | kBTCDisableSleepKey: false, 56 | kBTCControlsHiddenKey: false, 57 | "BTCMigrated": false 58 | ]) 59 | 60 | let preferences = BTCPreferences.sharedPreferences() 61 | preferences.registerDefaults([ 62 | kBTCSelectedCurrencyKey: "USD", 63 | kBTCNumberOfCoinsKey: 0 64 | ]) 65 | 66 | if standardDefaults.boolForKey("BTCMigrated") { 67 | let keys = [kBTCSelectedCurrencyKey, kBTCNumberOfCoinsKey] 68 | for key in keys { 69 | if let value = standardDefaults.objectForKey(key) as? NSCoding { 70 | preferences.setObject(value, forKey: key) 71 | } 72 | } 73 | preferences.synchronize() 74 | 75 | standardDefaults.setBool(true, forKey: "BTCMigrated") 76 | standardDefaults.synchronize() 77 | } 78 | } 79 | 80 | 81 | // MARK: - UIApplicationDelegate 82 | 83 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool { 84 | configureAnalytics() 85 | 86 | application.statusBarStyle = .LightContent 87 | application.setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum) 88 | 89 | configureAppearance() 90 | configureDefaults() 91 | 92 | window.makeKeyAndVisible() 93 | 94 | dispatch_async(dispatch_get_main_queue()) { 95 | let info = NSBundle.mainBundle().infoDictionary! 96 | let shortVersion = (info["CFBundleShortVersionString"] as String) 97 | let version = (info["CFBundleVersion"] as String) 98 | let versionString = "\(shortVersion) (\(version))" 99 | let standardDefaults = NSUserDefaults.standardUserDefaults() 100 | standardDefaults.setObject(versionString, forKey: "BTCVersion") 101 | standardDefaults.synchronize() 102 | } 103 | 104 | return true 105 | } 106 | 107 | func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { 108 | BTCConversionProvider.sharedProvider().getConversionRates { conversionRate, result in 109 | completionHandler(result) 110 | } 111 | } 112 | 113 | func applicationDidBecomeActive(application: UIApplication) { 114 | #if !DEBUG 115 | Mixpanel.sharedInstance().track("Active") 116 | #endif 117 | } 118 | 119 | func applicationWillResignActive(application: UIApplication) { 120 | #if !DEBUG 121 | Mixpanel.sharedInstance().flush() 122 | #endif 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /CoinsKit/Classes/BTCValueView.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTCValueView.m 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 4/23/14. 6 | // Copyright (c) 2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | #import "BTCValueView.h" 10 | #import "BTCPreferences.h" 11 | #import "BTCDefines.h" 12 | 13 | @implementation BTCValueView 14 | 15 | #pragma mark - Accessors 16 | 17 | @synthesize conversionRates = _conversionRates; 18 | @synthesize valueButton = _valueButton; 19 | @synthesize quantityButton = _quantityButton; 20 | 21 | - (void)setConversionRates:(NSDictionary *)conversionRates { 22 | _conversionRates = conversionRates; 23 | 24 | static NSNumberFormatter *currencyFormatter = nil; 25 | static dispatch_once_t currencyOnceToken; 26 | dispatch_once(¤cyOnceToken, ^{ 27 | currencyFormatter = [[NSNumberFormatter alloc] init]; 28 | currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle; 29 | }); 30 | 31 | BTCPreferences *preferences = [BTCPreferences sharedPreferences]; 32 | currencyFormatter.currencyCode = [preferences objectForKey:kBTCSelectedCurrencyKey]; 33 | double value = [[preferences objectForKey:kBTCNumberOfCoinsKey] doubleValue] * [conversionRates[currencyFormatter.currencyCode] doubleValue]; 34 | [self.valueButton setTitle:[currencyFormatter stringFromNumber:@(value)] forState:UIControlStateNormal]; 35 | 36 | static NSNumberFormatter *numberFormatter = nil; 37 | static dispatch_once_t numberOnceToken; 38 | dispatch_once(&numberOnceToken, ^{ 39 | numberFormatter = [[NSNumberFormatter alloc] init]; 40 | numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; 41 | numberFormatter.currencySymbol = @""; 42 | numberFormatter.minimumFractionDigits = 0; 43 | numberFormatter.maximumFractionDigits = 10; 44 | numberFormatter.roundingMode = NSNumberFormatterRoundDown; 45 | }); 46 | 47 | NSNumber *number = [preferences objectForKey:kBTCNumberOfCoinsKey]; 48 | 49 | NSString *title = [numberFormatter stringFromNumber:number]; 50 | [self.quantityButton setTitle:[NSString stringWithFormat:@"%@ BTC", title ? title : @"0"] forState:UIControlStateNormal]; 51 | } 52 | 53 | - (UIButton *)valueButton { 54 | if (!_valueButton) { 55 | _valueButton = [[UIButton alloc] init]; 56 | _valueButton.translatesAutoresizingMaskIntoConstraints = NO; 57 | _valueButton.titleLabel.font = [UIFont fontWithName:@"Avenir-Heavy" size:UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? 80.0 : 50.0]; 58 | _valueButton.titleLabel.adjustsFontSizeToFitWidth = YES; 59 | _valueButton.titleLabel.textAlignment = NSTextAlignmentCenter; 60 | [_valueButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 61 | } 62 | return _valueButton; 63 | } 64 | 65 | 66 | - (UIButton *)quantityButton { 67 | if (!_quantityButton) { 68 | _quantityButton = [[UIButton alloc] init]; 69 | _quantityButton.translatesAutoresizingMaskIntoConstraints = NO; 70 | _quantityButton.titleLabel.font = [UIFont fontWithName:@"Avenir-Light" size:UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? 30.0 : 20.0]; 71 | [_quantityButton setTitleColor:[UIColor colorWithWhite:1.0 alpha:0.5f] forState:UIControlStateNormal]; 72 | } 73 | return _quantityButton; 74 | } 75 | 76 | 77 | #pragma mark - UIView 78 | 79 | - (instancetype)initWithFrame:(CGRect)frame { 80 | if ((self = [super initWithFrame:frame])) { 81 | self.translatesAutoresizingMaskIntoConstraints = NO; 82 | self.backgroundColor = [UIColor clearColor]; 83 | 84 | [self setupViews]; 85 | [self setupConstraints]; 86 | } 87 | return self; 88 | } 89 | 90 | 91 | #pragma mark - Configuration 92 | 93 | - (CGFloat)verticalSpacing { 94 | return 16.0; 95 | } 96 | 97 | 98 | - (void)setupViews { 99 | [self addSubview:self.valueButton]; 100 | [self addSubview:self.quantityButton]; 101 | } 102 | 103 | 104 | #pragma mark - Private 105 | 106 | - (void)setupConstraints { 107 | NSDictionary *views = @{ 108 | @"valueButton": self.valueButton, 109 | @"quantityView": self.quantityButton 110 | }; 111 | 112 | CGFloat verticalSpacing = [self verticalSpacing]; 113 | 114 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[valueButton]-|" options:kNilOptions metrics:nil views:views]]; 115 | [self addConstraint:[NSLayoutConstraint constraintWithItem:self.valueButton attribute:NSLayoutAttributeBaseline relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:-verticalSpacing]]; 116 | 117 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[quantityView]-|" options:kNilOptions metrics:nil views:views]]; 118 | [self addConstraint:[NSLayoutConstraint constraintWithItem:self.quantityButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.valueButton attribute:NSLayoutAttributeBaseline multiplier:1.0 constant:verticalSpacing / 2.0]]; 119 | } 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /Coins/Resources/currencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "currencies": { 3 | "AED": "United Arab Emirates dirham", 4 | "AFN": "Afghan afghani", 5 | "ALL": "Albanian lek", 6 | "AMD": "Armenian dram", 7 | "ANG": "Netherlands Antillean guilder", 8 | "AOA": "Angolan kwanza", 9 | "ARS": "Argentine peso", 10 | "AUD": "Australian dollar", 11 | "AWG": "Aruban florin", 12 | "AZN": "Azerbaijani manat", 13 | "BAM": "Bosnia and Herzegovina convertible mark", 14 | "BBD": "Barbadian dollar", 15 | "BDT": "Bangladeshi taka", 16 | "BGN": "Bulgarian lev", 17 | "BHD": "Bahraini dinar", 18 | "BIF": "Burundian franc", 19 | "BMD": "Bermudian dollar", 20 | "BND": "Brunei dollar", 21 | "BOB": "Bolivian boliviano", 22 | "BRL": "Brazilian real", 23 | "BSD": "Bahamian dollar", 24 | "BTN": "Bhutanese ngultrum", 25 | "BWP": "Botswana pula", 26 | "BYR": "Belarusian ruble", 27 | "BZD": "Belize dollar", 28 | "CAD": "Canadian dollar", 29 | "CDF": "Congolese franc", 30 | "CHF": "Swiss franc", 31 | "CLP": "Chilean peso", 32 | "CNY": "Chinese yuan", 33 | "COP": "Colombian peso", 34 | "CRC": "Costa Rican col\u00f3n", 35 | "CUP": "Cuban peso", 36 | "CVE": "Cape Verdean escudo", 37 | "CZK": "Czech koruna", 38 | "DJF": "Djiboutian franc", 39 | "DKK": "Danish krone", 40 | "DOP": "Dominican peso", 41 | "DZD": "Algerian dinar", 42 | "EGP": "Egyptian pound", 43 | "ETB": "Ethiopian birr", 44 | "EUR": "Euro", 45 | "FJD": "Fijian dollar", 46 | "FKP": "Falkland Islands pound", 47 | "GBP": "Pound sterling", 48 | "GEL": "Georgian lari", 49 | "GHS": "Ghana cedi", 50 | "GIP": "Gibraltar pound", 51 | "GMD": "Gambian dalasi", 52 | "GNF": "Guinean franc", 53 | "GTQ": "Guatemalan quetzal", 54 | "GYD": "Guyanese dollar", 55 | "HKD": "Hong Kong dollar", 56 | "HNL": "Honduran lempira", 57 | "HRK": "Croatian kuna", 58 | "HTG": "Haitian gourde", 59 | "HUF": "Hungarian forint", 60 | "IDR": "Indonesian rupiah", 61 | "ILS": "Israeli new shekel", 62 | "INR": "Indian rupee", 63 | "IQD": "Iraqi dinar", 64 | "IRR": "Iranian rial", 65 | "ISK": "Icelandic kr\u00f3na", 66 | "JEP": "Jersey pound", 67 | "JMD": "Jamaican dollar", 68 | "JOD": "Jordanian dinar", 69 | "JPY": "Japanese yen", 70 | "KES": "Kenyan shilling", 71 | "KGS": "Kyrgyzstani som", 72 | "KHR": "Cambodian riel", 73 | "KMF": "Comorian franc", 74 | "KPW": "North Korean won", 75 | "KRW": "South Korean won", 76 | "KWD": "Kuwaiti dinar", 77 | "KYD": "Cayman Islands dollar", 78 | "KZT": "Kazakhstani tenge", 79 | "LAK": "Lao kip", 80 | "LBP": "Lebanese pound", 81 | "LKR": "Sri Lankan rupee", 82 | "LRD": "Liberian dollar", 83 | "LSL": "Lesotho loti", 84 | "LTL": "Lithuanian litas", 85 | "LVL": "Latvian lats", 86 | "LYD": "Libyan dinar", 87 | "MAD": "Moroccan dirham", 88 | "MDL": "Moldovan leu", 89 | "MGA": "Malagasy ariary", 90 | "MKD": "Macedonian denar", 91 | "MMK": "Burmese kyat", 92 | "MNT": "Mongolian t\u00f6gr\u00f6g", 93 | "MOP": "Macanese pataca", 94 | "MRO": "Mauritanian ouguiya", 95 | "MUR": "Mauritian rupee", 96 | "MVR": "Maldivian rufiyaa", 97 | "MWK": "Malawian kwacha", 98 | "MXN": "Mexican peso", 99 | "MYR": "Malaysian ringgit", 100 | "MZN": "Mozambican metical", 101 | "NAD": "Namibian dollar", 102 | "NGN": "Nigerian naira", 103 | "NIO": "Nicaraguan c\u00f3rdoba", 104 | "NOK": "Norwegian krone", 105 | "NPR": "Nepalese rupee", 106 | "NZD": "New Zealand dollar", 107 | "OMR": "Omani rial", 108 | "PAB": "Panamanian balboa", 109 | "PEN": "Peruvian nuevo sol", 110 | "PGK": "Papua New Guinean kina", 111 | "PHP": "Philippine peso", 112 | "PKR": "Pakistani rupee", 113 | "PLN": "Polish z\u0142oty", 114 | "PYG": "Paraguayan guaran\u00ed", 115 | "QAR": "Qatari riyal", 116 | "RMB": "Renminbi", 117 | "RON": "Romanian leu", 118 | "RSD": "Serbian dinar", 119 | "RUB": "Russian ruble", 120 | "RWF": "Rwandan franc", 121 | "SAR": "Saudi riyal", 122 | "SBD": "Solomon Islands dollar", 123 | "SCR": "Seychellois rupee", 124 | "SDG": "Sudanese pound", 125 | "SEK": "Swedish krona", 126 | "SGD": "Singapore dollar", 127 | "SHP": "Saint Helena pound", 128 | "SLL": "Sierra Leonean leone", 129 | "SOS": "Somali shilling", 130 | "SRD": "Surinamese dollar", 131 | "STD": "S\u00e3o Tom\u00e9 and Pr\u00edncipe dobra", 132 | "SVC": "Salvadoran col\u00f3n", 133 | "SYP": "Syrian pound", 134 | "SZL": "Swazi lilangeni", 135 | "THB": "Thai baht", 136 | "TJS": "Tajikistani somoni", 137 | "TMT": "Turkmenistan manat", 138 | "TND": "Tunisian dinar", 139 | "TRY": "Turkish lira", 140 | "TTD": "Trinidad and Tobago dollar", 141 | "TWD": "New Taiwan dollar", 142 | "TZS": "Tanzanian shilling", 143 | "UAH": "Ukrainian hryvnia", 144 | "UGX": "Ugandan shilling", 145 | "USD": "United States dollar", 146 | "UYU": "Uruguayan peso", 147 | "UZS": "Uzbekistani som", 148 | "VEF": "Venezuelan bol\u00edvar", 149 | "VND": "Vietnamese \u0111\u1ed3ng", 150 | "VUV": "Vanuatu vatu", 151 | "WST": "Samoan t\u0101l\u0101", 152 | "XAF": "Central African CFA franc", 153 | "XCD": "East Caribbean dollar", 154 | "XOF": "West African CFA franc", 155 | "XPF": "CFP franc", 156 | "YER": "Yemeni rial", 157 | "ZAR": "South African rand", 158 | "ZMW": "Zambian kwacha", 159 | "ZWL": "Zimbabwean dollar" 160 | }, 161 | "order": [ 162 | "USD", 163 | "GBP", 164 | "HKD", 165 | "CAD", 166 | "EUR", 167 | "AUD", 168 | "AED", 169 | "AFN", 170 | "ALL", 171 | "AMD", 172 | "ANG", 173 | "AOA", 174 | "ARS", 175 | "AWG", 176 | "AZN", 177 | "BAM", 178 | "BBD", 179 | "BDT", 180 | "BGN", 181 | "BHD", 182 | "BIF", 183 | "BMD", 184 | "BND", 185 | "BOB", 186 | "BRL", 187 | "BSD", 188 | "BTN", 189 | "BWP", 190 | "BYR", 191 | "BZD", 192 | "CDF", 193 | "CHF", 194 | "CLP", 195 | "CNY", 196 | "COP", 197 | "CRC", 198 | "CUP", 199 | "CVE", 200 | "CZK", 201 | "DJF", 202 | "DKK", 203 | "DOP", 204 | "DZD", 205 | "EGP", 206 | "ETB", 207 | "FJD", 208 | "FKP", 209 | "GEL", 210 | "GHS", 211 | "GIP", 212 | "GMD", 213 | "GNF", 214 | "GTQ", 215 | "GYD", 216 | "HNL", 217 | "HRK", 218 | "HTG", 219 | "HUF", 220 | "IDR", 221 | "ILS", 222 | "INR", 223 | "IQD", 224 | "IRR", 225 | "ISK", 226 | "JMD", 227 | "JOD", 228 | "JPY", 229 | "KES", 230 | "KGS", 231 | "KHR", 232 | "KMF", 233 | "KPW", 234 | "KRW", 235 | "KWD", 236 | "KYD", 237 | "KZT", 238 | "LAK", 239 | "LBP", 240 | "LKR", 241 | "LRD", 242 | "LSL", 243 | "LTL", 244 | "LVL", 245 | "LYD", 246 | "MAD", 247 | "MDL", 248 | "MGA", 249 | "MKD", 250 | "MMK", 251 | "MNT", 252 | "MOP", 253 | "MRO", 254 | "MUR", 255 | "MVR", 256 | "MWK", 257 | "MXN", 258 | "MYR", 259 | "MZN", 260 | "NAD", 261 | "NGN", 262 | "NIO", 263 | "NOK", 264 | "NPR", 265 | "NZD", 266 | "OMR", 267 | "PAB", 268 | "PEN", 269 | "PGK", 270 | "PHP", 271 | "PKR", 272 | "PLN", 273 | "PYG", 274 | "QAR", 275 | "RON", 276 | "RSD", 277 | "RUB", 278 | "RWF", 279 | "SAR", 280 | "SBD", 281 | "SCR", 282 | "SDG", 283 | "SEK", 284 | "SGD", 285 | "SHP", 286 | "SLL", 287 | "SOS", 288 | "SRD", 289 | "STD", 290 | "SVC", 291 | "SYP", 292 | "SZL", 293 | "THB", 294 | "TJS", 295 | "TND", 296 | "TRY", 297 | "TTD", 298 | "TWD", 299 | "TZS", 300 | "UAH", 301 | "UGX", 302 | "UYU", 303 | "UZS", 304 | "VEF", 305 | "VND", 306 | "VUV", 307 | "WST", 308 | "XAF", 309 | "XCD", 310 | "XOF", 311 | "XPF", 312 | "YER", 313 | "ZAR", 314 | "ZWL" 315 | ] 316 | } 317 | -------------------------------------------------------------------------------- /Coins/Classes/ValueViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ValueViewController.swift 3 | // Coins 4 | // 5 | // Created by Sam Soffes on 12/20/13. 6 | // Copyright (c) 2013-2014 Nothing Magical, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoinsKit 11 | import GradientView 12 | 13 | class BTCValueViewController: UIViewController, UITextFieldDelegate, SSPullToRefreshViewDelegate { 14 | 15 | // MARK: - Properties 16 | 17 | let flapsView: GradientView = { 18 | let view = GradientView() 19 | view.autoresizingMask = .FlexibleWidth | .FlexibleHeight 20 | view.colors = [CoinsKit.blueColor, CoinsKit.purpleColor] 21 | view.locations = [0.5, 0.51] 22 | return view 23 | }() 24 | 25 | let scrollView: UIScrollView = { 26 | let view = UIScrollView() 27 | view.setTranslatesAutoresizingMaskIntoConstraints(false) 28 | view.showsHorizontalScrollIndicator = false 29 | view.showsVerticalScrollIndicator = false 30 | view.alwaysBounceVertical = true 31 | return view 32 | }() 33 | 34 | var pullToRefresh: SSPullToRefreshView! 35 | 36 | let backgroundView: GradientView = { 37 | let view = GradientView() 38 | view.setTranslatesAutoresizingMaskIntoConstraints(false) 39 | view.colors = [CoinsKit.blueColor, CoinsKit.purpleColor] 40 | return view 41 | }() 42 | 43 | let valueView = BTCValueView() 44 | 45 | let updateButton: TickingButton = { 46 | let view = TickingButton() 47 | view.setTranslatesAutoresizingMaskIntoConstraints(false) 48 | view.setTitleColor(UIColor(white: 1, alpha: 0.3), forState: .Normal) 49 | view.setTitleColor(UIColor(white: 1, alpha: 0.8), forState: .Highlighted) 50 | view.titleLabel?.font = UIFont(name: "Avenir-Light", size: 12) 51 | view.titleLabel?.textAlignment = .Center 52 | return view 53 | }() 54 | 55 | let textField: TextField = { 56 | let view = TextField() 57 | view.setTranslatesAutoresizingMaskIntoConstraints(false) 58 | view.alpha = 0 59 | return view 60 | }() 61 | 62 | let doneButton: UIButton = { 63 | let view = UIButton() 64 | view.setTranslatesAutoresizingMaskIntoConstraints(false) 65 | view.titleLabel?.font = UIFont(name: "Avenir-Light", size: 14) 66 | view.alpha = 0 67 | view.setTitleColor(UIColor(white: 1, alpha: 0.5), forState: .Normal) 68 | view.setTitleColor(UIColor.whiteColor(), forState: .Highlighted) 69 | view.setTitle(LocalizedString("DONE"), forState: .Normal) 70 | view.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) 71 | view.layer.borderColor = UIColor(white: 1, alpha: 0.5).CGColor 72 | view.layer.borderWidth = 1 73 | view.layer.cornerRadius = 5 74 | return view 75 | }() 76 | 77 | var currencyPopover: UIPopoverController? 78 | 79 | var controlsHidden: Bool = false 80 | 81 | var loading: Bool = false { 82 | didSet { 83 | UIApplication.sharedApplication().networkActivityIndicatorVisible = loading 84 | 85 | if loading { 86 | updateButton.format = LocalizedString("UPDATING") 87 | pullToRefresh.startLoading() 88 | } else { 89 | updateButton.format = LocalizedString("UPDATED_FORMAT") 90 | pullToRefresh.finishLoading() 91 | } 92 | } 93 | } 94 | 95 | var autoRefreshing: Bool = false { 96 | didSet { 97 | if autoRefreshing && autoRefreshTimer == nil { 98 | let timer = NSTimer(timeInterval: 60, target: self, selector: "refresh:", userInfo: nil, repeats: true) 99 | NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes) 100 | autoRefreshTimer = timer 101 | } else { 102 | autoRefreshTimer?.invalidate() 103 | } 104 | } 105 | } 106 | 107 | var autoRefreshTimer: NSTimer? 108 | 109 | var doneButtonTopConstraint: NSLayoutConstraint! 110 | 111 | var textFieldTopConstraint: NSLayoutConstraint! 112 | 113 | var keyboardFrame: CGRect = CGRectZero 114 | 115 | 116 | // MARK: - Initializers 117 | 118 | deinit { 119 | NSNotificationCenter.defaultCenter().removeObserver(self) 120 | } 121 | 122 | 123 | // MARK: - UIViewController 124 | 125 | override func viewDidLoad() { 126 | super.viewDidLoad() 127 | 128 | automaticallyAdjustsScrollViewInsets = false 129 | navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil) 130 | 131 | textField.delegate = self 132 | doneButton.addTarget(self, action: "toggleControls", forControlEvents: .TouchUpInside) 133 | valueView.valueButton.addTarget(self, action: "pickCurrency", forControlEvents: .TouchUpInside) 134 | valueView.quantityButton.addTarget(self, action: "startEditing", forControlEvents: .TouchUpInside) 135 | updateButton.addTarget(self, action: "refresh", forControlEvents: .TouchUpInside) 136 | 137 | flapsView.frame = view.bounds 138 | view.addSubview(flapsView) 139 | 140 | view.addSubview(scrollView) 141 | self.pullToRefresh = PullToRefreshView(scrollView: scrollView, delegate: self) 142 | 143 | scrollView.addSubview(backgroundView) 144 | backgroundView.addSubview(valueView) 145 | view.addSubview(updateButton) 146 | view.addSubview(textField) 147 | view.addSubview(doneButton) 148 | 149 | setupViewConstraints() 150 | 151 | let tap = UITapGestureRecognizer(target: self, action: "toggleControls") 152 | scrollView.addGestureRecognizer(tap) 153 | 154 | let notificationCenter = NSNotificationCenter.defaultCenter() 155 | notificationCenter.addObserver(self, selector: "textFieldDidChange:", name: UITextFieldTextDidChangeNotification, object: nil) 156 | notificationCenter.addObserver(self, selector: "updateTimerPaused", name: UIApplicationDidEnterBackgroundNotification, object: nil) 157 | notificationCenter.addObserver(self, selector: "updateTimerPaused", name: UIApplicationDidBecomeActiveNotification, object: nil) 158 | notificationCenter.addObserver(self, selector: "keyboardWillChangeFrame:", name: UIKeyboardWillChangeFrameNotification, object: nil) 159 | 160 | notificationCenter.addObserver(self, selector: "update", name: kBTCCurrencyDidChangeNotificationName, object: nil) 161 | notificationCenter.addObserver(self, selector: "update", name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification, object: nil) 162 | update() 163 | 164 | notificationCenter.addObserver(self, selector: "refresh", name: UIApplicationDidBecomeActiveNotification, object: nil) 165 | refresh() 166 | 167 | notificationCenter.addObserver(self, selector: "preferencesDidChange", name: NSUserDefaultsDidChangeNotification, object: nil) 168 | preferencesDidChange() 169 | 170 | setControlsHidden(NSUserDefaults.standardUserDefaults().boolForKey(kBTCControlsHiddenKey), animated: false) 171 | } 172 | 173 | override func viewWillAppear(animated: Bool) { 174 | super.viewWillAppear(animated) 175 | 176 | update() 177 | navigationController?.setNavigationBarHidden(true, animated: animated) 178 | 179 | updateButton.startTicking() 180 | autoRefreshing = NSUserDefaults.standardUserDefaults().boolForKey(kBTCAutomaticallyRefreshKey) 181 | 182 | if BTCPreferences.sharedPreferences().doubleForKey(kBTCNumberOfCoinsKey) == 0.0 { 183 | setEditing(true, animated: animated) 184 | } 185 | } 186 | 187 | override func viewDidDisappear(animated: Bool) { 188 | super.viewDidDisappear(animated) 189 | updateButton.stopTicking() 190 | autoRefreshing = false 191 | } 192 | 193 | override func setEditing(editing: Bool, animated: Bool) { 194 | super.setEditing(editing, animated: animated) 195 | 196 | if editing { 197 | view.addConstraint(doneButtonTopConstraint) 198 | view.addConstraint(textFieldTopConstraint) 199 | textField.becomeFirstResponder() 200 | } else { 201 | view.removeConstraint(doneButtonTopConstraint) 202 | view.removeConstraint(textFieldTopConstraint) 203 | textField.resignFirstResponder() 204 | BTCPreferences.sharedPreferences().synchronize() 205 | } 206 | 207 | let animations: () -> Void = { 208 | self.textField.alpha = editing ? 1 : 0 209 | self.doneButton.alpha = self.textField.alpha 210 | self.valueView.valueButton.alpha = editing ? 0.0 : 1.0 211 | self.valueView.quantityButton.alpha = self.valueView.valueButton.alpha 212 | } 213 | 214 | if (animated) { 215 | UIView.animateWithDuration(0.3, animations: animations) 216 | UIView.animateWithDuration(0.8, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 1, options: nil, animations: { () -> Void in 217 | self.view.layoutIfNeeded() 218 | }, completion: nil) 219 | } else { 220 | animations() 221 | } 222 | } 223 | 224 | 225 | override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) { 226 | super.didRotateFromInterfaceOrientation(fromInterfaceOrientation) 227 | 228 | currencyPopover?.dismissPopoverAnimated(true) 229 | updateDoneButtonTopLayoutConstraint() 230 | } 231 | 232 | 233 | // MARK - Actions 234 | 235 | func refresh() { 236 | if loading { 237 | return 238 | } 239 | 240 | loading = true 241 | 242 | BTCConversionProvider.sharedProvider().getConversionRates() { conversionRates, result in 243 | self.update() 244 | self.loading = false 245 | } 246 | } 247 | 248 | func pickCurrency() { 249 | let viewController = CurrencyPickerTableViewController() 250 | 251 | if CoinsKit.isPad { 252 | let navigationController = UINavigationController(rootViewController: viewController) 253 | let popover = UIPopoverController(contentViewController: navigationController) 254 | popover.presentPopoverFromRect(valueView.valueButton.frame, inView: view, permittedArrowDirections: .Down, animated: true) 255 | self.currencyPopover = popover 256 | return 257 | } 258 | 259 | self.navigationController?.pushViewController(viewController, animated: true) 260 | } 261 | 262 | func toggleControls() { 263 | if editing { 264 | setEditing(false, animated: true) 265 | return 266 | } 267 | 268 | setControlsHidden(!controlsHidden, animated: true) 269 | } 270 | 271 | func startEditing() { 272 | setEditing(true, animated: true) 273 | } 274 | 275 | 276 | // MARK: - Private 277 | 278 | private func setupViewConstraints() { 279 | doneButtonTopConstraint = NSLayoutConstraint(item: doneButton, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1, constant: 0) 280 | doneButtonTopConstraint.priority = LayoutPriorityRequired 281 | updateDoneButtonTopLayoutConstraint() 282 | 283 | textFieldTopConstraint = NSLayoutConstraint(item: textField, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: 0) 284 | textFieldTopConstraint.priority = LayoutPriorityRequired 285 | 286 | let views = [ 287 | "scrollView": scrollView, 288 | "backgroundView": backgroundView, 289 | "valueView": valueView, 290 | "updateButton": updateButton, 291 | "textField": textField, 292 | "doneButton": doneButton 293 | ] 294 | 295 | view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[scrollView]|", options: nil, metrics: nil, views: views)) 296 | view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView]|", options: nil, metrics: nil, views: views)) 297 | 298 | var attributes: [NSLayoutAttribute] = [.Top, .Left, .Bottom, .Right] 299 | for attribute in attributes { 300 | view.addConstraint(NSLayoutConstraint(item: backgroundView, attribute: attribute, relatedBy: .Equal, toItem: view, attribute: attribute, multiplier: 1, constant: 0)) 301 | view.addConstraint(NSLayoutConstraint(item: valueView, attribute: attribute, relatedBy: .Equal, toItem: view, attribute: attribute, multiplier: 1, constant: 0)) 302 | } 303 | 304 | view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|-[updateButton]-|", options: nil, metrics: nil, views: views)) 305 | view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[updateButton]-10-|", options: nil, metrics: nil, views: views)) 306 | 307 | let doneBottomConstraint = NSLayoutConstraint(item: doneButton, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1, constant: 0) 308 | doneBottomConstraint.priority = LayoutPriorityDefaultLow 309 | view.addConstraint(doneBottomConstraint) 310 | 311 | view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("[doneButton]-|", options: nil, metrics: nil, views: views)) 312 | 313 | view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|-(20@500)-[textField(<=500@600)]-(20@500)-|", options: nil, metrics: nil, views: views)) 314 | 315 | let weakTextFieldTopConstraint = NSLayoutConstraint(item: textField, attribute: .Top, relatedBy: .Equal, toItem: valueView.valueButton, attribute: .Bottom, multiplier: 1, constant: 0) 316 | weakTextFieldTopConstraint.priority = LayoutPriorityDefaultLow 317 | view.addConstraint(weakTextFieldTopConstraint) 318 | 319 | view.addConstraint(NSLayoutConstraint(item: textField, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0)) 320 | 321 | let requiredTextFieldTopConstraint = NSLayoutConstraint(item: textField, attribute: .Top, relatedBy: .GreaterThanOrEqual, toItem: doneButton, attribute: .Bottom, multiplier: 1, constant: 20) 322 | requiredTextFieldTopConstraint.priority = LayoutPriorityRequired 323 | view.addConstraint(requiredTextFieldTopConstraint) 324 | } 325 | 326 | func textFieldDidChange(notification: NSNotification?) { 327 | var string = textField.text ?? "" 328 | string = string.stringByReplacingOccurrencesOfString(",", withString: ".") 329 | 330 | let preferences = BTCPreferences.sharedPreferences() 331 | preferences.setObject(strtod(string, nil), forKey: kBTCNumberOfCoinsKey) 332 | preferences.synchronize() 333 | 334 | update() 335 | } 336 | 337 | func update() { 338 | if CoinsKit.isPad { 339 | currencyPopover?.dismissPopoverAnimated(true) 340 | } 341 | 342 | if let conversionRates = BTCConversionProvider.sharedProvider().latestConversionRates() { 343 | updateButton.date = conversionRates["updatedAt"] as? NSDate 344 | valueView.conversionRates = conversionRates 345 | } 346 | 347 | if !textField.editing { 348 | let number = BTCPreferences.sharedPreferences().objectForKey(kBTCNumberOfCoinsKey).description 349 | textField.text = number == "0" ? nil : number 350 | } 351 | } 352 | 353 | func preferencesDidChange() { 354 | UIApplication.sharedApplication().idleTimerDisabled = NSUserDefaults.standardUserDefaults().boolForKey(kBTCDisableSleepKey) 355 | updateTimerPaused() 356 | } 357 | 358 | private func setControlsHidden(controlsHidden: Bool, animated: Bool) { 359 | let application = UIApplication.sharedApplication() 360 | let statusBarAnimation: UIStatusBarAnimation = animated ? .Fade : .None 361 | 362 | if self.controlsHidden == controlsHidden { 363 | if application.statusBarHidden != controlsHidden { 364 | application.setStatusBarHidden(controlsHidden, withAnimation: statusBarAnimation) 365 | } 366 | return 367 | } 368 | 369 | self.controlsHidden = controlsHidden 370 | 371 | application.setStatusBarHidden(controlsHidden, withAnimation: statusBarAnimation) 372 | updateDoneButtonTopLayoutConstraint() 373 | 374 | let userDefaults = NSUserDefaults.standardUserDefaults() 375 | userDefaults.setBool(controlsHidden, forKey: kBTCControlsHiddenKey) 376 | userDefaults.synchronize() 377 | 378 | let animations: () -> Void = { 379 | self.updateButton.alpha = controlsHidden ? 0 : 1 380 | self.view.layoutIfNeeded() 381 | } 382 | 383 | if animated { 384 | UIView.animateWithDuration(0.6, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .AllowUserInteraction, animations: animations, completion: nil) 385 | } else { 386 | animations() 387 | } 388 | } 389 | 390 | func updateTimerPaused() { 391 | let isActive = UIApplication.sharedApplication().applicationState == .Active 392 | autoRefreshing = isActive && NSUserDefaults.standardUserDefaults().boolForKey(kBTCAutomaticallyRefreshKey) 393 | } 394 | 395 | func keyboardWillChangeFrame(notification: NSNotification?) { 396 | if let value = notification?.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue { 397 | keyboardFrame = value.CGRectValue() 398 | textFieldTopConstraint.constant = min(keyboardFrame.size.height, keyboardFrame.size.width) / -2.0 399 | } 400 | } 401 | 402 | private func updateDoneButtonTopLayoutConstraint() { 403 | var constant: CGFloat = 10.0 404 | 405 | if !controlsHidden { 406 | constant += 20.0 407 | } 408 | 409 | if CoinsKit.isPad || UIInterfaceOrientationIsPortrait(self.interfaceOrientation) { 410 | constant += 6.0 411 | } 412 | 413 | doneButtonTopConstraint.constant = constant 414 | } 415 | 416 | 417 | // MARK: - UITextFieldDelegate 418 | 419 | func textFieldShouldReturn(textField: UITextField) -> Bool { 420 | toggleControls() 421 | return false 422 | } 423 | 424 | func textFieldDidEndEditing(textField: UITextField) { 425 | if editing { 426 | setEditing(false, animated: true) 427 | } 428 | } 429 | 430 | 431 | // MARK: - SSPullToRefreshViewDelegate 432 | 433 | func pullToRefreshViewDidStartLoading(view: SSPullToRefreshView!) { 434 | refresh() 435 | } 436 | 437 | func pullToRefreshViewShouldStartLoading(view: SSPullToRefreshView!) -> Bool { 438 | return !loading && !editing 439 | } 440 | } 441 | -------------------------------------------------------------------------------- /Coins.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 21104E5C1A253C67009B0D3C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21104E5B1A253C67009B0D3C /* AppDelegate.swift */; }; 11 | 21104E641A2541F6009B0D3C /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21104E631A2541F6009B0D3C /* TableViewCell.swift */; }; 12 | 21104E661A25441B009B0D3C /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21104E651A25441B009B0D3C /* TextField.swift */; }; 13 | 2130E1691864AD58006D3470 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2130E1681864AD58006D3470 /* Foundation.framework */; }; 14 | 2130E16B1864AD58006D3470 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2130E16A1864AD58006D3470 /* CoreGraphics.framework */; }; 15 | 2130E16D1864AD58006D3470 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2130E16C1864AD58006D3470 /* UIKit.framework */; }; 16 | 21363FF519C9434A0073FA6C /* BTCTodayValueView.m in Sources */ = {isa = PBXBuildFile; fileRef = 21363FF419C9434A0073FA6C /* BTCTodayValueView.m */; }; 17 | 213D0A721A25FF0500FA254B /* CoinsKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 213D0A5B1A25FF0500FA254B /* CoinsKit.framework */; }; 18 | 213D0A741A25FF0500FA254B /* CoinsKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 213D0A5B1A25FF0500FA254B /* CoinsKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 19 | 213D0A7C1A25FF4E00FA254B /* BTCConversionProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C103F119C921DD00CC5F36 /* BTCConversionProvider.m */; }; 20 | 213D0A7D1A25FF4E00FA254B /* BTCValueView.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C14D2519C91BBB0011C908 /* BTCValueView.m */; }; 21 | 213D0A7E1A25FF4E00FA254B /* BTCDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C103ED19C91EE700CC5F36 /* BTCDefines.m */; }; 22 | 213D0A801A25FF4E00FA254B /* NSUserDefaults+Coins.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C103E919C91E4000CC5F36 /* NSUserDefaults+Coins.m */; }; 23 | 213D0A811A25FF4E00FA254B /* BTCPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 21363FF719C955170073FA6C /* BTCPreferences.m */; }; 24 | 213D0A821A25FF5800FA254B /* CoinsKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 21C14D2C19C91BCA0011C908 /* CoinsKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25 | 213D0A831A25FF5800FA254B /* BTCConversionProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 21C103F019C921DD00CC5F36 /* BTCConversionProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | 213D0A841A25FF5800FA254B /* BTCValueView.h in Headers */ = {isa = PBXBuildFile; fileRef = 21C14D2419C91BBB0011C908 /* BTCValueView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27 | 213D0A851A25FF5800FA254B /* BTCDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 21C103EC19C91EE700CC5F36 /* BTCDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; 28 | 213D0A871A25FF5800FA254B /* NSUserDefaults+Coins.h in Headers */ = {isa = PBXBuildFile; fileRef = 21C103E819C91E4000CC5F36 /* NSUserDefaults+Coins.h */; settings = {ATTRIBUTES = (Public, ); }; }; 29 | 213D0A881A25FF5800FA254B /* BTCPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 21363FF619C955170073FA6C /* BTCPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; }; 30 | 213D0A891A25FF5D00FA254B /* CoinsKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21104E601A253E3F009B0D3C /* CoinsKit.swift */; }; 31 | 213D0A8A1A25FFFD00FA254B /* CoinsKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 213D0A5B1A25FF0500FA254B /* CoinsKit.framework */; }; 32 | 21900F5E1A254DE300C0CA2C /* TickingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21900F5D1A254DE300C0CA2C /* TickingButton.swift */; }; 33 | 21900F601A25506C00C0CA2C /* NSDate+Coins.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21900F5F1A25506C00C0CA2C /* NSDate+Coins.swift */; }; 34 | 21C14CEF19C910F80011C908 /* CurrencyPickerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C14CCE19C910F80011C908 /* CurrencyPickerTableViewController.swift */; }; 35 | 21C14CF419C910F80011C908 /* ValueViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C14CD819C910F80011C908 /* ValueViewController.swift */; }; 36 | 21C14CFB19C910F80011C908 /* currencies.json in Resources */ = {isa = PBXBuildFile; fileRef = 21C14CE519C910F80011C908 /* currencies.json */; }; 37 | 21C14CFC19C910F80011C908 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 21C14CE619C910F80011C908 /* Localizable.strings */; }; 38 | 21C14CFD19C910F80011C908 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 21C14CE819C910F80011C908 /* Images.xcassets */; }; 39 | 21C14CFE19C910F80011C908 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 21C14CE919C910F80011C908 /* Settings.bundle */; }; 40 | 21C14D0919C91A370011C908 /* NotificationCenter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21C14D0819C91A370011C908 /* NotificationCenter.framework */; }; 41 | 21C14D1419C91A370011C908 /* Coins Today.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 21C14D0719C91A370011C908 /* Coins Today.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 42 | 21C14D2019C91B9F0011C908 /* BTCTodayViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C14D1D19C91B9F0011C908 /* BTCTodayViewController.m */; }; 43 | 21FD2C4C1A26085700F8615D /* PullToRefreshView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21FD2C4B1A26085700F8615D /* PullToRefreshView.swift */; }; 44 | 21FD42651A26B12500772B53 /* GradientView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21FD42621A26B11500772B53 /* GradientView.framework */; }; 45 | 21FD42661A26B12E00772B53 /* GradientView.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 21FD42621A26B11500772B53 /* GradientView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 46 | 32A93DCF17EE721A2B4BF684 /* libPods-Coins.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 421E383A04144C6A8624166B /* libPods-Coins.a */; }; 47 | /* End PBXBuildFile section */ 48 | 49 | /* Begin PBXContainerItemProxy section */ 50 | 213D0A701A25FF0500FA254B /* PBXContainerItemProxy */ = { 51 | isa = PBXContainerItemProxy; 52 | containerPortal = 2130E15D1864AD57006D3470 /* Project object */; 53 | proxyType = 1; 54 | remoteGlobalIDString = 213D0A5A1A25FF0500FA254B; 55 | remoteInfo = CoinsKit; 56 | }; 57 | 213D0A8B1A26000200FA254B /* PBXContainerItemProxy */ = { 58 | isa = PBXContainerItemProxy; 59 | containerPortal = 2130E15D1864AD57006D3470 /* Project object */; 60 | proxyType = 1; 61 | remoteGlobalIDString = 213D0A5A1A25FF0500FA254B; 62 | remoteInfo = CoinsKit; 63 | }; 64 | 21C14D1219C91A370011C908 /* PBXContainerItemProxy */ = { 65 | isa = PBXContainerItemProxy; 66 | containerPortal = 2130E15D1864AD57006D3470 /* Project object */; 67 | proxyType = 1; 68 | remoteGlobalIDString = 21C14D0619C91A370011C908; 69 | remoteInfo = "Coins Today"; 70 | }; 71 | 21C14D1519C91A370011C908 /* PBXContainerItemProxy */ = { 72 | isa = PBXContainerItemProxy; 73 | containerPortal = 2130E15D1864AD57006D3470 /* Project object */; 74 | proxyType = 1; 75 | remoteGlobalIDString = 21C14D0619C91A370011C908; 76 | remoteInfo = "Coins Today"; 77 | }; 78 | 21FD425F1A26B11500772B53 /* PBXContainerItemProxy */ = { 79 | isa = PBXContainerItemProxy; 80 | containerPortal = 21FD425A1A26B11400772B53 /* Gradient View.xcodeproj */; 81 | proxyType = 2; 82 | remoteGlobalIDString = 2163B9F61A25FBF000610B0C; 83 | remoteInfo = Example; 84 | }; 85 | 21FD42611A26B11500772B53 /* PBXContainerItemProxy */ = { 86 | isa = PBXContainerItemProxy; 87 | containerPortal = 21FD425A1A26B11400772B53 /* Gradient View.xcodeproj */; 88 | proxyType = 2; 89 | remoteGlobalIDString = 2163BA201A25FBFD00610B0C; 90 | remoteInfo = GradientView; 91 | }; 92 | 21FD42631A26B11F00772B53 /* PBXContainerItemProxy */ = { 93 | isa = PBXContainerItemProxy; 94 | containerPortal = 21FD425A1A26B11400772B53 /* Gradient View.xcodeproj */; 95 | proxyType = 1; 96 | remoteGlobalIDString = 2163BA1F1A25FBFD00610B0C; 97 | remoteInfo = GradientView; 98 | }; 99 | /* End PBXContainerItemProxy section */ 100 | 101 | /* Begin PBXCopyFilesBuildPhase section */ 102 | 213D0A731A25FF0500FA254B /* Embed Frameworks */ = { 103 | isa = PBXCopyFilesBuildPhase; 104 | buildActionMask = 2147483647; 105 | dstPath = ""; 106 | dstSubfolderSpec = 10; 107 | files = ( 108 | 21FD42661A26B12E00772B53 /* GradientView.framework in Embed Frameworks */, 109 | 213D0A741A25FF0500FA254B /* CoinsKit.framework in Embed Frameworks */, 110 | ); 111 | name = "Embed Frameworks"; 112 | runOnlyForDeploymentPostprocessing = 0; 113 | }; 114 | 21C14D1A19C91A370011C908 /* Embed App Extensions */ = { 115 | isa = PBXCopyFilesBuildPhase; 116 | buildActionMask = 2147483647; 117 | dstPath = ""; 118 | dstSubfolderSpec = 13; 119 | files = ( 120 | 21C14D1419C91A370011C908 /* Coins Today.appex in Embed App Extensions */, 121 | ); 122 | name = "Embed App Extensions"; 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXCopyFilesBuildPhase section */ 126 | 127 | /* Begin PBXFileReference section */ 128 | 21104E5B1A253C67009B0D3C /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 129 | 21104E5D1A253D3C009B0D3C /* Coins-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Coins-Bridging-Header.h"; sourceTree = ""; }; 130 | 21104E601A253E3F009B0D3C /* CoinsKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoinsKit.swift; sourceTree = ""; }; 131 | 21104E631A2541F6009B0D3C /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = ""; }; 132 | 21104E651A25441B009B0D3C /* TextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = ""; }; 133 | 2130E1651864AD58006D3470 /* Coins.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Coins.app; sourceTree = BUILT_PRODUCTS_DIR; }; 134 | 2130E1681864AD58006D3470 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 135 | 2130E16A1864AD58006D3470 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 136 | 2130E16C1864AD58006D3470 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 137 | 2130E1811864AD58006D3470 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 138 | 21363FF319C9434A0073FA6C /* BTCTodayValueView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTCTodayValueView.h; sourceTree = ""; }; 139 | 21363FF419C9434A0073FA6C /* BTCTodayValueView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTCTodayValueView.m; sourceTree = ""; }; 140 | 21363FF619C955170073FA6C /* BTCPreferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTCPreferences.h; sourceTree = ""; }; 141 | 21363FF719C955170073FA6C /* BTCPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTCPreferences.m; sourceTree = ""; }; 142 | 213D0A5B1A25FF0500FA254B /* CoinsKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoinsKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 143 | 213D0A5E1A25FF0500FA254B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 144 | 21900F5D1A254DE300C0CA2C /* TickingButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TickingButton.swift; sourceTree = ""; }; 145 | 21900F5F1A25506C00C0CA2C /* NSDate+Coins.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSDate+Coins.swift"; sourceTree = ""; }; 146 | 21B148BA19C92DB200972BEF /* Coins.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Coins.entitlements; sourceTree = ""; }; 147 | 21B148BB19C92DB900972BEF /* Coins Today.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Coins Today.entitlements"; sourceTree = ""; }; 148 | 21C103E819C91E4000CC5F36 /* NSUserDefaults+Coins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSUserDefaults+Coins.h"; sourceTree = ""; }; 149 | 21C103E919C91E4000CC5F36 /* NSUserDefaults+Coins.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSUserDefaults+Coins.m"; sourceTree = ""; }; 150 | 21C103EC19C91EE700CC5F36 /* BTCDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTCDefines.h; sourceTree = ""; }; 151 | 21C103ED19C91EE700CC5F36 /* BTCDefines.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTCDefines.m; sourceTree = ""; }; 152 | 21C103F019C921DD00CC5F36 /* BTCConversionProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTCConversionProvider.h; sourceTree = ""; }; 153 | 21C103F119C921DD00CC5F36 /* BTCConversionProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTCConversionProvider.m; sourceTree = ""; }; 154 | 21C14CCE19C910F80011C908 /* CurrencyPickerTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CurrencyPickerTableViewController.swift; sourceTree = ""; }; 155 | 21C14CD819C910F80011C908 /* ValueViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueViewController.swift; sourceTree = ""; }; 156 | 21C14CE319C910F80011C908 /* Coins-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Coins-Info.plist"; sourceTree = ""; }; 157 | 21C14CE519C910F80011C908 /* currencies.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = currencies.json; sourceTree = ""; }; 158 | 21C14CE719C910F80011C908 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 159 | 21C14CE819C910F80011C908 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 160 | 21C14CE919C910F80011C908 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; 161 | 21C14D0719C91A370011C908 /* Coins Today.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Coins Today.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 162 | 21C14D0819C91A370011C908 /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; }; 163 | 21C14D1C19C91B9F0011C908 /* BTCTodayViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTCTodayViewController.h; sourceTree = ""; }; 164 | 21C14D1D19C91B9F0011C908 /* BTCTodayViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTCTodayViewController.m; sourceTree = ""; }; 165 | 21C14D1F19C91B9F0011C908 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 166 | 21C14D2419C91BBB0011C908 /* BTCValueView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTCValueView.h; sourceTree = ""; }; 167 | 21C14D2519C91BBB0011C908 /* BTCValueView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTCValueView.m; sourceTree = ""; }; 168 | 21C14D2C19C91BCA0011C908 /* CoinsKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoinsKit.h; sourceTree = ""; }; 169 | 21FD2C4B1A26085700F8615D /* PullToRefreshView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PullToRefreshView.swift; sourceTree = ""; }; 170 | 21FD425A1A26B11400772B53 /* Gradient View.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "Gradient View.xcodeproj"; path = "Carthage.checkout/GradientView/Gradient View.xcodeproj"; sourceTree = SOURCE_ROOT; }; 171 | 421E383A04144C6A8624166B /* libPods-Coins.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Coins.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 172 | 7C733206B69A4AA88CE1C3A3 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 173 | C1BD2968FA93A53EDFA565AD /* Pods-Coins.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Coins.release.xcconfig"; path = "Pods/Target Support Files/Pods-Coins/Pods-Coins.release.xcconfig"; sourceTree = ""; }; 174 | DD6A6B0D5AE336003EBD8FCE /* Pods-Coins.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Coins.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Coins/Pods-Coins.debug.xcconfig"; sourceTree = ""; }; 175 | E7F6998536F74DFE984E7C8A /* libPods-Coins Today.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Coins Today.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 176 | /* End PBXFileReference section */ 177 | 178 | /* Begin PBXFrameworksBuildPhase section */ 179 | 2130E1621864AD58006D3470 /* Frameworks */ = { 180 | isa = PBXFrameworksBuildPhase; 181 | buildActionMask = 2147483647; 182 | files = ( 183 | 21FD42651A26B12500772B53 /* GradientView.framework in Frameworks */, 184 | 2130E16B1864AD58006D3470 /* CoreGraphics.framework in Frameworks */, 185 | 2130E16D1864AD58006D3470 /* UIKit.framework in Frameworks */, 186 | 213D0A721A25FF0500FA254B /* CoinsKit.framework in Frameworks */, 187 | 2130E1691864AD58006D3470 /* Foundation.framework in Frameworks */, 188 | 32A93DCF17EE721A2B4BF684 /* libPods-Coins.a in Frameworks */, 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | 213D0A571A25FF0500FA254B /* Frameworks */ = { 193 | isa = PBXFrameworksBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | ); 197 | runOnlyForDeploymentPostprocessing = 0; 198 | }; 199 | 21C14D0419C91A370011C908 /* Frameworks */ = { 200 | isa = PBXFrameworksBuildPhase; 201 | buildActionMask = 2147483647; 202 | files = ( 203 | 213D0A8A1A25FFFD00FA254B /* CoinsKit.framework in Frameworks */, 204 | 21C14D0919C91A370011C908 /* NotificationCenter.framework in Frameworks */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXFrameworksBuildPhase section */ 209 | 210 | /* Begin PBXGroup section */ 211 | 2130E15C1864AD57006D3470 = { 212 | isa = PBXGroup; 213 | children = ( 214 | 21C14CC719C910F80011C908 /* Coins */, 215 | 21C14D0A19C91A370011C908 /* Coins Today */, 216 | 21C14D2219C91BBB0011C908 /* CoinsKit */, 217 | 21F9D1971876952A00F36678 /* Vendor */, 218 | 2130E1671864AD58006D3470 /* Frameworks */, 219 | 2130E1661864AD58006D3470 /* Products */, 220 | 9625555A56EE5EEE4742E258 /* Pods */, 221 | ); 222 | sourceTree = ""; 223 | }; 224 | 2130E1661864AD58006D3470 /* Products */ = { 225 | isa = PBXGroup; 226 | children = ( 227 | 2130E1651864AD58006D3470 /* Coins.app */, 228 | 21C14D0719C91A370011C908 /* Coins Today.appex */, 229 | 213D0A5B1A25FF0500FA254B /* CoinsKit.framework */, 230 | ); 231 | name = Products; 232 | sourceTree = ""; 233 | }; 234 | 2130E1671864AD58006D3470 /* Frameworks */ = { 235 | isa = PBXGroup; 236 | children = ( 237 | 2130E1681864AD58006D3470 /* Foundation.framework */, 238 | 2130E16A1864AD58006D3470 /* CoreGraphics.framework */, 239 | 2130E16C1864AD58006D3470 /* UIKit.framework */, 240 | 2130E1811864AD58006D3470 /* XCTest.framework */, 241 | 7C733206B69A4AA88CE1C3A3 /* libPods.a */, 242 | 21C14D0819C91A370011C908 /* NotificationCenter.framework */, 243 | 421E383A04144C6A8624166B /* libPods-Coins.a */, 244 | E7F6998536F74DFE984E7C8A /* libPods-Coins Today.a */, 245 | ); 246 | name = Frameworks; 247 | sourceTree = ""; 248 | }; 249 | 213D0A5D1A25FF0500FA254B /* Supporting Files */ = { 250 | isa = PBXGroup; 251 | children = ( 252 | 213D0A5E1A25FF0500FA254B /* Info.plist */, 253 | ); 254 | name = "Supporting Files"; 255 | sourceTree = ""; 256 | }; 257 | 21C14CC719C910F80011C908 /* Coins */ = { 258 | isa = PBXGroup; 259 | children = ( 260 | 21C14CC819C910F80011C908 /* Classes */, 261 | 21C14CDD19C910F80011C908 /* Other Sources */, 262 | 21C14CE219C910F80011C908 /* Resources */, 263 | ); 264 | path = Coins; 265 | sourceTree = ""; 266 | }; 267 | 21C14CC819C910F80011C908 /* Classes */ = { 268 | isa = PBXGroup; 269 | children = ( 270 | 21FD2C4D1A2619E100F8615D /* Application */, 271 | 21FD2C4E1A2619E900F8615D /* View Controllers */, 272 | 21FD2C4F1A2619F400F8615D /* Views */, 273 | 21FD2C501A2619F700F8615D /* Extensions */, 274 | ); 275 | path = Classes; 276 | sourceTree = ""; 277 | }; 278 | 21C14CDD19C910F80011C908 /* Other Sources */ = { 279 | isa = PBXGroup; 280 | children = ( 281 | 21104E5D1A253D3C009B0D3C /* Coins-Bridging-Header.h */, 282 | ); 283 | path = "Other Sources"; 284 | sourceTree = ""; 285 | }; 286 | 21C14CE219C910F80011C908 /* Resources */ = { 287 | isa = PBXGroup; 288 | children = ( 289 | 21B148BA19C92DB200972BEF /* Coins.entitlements */, 290 | 21C14CE319C910F80011C908 /* Coins-Info.plist */, 291 | 21C14CE519C910F80011C908 /* currencies.json */, 292 | 21C14CE619C910F80011C908 /* Localizable.strings */, 293 | 21C14CE819C910F80011C908 /* Images.xcassets */, 294 | 21C14CE919C910F80011C908 /* Settings.bundle */, 295 | ); 296 | path = Resources; 297 | sourceTree = ""; 298 | }; 299 | 21C14D0A19C91A370011C908 /* Coins Today */ = { 300 | isa = PBXGroup; 301 | children = ( 302 | 21C14D1B19C91B9F0011C908 /* Classes */, 303 | 21C14D1E19C91B9F0011C908 /* Resources */, 304 | ); 305 | path = "Coins Today"; 306 | sourceTree = ""; 307 | }; 308 | 21C14D1B19C91B9F0011C908 /* Classes */ = { 309 | isa = PBXGroup; 310 | children = ( 311 | 21C14D1C19C91B9F0011C908 /* BTCTodayViewController.h */, 312 | 21C14D1D19C91B9F0011C908 /* BTCTodayViewController.m */, 313 | 21363FF319C9434A0073FA6C /* BTCTodayValueView.h */, 314 | 21363FF419C9434A0073FA6C /* BTCTodayValueView.m */, 315 | ); 316 | path = Classes; 317 | sourceTree = ""; 318 | }; 319 | 21C14D1E19C91B9F0011C908 /* Resources */ = { 320 | isa = PBXGroup; 321 | children = ( 322 | 21B148BB19C92DB900972BEF /* Coins Today.entitlements */, 323 | 21C14D1F19C91B9F0011C908 /* Info.plist */, 324 | ); 325 | path = Resources; 326 | sourceTree = ""; 327 | }; 328 | 21C14D2219C91BBB0011C908 /* CoinsKit */ = { 329 | isa = PBXGroup; 330 | children = ( 331 | 21104E601A253E3F009B0D3C /* CoinsKit.swift */, 332 | 21C14D2319C91BBB0011C908 /* Classes */, 333 | 213D0A5D1A25FF0500FA254B /* Supporting Files */, 334 | ); 335 | path = CoinsKit; 336 | sourceTree = ""; 337 | }; 338 | 21C14D2319C91BBB0011C908 /* Classes */ = { 339 | isa = PBXGroup; 340 | children = ( 341 | 21C14D2C19C91BCA0011C908 /* CoinsKit.h */, 342 | 21C103F019C921DD00CC5F36 /* BTCConversionProvider.h */, 343 | 21C103F119C921DD00CC5F36 /* BTCConversionProvider.m */, 344 | 21C14D2419C91BBB0011C908 /* BTCValueView.h */, 345 | 21C14D2519C91BBB0011C908 /* BTCValueView.m */, 346 | 21C103EC19C91EE700CC5F36 /* BTCDefines.h */, 347 | 21C103ED19C91EE700CC5F36 /* BTCDefines.m */, 348 | 21C103E819C91E4000CC5F36 /* NSUserDefaults+Coins.h */, 349 | 21C103E919C91E4000CC5F36 /* NSUserDefaults+Coins.m */, 350 | 21363FF619C955170073FA6C /* BTCPreferences.h */, 351 | 21363FF719C955170073FA6C /* BTCPreferences.m */, 352 | ); 353 | path = Classes; 354 | sourceTree = ""; 355 | }; 356 | 21F9D1971876952A00F36678 /* Vendor */ = { 357 | isa = PBXGroup; 358 | children = ( 359 | 21FD425A1A26B11400772B53 /* Gradient View.xcodeproj */, 360 | ); 361 | path = Vendor; 362 | sourceTree = ""; 363 | }; 364 | 21FD2C4D1A2619E100F8615D /* Application */ = { 365 | isa = PBXGroup; 366 | children = ( 367 | 21104E5B1A253C67009B0D3C /* AppDelegate.swift */, 368 | ); 369 | name = Application; 370 | sourceTree = ""; 371 | }; 372 | 21FD2C4E1A2619E900F8615D /* View Controllers */ = { 373 | isa = PBXGroup; 374 | children = ( 375 | 21C14CD819C910F80011C908 /* ValueViewController.swift */, 376 | 21C14CCE19C910F80011C908 /* CurrencyPickerTableViewController.swift */, 377 | ); 378 | name = "View Controllers"; 379 | sourceTree = ""; 380 | }; 381 | 21FD2C4F1A2619F400F8615D /* Views */ = { 382 | isa = PBXGroup; 383 | children = ( 384 | 21900F5D1A254DE300C0CA2C /* TickingButton.swift */, 385 | 21104E651A25441B009B0D3C /* TextField.swift */, 386 | 21104E631A2541F6009B0D3C /* TableViewCell.swift */, 387 | 21FD2C4B1A26085700F8615D /* PullToRefreshView.swift */, 388 | ); 389 | name = Views; 390 | sourceTree = ""; 391 | }; 392 | 21FD2C501A2619F700F8615D /* Extensions */ = { 393 | isa = PBXGroup; 394 | children = ( 395 | 21900F5F1A25506C00C0CA2C /* NSDate+Coins.swift */, 396 | ); 397 | name = Extensions; 398 | sourceTree = ""; 399 | }; 400 | 21FD425B1A26B11400772B53 /* Products */ = { 401 | isa = PBXGroup; 402 | children = ( 403 | 21FD42601A26B11500772B53 /* Example.app */, 404 | 21FD42621A26B11500772B53 /* GradientView.framework */, 405 | ); 406 | name = Products; 407 | sourceTree = ""; 408 | }; 409 | 9625555A56EE5EEE4742E258 /* Pods */ = { 410 | isa = PBXGroup; 411 | children = ( 412 | DD6A6B0D5AE336003EBD8FCE /* Pods-Coins.debug.xcconfig */, 413 | C1BD2968FA93A53EDFA565AD /* Pods-Coins.release.xcconfig */, 414 | ); 415 | name = Pods; 416 | sourceTree = ""; 417 | }; 418 | /* End PBXGroup section */ 419 | 420 | /* Begin PBXHeadersBuildPhase section */ 421 | 213D0A581A25FF0500FA254B /* Headers */ = { 422 | isa = PBXHeadersBuildPhase; 423 | buildActionMask = 2147483647; 424 | files = ( 425 | 213D0A871A25FF5800FA254B /* NSUserDefaults+Coins.h in Headers */, 426 | 213D0A821A25FF5800FA254B /* CoinsKit.h in Headers */, 427 | 213D0A851A25FF5800FA254B /* BTCDefines.h in Headers */, 428 | 213D0A831A25FF5800FA254B /* BTCConversionProvider.h in Headers */, 429 | 213D0A881A25FF5800FA254B /* BTCPreferences.h in Headers */, 430 | 213D0A841A25FF5800FA254B /* BTCValueView.h in Headers */, 431 | ); 432 | runOnlyForDeploymentPostprocessing = 0; 433 | }; 434 | /* End PBXHeadersBuildPhase section */ 435 | 436 | /* Begin PBXNativeTarget section */ 437 | 2130E1641864AD58006D3470 /* Coins */ = { 438 | isa = PBXNativeTarget; 439 | buildConfigurationList = 2130E1911864AD58006D3470 /* Build configuration list for PBXNativeTarget "Coins" */; 440 | buildPhases = ( 441 | A6D58084BA76E5D8F77E64E1 /* Check Pods Manifest.lock */, 442 | 2130E1611864AD58006D3470 /* Sources */, 443 | 2130E1621864AD58006D3470 /* Frameworks */, 444 | 2130E1631864AD58006D3470 /* Resources */, 445 | 21C14D0219C9196B0011C908 /* Hockey */, 446 | 21C14D1A19C91A370011C908 /* Embed App Extensions */, 447 | 0B7B534546DA5F32F0701796 /* Copy Pods Resources */, 448 | 213D0A731A25FF0500FA254B /* Embed Frameworks */, 449 | ); 450 | buildRules = ( 451 | ); 452 | dependencies = ( 453 | 21FD42641A26B11F00772B53 /* PBXTargetDependency */, 454 | 21C14D1319C91A370011C908 /* PBXTargetDependency */, 455 | 21C14D1619C91A370011C908 /* PBXTargetDependency */, 456 | 213D0A711A25FF0500FA254B /* PBXTargetDependency */, 457 | ); 458 | name = Coins; 459 | productName = Coins; 460 | productReference = 2130E1651864AD58006D3470 /* Coins.app */; 461 | productType = "com.apple.product-type.application"; 462 | }; 463 | 213D0A5A1A25FF0500FA254B /* CoinsKit */ = { 464 | isa = PBXNativeTarget; 465 | buildConfigurationList = 213D0A751A25FF0500FA254B /* Build configuration list for PBXNativeTarget "CoinsKit" */; 466 | buildPhases = ( 467 | 213D0A561A25FF0500FA254B /* Sources */, 468 | 213D0A571A25FF0500FA254B /* Frameworks */, 469 | 213D0A581A25FF0500FA254B /* Headers */, 470 | 213D0A591A25FF0500FA254B /* Resources */, 471 | ); 472 | buildRules = ( 473 | ); 474 | dependencies = ( 475 | ); 476 | name = CoinsKit; 477 | productName = CoinsKit; 478 | productReference = 213D0A5B1A25FF0500FA254B /* CoinsKit.framework */; 479 | productType = "com.apple.product-type.framework"; 480 | }; 481 | 21C14D0619C91A370011C908 /* Coins Today */ = { 482 | isa = PBXNativeTarget; 483 | buildConfigurationList = 21C14D1719C91A370011C908 /* Build configuration list for PBXNativeTarget "Coins Today" */; 484 | buildPhases = ( 485 | 21C14D0319C91A370011C908 /* Sources */, 486 | 21C14D0419C91A370011C908 /* Frameworks */, 487 | 21C14D0519C91A370011C908 /* Resources */, 488 | ); 489 | buildRules = ( 490 | ); 491 | dependencies = ( 492 | 213D0A8C1A26000200FA254B /* PBXTargetDependency */, 493 | ); 494 | name = "Coins Today"; 495 | productName = "Coins Today"; 496 | productReference = 21C14D0719C91A370011C908 /* Coins Today.appex */; 497 | productType = "com.apple.product-type.app-extension"; 498 | }; 499 | /* End PBXNativeTarget section */ 500 | 501 | /* Begin PBXProject section */ 502 | 2130E15D1864AD57006D3470 /* Project object */ = { 503 | isa = PBXProject; 504 | attributes = { 505 | CLASSPREFIX = BTC; 506 | LastUpgradeCheck = 0510; 507 | ORGANIZATIONNAME = "Nothing Magical, Inc."; 508 | TargetAttributes = { 509 | 2130E1641864AD58006D3470 = { 510 | DevelopmentTeam = UP9C8XM22A; 511 | SystemCapabilities = { 512 | com.apple.ApplicationGroups.iOS = { 513 | enabled = 1; 514 | }; 515 | com.apple.BackgroundModes = { 516 | enabled = 1; 517 | }; 518 | com.apple.iCloud = { 519 | enabled = 1; 520 | }; 521 | }; 522 | }; 523 | 213D0A5A1A25FF0500FA254B = { 524 | CreatedOnToolsVersion = 6.2; 525 | DevelopmentTeam = UP9C8XM22A; 526 | }; 527 | 21C14D0619C91A370011C908 = { 528 | CreatedOnToolsVersion = 6.0; 529 | DevelopmentTeam = UP9C8XM22A; 530 | SystemCapabilities = { 531 | com.apple.ApplicationGroups.iOS = { 532 | enabled = 1; 533 | }; 534 | com.apple.iCloud = { 535 | enabled = 1; 536 | }; 537 | }; 538 | }; 539 | }; 540 | }; 541 | buildConfigurationList = 2130E1601864AD57006D3470 /* Build configuration list for PBXProject "Coins" */; 542 | compatibilityVersion = "Xcode 3.2"; 543 | developmentRegion = English; 544 | hasScannedForEncodings = 0; 545 | knownRegions = ( 546 | en, 547 | ); 548 | mainGroup = 2130E15C1864AD57006D3470; 549 | productRefGroup = 2130E1661864AD58006D3470 /* Products */; 550 | projectDirPath = ""; 551 | projectReferences = ( 552 | { 553 | ProductGroup = 21FD425B1A26B11400772B53 /* Products */; 554 | ProjectRef = 21FD425A1A26B11400772B53 /* Gradient View.xcodeproj */; 555 | }, 556 | ); 557 | projectRoot = ""; 558 | targets = ( 559 | 2130E1641864AD58006D3470 /* Coins */, 560 | 21C14D0619C91A370011C908 /* Coins Today */, 561 | 213D0A5A1A25FF0500FA254B /* CoinsKit */, 562 | ); 563 | }; 564 | /* End PBXProject section */ 565 | 566 | /* Begin PBXReferenceProxy section */ 567 | 21FD42601A26B11500772B53 /* Example.app */ = { 568 | isa = PBXReferenceProxy; 569 | fileType = wrapper.application; 570 | path = Example.app; 571 | remoteRef = 21FD425F1A26B11500772B53 /* PBXContainerItemProxy */; 572 | sourceTree = BUILT_PRODUCTS_DIR; 573 | }; 574 | 21FD42621A26B11500772B53 /* GradientView.framework */ = { 575 | isa = PBXReferenceProxy; 576 | fileType = wrapper.framework; 577 | path = GradientView.framework; 578 | remoteRef = 21FD42611A26B11500772B53 /* PBXContainerItemProxy */; 579 | sourceTree = BUILT_PRODUCTS_DIR; 580 | }; 581 | /* End PBXReferenceProxy section */ 582 | 583 | /* Begin PBXResourcesBuildPhase section */ 584 | 2130E1631864AD58006D3470 /* Resources */ = { 585 | isa = PBXResourcesBuildPhase; 586 | buildActionMask = 2147483647; 587 | files = ( 588 | 21C14CFD19C910F80011C908 /* Images.xcassets in Resources */, 589 | 21C14CFC19C910F80011C908 /* Localizable.strings in Resources */, 590 | 21C14CFE19C910F80011C908 /* Settings.bundle in Resources */, 591 | 21C14CFB19C910F80011C908 /* currencies.json in Resources */, 592 | ); 593 | runOnlyForDeploymentPostprocessing = 0; 594 | }; 595 | 213D0A591A25FF0500FA254B /* Resources */ = { 596 | isa = PBXResourcesBuildPhase; 597 | buildActionMask = 2147483647; 598 | files = ( 599 | ); 600 | runOnlyForDeploymentPostprocessing = 0; 601 | }; 602 | 21C14D0519C91A370011C908 /* Resources */ = { 603 | isa = PBXResourcesBuildPhase; 604 | buildActionMask = 2147483647; 605 | files = ( 606 | ); 607 | runOnlyForDeploymentPostprocessing = 0; 608 | }; 609 | /* End PBXResourcesBuildPhase section */ 610 | 611 | /* Begin PBXShellScriptBuildPhase section */ 612 | 0B7B534546DA5F32F0701796 /* Copy Pods Resources */ = { 613 | isa = PBXShellScriptBuildPhase; 614 | buildActionMask = 2147483647; 615 | files = ( 616 | ); 617 | inputPaths = ( 618 | ); 619 | name = "Copy Pods Resources"; 620 | outputPaths = ( 621 | ); 622 | runOnlyForDeploymentPostprocessing = 0; 623 | shellPath = /bin/sh; 624 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Coins/Pods-Coins-resources.sh\"\n"; 625 | showEnvVarsInLog = 0; 626 | }; 627 | 21C14D0219C9196B0011C908 /* Hockey */ = { 628 | isa = PBXShellScriptBuildPhase; 629 | buildActionMask = 2147483647; 630 | files = ( 631 | ); 632 | inputPaths = ( 633 | ); 634 | name = Hockey; 635 | outputPaths = ( 636 | ); 637 | runOnlyForDeploymentPostprocessing = 0; 638 | shellPath = /bin/sh; 639 | shellScript = "FILE=\"${SRCROOT}/Vendor/HockeySDK-iOS/BuildAgent\"\nif [ -f \"$FILE\" ]; then\n\"$FILE\"\nfi"; 640 | }; 641 | A6D58084BA76E5D8F77E64E1 /* Check Pods Manifest.lock */ = { 642 | isa = PBXShellScriptBuildPhase; 643 | buildActionMask = 2147483647; 644 | files = ( 645 | ); 646 | inputPaths = ( 647 | ); 648 | name = "Check Pods Manifest.lock"; 649 | outputPaths = ( 650 | ); 651 | runOnlyForDeploymentPostprocessing = 0; 652 | shellPath = /bin/sh; 653 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 654 | showEnvVarsInLog = 0; 655 | }; 656 | /* End PBXShellScriptBuildPhase section */ 657 | 658 | /* Begin PBXSourcesBuildPhase section */ 659 | 2130E1611864AD58006D3470 /* Sources */ = { 660 | isa = PBXSourcesBuildPhase; 661 | buildActionMask = 2147483647; 662 | files = ( 663 | 21104E641A2541F6009B0D3C /* TableViewCell.swift in Sources */, 664 | 21900F5E1A254DE300C0CA2C /* TickingButton.swift in Sources */, 665 | 21900F601A25506C00C0CA2C /* NSDate+Coins.swift in Sources */, 666 | 21104E661A25441B009B0D3C /* TextField.swift in Sources */, 667 | 21104E5C1A253C67009B0D3C /* AppDelegate.swift in Sources */, 668 | 21FD2C4C1A26085700F8615D /* PullToRefreshView.swift in Sources */, 669 | 21C14CF419C910F80011C908 /* ValueViewController.swift in Sources */, 670 | 21C14CEF19C910F80011C908 /* CurrencyPickerTableViewController.swift in Sources */, 671 | ); 672 | runOnlyForDeploymentPostprocessing = 0; 673 | }; 674 | 213D0A561A25FF0500FA254B /* Sources */ = { 675 | isa = PBXSourcesBuildPhase; 676 | buildActionMask = 2147483647; 677 | files = ( 678 | 213D0A7D1A25FF4E00FA254B /* BTCValueView.m in Sources */, 679 | 213D0A891A25FF5D00FA254B /* CoinsKit.swift in Sources */, 680 | 213D0A7C1A25FF4E00FA254B /* BTCConversionProvider.m in Sources */, 681 | 213D0A7E1A25FF4E00FA254B /* BTCDefines.m in Sources */, 682 | 213D0A811A25FF4E00FA254B /* BTCPreferences.m in Sources */, 683 | 213D0A801A25FF4E00FA254B /* NSUserDefaults+Coins.m in Sources */, 684 | ); 685 | runOnlyForDeploymentPostprocessing = 0; 686 | }; 687 | 21C14D0319C91A370011C908 /* Sources */ = { 688 | isa = PBXSourcesBuildPhase; 689 | buildActionMask = 2147483647; 690 | files = ( 691 | 21363FF519C9434A0073FA6C /* BTCTodayValueView.m in Sources */, 692 | 21C14D2019C91B9F0011C908 /* BTCTodayViewController.m in Sources */, 693 | ); 694 | runOnlyForDeploymentPostprocessing = 0; 695 | }; 696 | /* End PBXSourcesBuildPhase section */ 697 | 698 | /* Begin PBXTargetDependency section */ 699 | 213D0A711A25FF0500FA254B /* PBXTargetDependency */ = { 700 | isa = PBXTargetDependency; 701 | target = 213D0A5A1A25FF0500FA254B /* CoinsKit */; 702 | targetProxy = 213D0A701A25FF0500FA254B /* PBXContainerItemProxy */; 703 | }; 704 | 213D0A8C1A26000200FA254B /* PBXTargetDependency */ = { 705 | isa = PBXTargetDependency; 706 | target = 213D0A5A1A25FF0500FA254B /* CoinsKit */; 707 | targetProxy = 213D0A8B1A26000200FA254B /* PBXContainerItemProxy */; 708 | }; 709 | 21C14D1319C91A370011C908 /* PBXTargetDependency */ = { 710 | isa = PBXTargetDependency; 711 | target = 21C14D0619C91A370011C908 /* Coins Today */; 712 | targetProxy = 21C14D1219C91A370011C908 /* PBXContainerItemProxy */; 713 | }; 714 | 21C14D1619C91A370011C908 /* PBXTargetDependency */ = { 715 | isa = PBXTargetDependency; 716 | target = 21C14D0619C91A370011C908 /* Coins Today */; 717 | targetProxy = 21C14D1519C91A370011C908 /* PBXContainerItemProxy */; 718 | }; 719 | 21FD42641A26B11F00772B53 /* PBXTargetDependency */ = { 720 | isa = PBXTargetDependency; 721 | name = GradientView; 722 | targetProxy = 21FD42631A26B11F00772B53 /* PBXContainerItemProxy */; 723 | }; 724 | /* End PBXTargetDependency section */ 725 | 726 | /* Begin PBXVariantGroup section */ 727 | 21C14CE619C910F80011C908 /* Localizable.strings */ = { 728 | isa = PBXVariantGroup; 729 | children = ( 730 | 21C14CE719C910F80011C908 /* en */, 731 | ); 732 | name = Localizable.strings; 733 | sourceTree = ""; 734 | }; 735 | /* End PBXVariantGroup section */ 736 | 737 | /* Begin XCBuildConfiguration section */ 738 | 2130E18F1864AD58006D3470 /* Debug */ = { 739 | isa = XCBuildConfiguration; 740 | buildSettings = { 741 | ALWAYS_SEARCH_USER_PATHS = NO; 742 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 743 | CLANG_CXX_LIBRARY = "libc++"; 744 | CLANG_ENABLE_MODULES = YES; 745 | CLANG_ENABLE_OBJC_ARC = YES; 746 | CLANG_WARN_BOOL_CONVERSION = YES; 747 | CLANG_WARN_CONSTANT_CONVERSION = YES; 748 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 749 | CLANG_WARN_EMPTY_BODY = YES; 750 | CLANG_WARN_ENUM_CONVERSION = YES; 751 | CLANG_WARN_INT_CONVERSION = YES; 752 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 753 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 754 | COPY_PHASE_STRIP = NO; 755 | GCC_C_LANGUAGE_STANDARD = gnu99; 756 | GCC_DYNAMIC_NO_PIC = NO; 757 | GCC_OPTIMIZATION_LEVEL = 0; 758 | GCC_PREPROCESSOR_DEFINITIONS = ( 759 | "DEBUG=1", 760 | "$(inherited)", 761 | ); 762 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 763 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 764 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 765 | GCC_WARN_UNDECLARED_SELECTOR = YES; 766 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 767 | GCC_WARN_UNUSED_FUNCTION = YES; 768 | GCC_WARN_UNUSED_VARIABLE = YES; 769 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 770 | ONLY_ACTIVE_ARCH = YES; 771 | SDKROOT = iphoneos; 772 | TARGETED_DEVICE_FAMILY = "1,2"; 773 | WARNING_CFLAGS = "-Weverything"; 774 | }; 775 | name = Debug; 776 | }; 777 | 2130E1901864AD58006D3470 /* Release */ = { 778 | isa = XCBuildConfiguration; 779 | buildSettings = { 780 | ALWAYS_SEARCH_USER_PATHS = NO; 781 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 782 | CLANG_CXX_LIBRARY = "libc++"; 783 | CLANG_ENABLE_MODULES = YES; 784 | CLANG_ENABLE_OBJC_ARC = YES; 785 | CLANG_WARN_BOOL_CONVERSION = YES; 786 | CLANG_WARN_CONSTANT_CONVERSION = YES; 787 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 788 | CLANG_WARN_EMPTY_BODY = YES; 789 | CLANG_WARN_ENUM_CONVERSION = YES; 790 | CLANG_WARN_INT_CONVERSION = YES; 791 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 792 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 793 | COPY_PHASE_STRIP = YES; 794 | ENABLE_NS_ASSERTIONS = NO; 795 | GCC_C_LANGUAGE_STANDARD = gnu99; 796 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 797 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 798 | GCC_WARN_UNDECLARED_SELECTOR = YES; 799 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 800 | GCC_WARN_UNUSED_FUNCTION = YES; 801 | GCC_WARN_UNUSED_VARIABLE = YES; 802 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 803 | SDKROOT = iphoneos; 804 | TARGETED_DEVICE_FAMILY = "1,2"; 805 | VALIDATE_PRODUCT = YES; 806 | WARNING_CFLAGS = "-Weverything"; 807 | }; 808 | name = Release; 809 | }; 810 | 2130E1921864AD58006D3470 /* Debug */ = { 811 | isa = XCBuildConfiguration; 812 | baseConfigurationReference = DD6A6B0D5AE336003EBD8FCE /* Pods-Coins.debug.xcconfig */; 813 | buildSettings = { 814 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 815 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 816 | CLANG_ENABLE_MODULES = YES; 817 | CODE_SIGN_ENTITLEMENTS = Coins/Resources/Coins.entitlements; 818 | CODE_SIGN_IDENTITY = "iPhone Developer"; 819 | FRAMEWORK_SEARCH_PATHS = ( 820 | "$(inherited)", 821 | "$(PROJECT_DIR)", 822 | "$(PROJECT_DIR)/Vendor", 823 | "$(PROJECT_DIR)/Carthage.build/iOS", 824 | ); 825 | INFOPLIST_FILE = "$(SRCROOT)/Coins/Resources/Coins-Info.plist"; 826 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 827 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 828 | OTHER_SWIFT_FLAGS = "-DDEBUG=1"; 829 | PRODUCT_NAME = "$(TARGET_NAME)"; 830 | SWIFT_OBJC_BRIDGING_HEADER = "Coins/Other Sources/Coins-Bridging-Header.h"; 831 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 832 | WRAPPER_EXTENSION = app; 833 | }; 834 | name = Debug; 835 | }; 836 | 2130E1931864AD58006D3470 /* Release */ = { 837 | isa = XCBuildConfiguration; 838 | baseConfigurationReference = C1BD2968FA93A53EDFA565AD /* Pods-Coins.release.xcconfig */; 839 | buildSettings = { 840 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 841 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 842 | CLANG_ENABLE_MODULES = YES; 843 | CODE_SIGN_ENTITLEMENTS = Coins/Resources/Coins.entitlements; 844 | CODE_SIGN_IDENTITY = "iPhone Developer"; 845 | FRAMEWORK_SEARCH_PATHS = ( 846 | "$(inherited)", 847 | "$(PROJECT_DIR)", 848 | "$(PROJECT_DIR)/Vendor", 849 | "$(PROJECT_DIR)/Carthage.build/iOS", 850 | ); 851 | INFOPLIST_FILE = "$(SRCROOT)/Coins/Resources/Coins-Info.plist"; 852 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 853 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 854 | PRODUCT_NAME = "$(TARGET_NAME)"; 855 | SWIFT_OBJC_BRIDGING_HEADER = "Coins/Other Sources/Coins-Bridging-Header.h"; 856 | WRAPPER_EXTENSION = app; 857 | }; 858 | name = Release; 859 | }; 860 | 213D0A761A25FF0500FA254B /* Debug */ = { 861 | isa = XCBuildConfiguration; 862 | buildSettings = { 863 | APPLICATION_EXTENSION_API_ONLY = YES; 864 | CLANG_WARN_UNREACHABLE_CODE = YES; 865 | CODE_SIGN_IDENTITY = "iPhone Developer"; 866 | CURRENT_PROJECT_VERSION = 1; 867 | DEFINES_MODULE = YES; 868 | DYLIB_COMPATIBILITY_VERSION = 1; 869 | DYLIB_CURRENT_VERSION = 1; 870 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 871 | ENABLE_STRICT_OBJC_MSGSEND = YES; 872 | GCC_PREPROCESSOR_DEFINITIONS = ( 873 | "DEBUG=1", 874 | "$(inherited)", 875 | ); 876 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 877 | INFOPLIST_FILE = CoinsKit/Info.plist; 878 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 879 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 880 | MTL_ENABLE_DEBUG_INFO = YES; 881 | PRODUCT_NAME = "$(TARGET_NAME)"; 882 | SKIP_INSTALL = YES; 883 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 884 | VERSIONING_SYSTEM = "apple-generic"; 885 | VERSION_INFO_PREFIX = ""; 886 | WARNING_CFLAGS = ( 887 | "-Weverything", 888 | "-Wno-missing-variable-declarations", 889 | ); 890 | }; 891 | name = Debug; 892 | }; 893 | 213D0A771A25FF0500FA254B /* Release */ = { 894 | isa = XCBuildConfiguration; 895 | buildSettings = { 896 | APPLICATION_EXTENSION_API_ONLY = YES; 897 | CLANG_WARN_UNREACHABLE_CODE = YES; 898 | CODE_SIGN_IDENTITY = "iPhone Distribution"; 899 | CURRENT_PROJECT_VERSION = 1; 900 | DEFINES_MODULE = YES; 901 | DYLIB_COMPATIBILITY_VERSION = 1; 902 | DYLIB_CURRENT_VERSION = 1; 903 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 904 | ENABLE_STRICT_OBJC_MSGSEND = YES; 905 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 906 | INFOPLIST_FILE = CoinsKit/Info.plist; 907 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 908 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 909 | MTL_ENABLE_DEBUG_INFO = NO; 910 | PRODUCT_NAME = "$(TARGET_NAME)"; 911 | SKIP_INSTALL = YES; 912 | VERSIONING_SYSTEM = "apple-generic"; 913 | VERSION_INFO_PREFIX = ""; 914 | WARNING_CFLAGS = ( 915 | "-Weverything", 916 | "-Wno-missing-variable-declarations", 917 | ); 918 | }; 919 | name = Release; 920 | }; 921 | 21C14D1819C91A370011C908 /* Debug */ = { 922 | isa = XCBuildConfiguration; 923 | buildSettings = { 924 | CLANG_WARN_UNREACHABLE_CODE = YES; 925 | CODE_SIGN_ENTITLEMENTS = "Coins Today/Resources/Coins Today.entitlements"; 926 | CODE_SIGN_IDENTITY = "iPhone Developer"; 927 | ENABLE_STRICT_OBJC_MSGSEND = YES; 928 | GCC_PREPROCESSOR_DEFINITIONS = ( 929 | "DEBUG=1", 930 | "$(inherited)", 931 | ); 932 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 933 | INFOPLIST_FILE = "$(SRCROOT)/Coins Today/Resources/Info.plist"; 934 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 935 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 936 | MTL_ENABLE_DEBUG_INFO = YES; 937 | PRODUCT_NAME = "$(TARGET_NAME)"; 938 | SKIP_INSTALL = YES; 939 | }; 940 | name = Debug; 941 | }; 942 | 21C14D1919C91A370011C908 /* Release */ = { 943 | isa = XCBuildConfiguration; 944 | buildSettings = { 945 | CLANG_WARN_UNREACHABLE_CODE = YES; 946 | CODE_SIGN_ENTITLEMENTS = "Coins Today/Resources/Coins Today.entitlements"; 947 | CODE_SIGN_IDENTITY = "iPhone Developer"; 948 | ENABLE_STRICT_OBJC_MSGSEND = YES; 949 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 950 | INFOPLIST_FILE = "$(SRCROOT)/Coins Today/Resources/Info.plist"; 951 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 952 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 953 | MTL_ENABLE_DEBUG_INFO = NO; 954 | PRODUCT_NAME = "$(TARGET_NAME)"; 955 | SKIP_INSTALL = YES; 956 | }; 957 | name = Release; 958 | }; 959 | /* End XCBuildConfiguration section */ 960 | 961 | /* Begin XCConfigurationList section */ 962 | 2130E1601864AD57006D3470 /* Build configuration list for PBXProject "Coins" */ = { 963 | isa = XCConfigurationList; 964 | buildConfigurations = ( 965 | 2130E18F1864AD58006D3470 /* Debug */, 966 | 2130E1901864AD58006D3470 /* Release */, 967 | ); 968 | defaultConfigurationIsVisible = 0; 969 | defaultConfigurationName = Release; 970 | }; 971 | 2130E1911864AD58006D3470 /* Build configuration list for PBXNativeTarget "Coins" */ = { 972 | isa = XCConfigurationList; 973 | buildConfigurations = ( 974 | 2130E1921864AD58006D3470 /* Debug */, 975 | 2130E1931864AD58006D3470 /* Release */, 976 | ); 977 | defaultConfigurationIsVisible = 0; 978 | defaultConfigurationName = Release; 979 | }; 980 | 213D0A751A25FF0500FA254B /* Build configuration list for PBXNativeTarget "CoinsKit" */ = { 981 | isa = XCConfigurationList; 982 | buildConfigurations = ( 983 | 213D0A761A25FF0500FA254B /* Debug */, 984 | 213D0A771A25FF0500FA254B /* Release */, 985 | ); 986 | defaultConfigurationIsVisible = 0; 987 | defaultConfigurationName = Release; 988 | }; 989 | 21C14D1719C91A370011C908 /* Build configuration list for PBXNativeTarget "Coins Today" */ = { 990 | isa = XCConfigurationList; 991 | buildConfigurations = ( 992 | 21C14D1819C91A370011C908 /* Debug */, 993 | 21C14D1919C91A370011C908 /* Release */, 994 | ); 995 | defaultConfigurationIsVisible = 0; 996 | defaultConfigurationName = Release; 997 | }; 998 | /* End XCConfigurationList section */ 999 | }; 1000 | rootObject = 2130E15D1864AD57006D3470 /* Project object */; 1001 | } 1002 | --------------------------------------------------------------------------------