├── Asset ├── appgroup.png ├── art.png └── preview.png ├── Did-you-know-master ├── Did you know.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ ├── Manu.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── hiran.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── Manu.xcuserdatad │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ │ ├── ExampleSCDWidget.xcscheme │ │ │ ├── ExampleSharedCoreData.xcscheme │ │ │ ├── SCDWidget.xcscheme │ │ │ ├── SharedCoreData.xcscheme │ │ │ └── xcschememanagement.plist │ │ └── hiran.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── Facts+CoreDataClass.swift ├── Facts+CoreDataProperties.swift ├── SCDWidget │ ├── Base.lproj │ │ └── MainInterface.storyboard │ ├── Info.plist │ ├── SCDWidget.entitlements │ └── TodayViewController.swift ├── SharedCoreData │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x-1.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x-1.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x-1.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ ├── Contents.json │ │ └── Icon_bulb.imageset │ │ │ ├── Contents.json │ │ │ ├── s.png │ │ │ ├── s@2x.png │ │ │ └── s@3x.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── DataManager │ │ ├── SCDCoreDataWrapper.swift │ │ └── SCDFactModel.swift │ ├── DatePicker │ │ └── JBDatePicker │ │ │ ├── Classes │ │ │ ├── JBDate.swift │ │ │ ├── JBDateExtension.swift │ │ │ ├── JBDatePickerContentVC.swift │ │ │ ├── JBDatePickerDayView.swift │ │ │ ├── JBDatePickerEnums.swift │ │ │ ├── JBDatePickerManager.swift │ │ │ ├── JBDatePickerMonthView.swift │ │ │ ├── JBDatePickerSelectionView.swift │ │ │ ├── JBDatePickerView.swift │ │ │ ├── JBDatePickerViewDelegate.swift │ │ │ ├── JBDatePickerWeekDaysView.swift │ │ │ ├── JBDatePickerWeekView.swift │ │ │ └── JBFont.swift │ │ │ ├── Info.plist │ │ │ └── JBDatePicker.h │ ├── DidYouKnowFacts.json │ ├── HomeViewController.swift │ ├── Info.plist │ ├── SharedCoreData.entitlements │ └── SharedCoreData.xcdatamodeld │ │ ├── .xccurrentversion │ │ └── SharedCoreData.xcdatamodel │ │ └── contents ├── SharedCoreDataTests │ ├── Info.plist │ └── SharedCoreDataTests.swift └── SharedCoreDataUITests │ ├── Info.plist │ └── SharedCoreDataUITests.swift └── README.md /Asset/appgroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Asset/appgroup.png -------------------------------------------------------------------------------- /Asset/art.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Asset/art.png -------------------------------------------------------------------------------- /Asset/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Asset/preview.png -------------------------------------------------------------------------------- /Did-you-know-master/Did you know.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Did-you-know-master/Did you know.xcodeproj/project.xcworkspace/xcuserdata/Manu.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/Did you know.xcodeproj/project.xcworkspace/xcuserdata/Manu.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Did-you-know-master/Did you know.xcodeproj/project.xcworkspace/xcuserdata/hiran.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/Did you know.xcodeproj/project.xcworkspace/xcuserdata/hiran.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Did-you-know-master/Did you know.xcodeproj/xcuserdata/Manu.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Did-you-know-master/Did you know.xcodeproj/xcuserdata/Manu.xcuserdatad/xcschemes/ExampleSCDWidget.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 6 | 9 | 10 | 16 | 22 | 23 | 24 | 30 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 70 | 72 | 78 | 79 | 80 | 81 | 82 | 83 | 90 | 92 | 98 | 99 | 100 | 101 | 103 | 104 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /Did-you-know-master/Did you know.xcodeproj/xcuserdata/Manu.xcuserdatad/xcschemes/ExampleSharedCoreData.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Did-you-know-master/Did you know.xcodeproj/xcuserdata/Manu.xcuserdatad/xcschemes/SCDWidget.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 6 | 9 | 10 | 16 | 22 | 23 | 24 | 30 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 70 | 72 | 78 | 79 | 80 | 81 | 82 | 83 | 90 | 92 | 98 | 99 | 100 | 101 | 103 | 104 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /Did-you-know-master/Did you know.xcodeproj/xcuserdata/Manu.xcuserdatad/xcschemes/SharedCoreData.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Did-you-know-master/Did you know.xcodeproj/xcuserdata/Manu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ExampleSCDWidget.xcscheme 8 | 9 | orderHint 10 | 3 11 | 12 | ExampleSharedCoreData.xcscheme 13 | 14 | orderHint 15 | 2 16 | 17 | SCDWidget.xcscheme 18 | 19 | orderHint 20 | 1 21 | 22 | SharedCoreData.xcscheme 23 | 24 | orderHint 25 | 0 26 | 27 | 28 | SuppressBuildableAutocreation 29 | 30 | 324735191FE25EA10002C221 31 | 32 | primary 33 | 34 | 35 | 324735301FE25EA20002C221 36 | 37 | primary 38 | 39 | 40 | 3247353B1FE25EA20002C221 41 | 42 | primary 43 | 44 | 45 | 324735511FE26E580002C221 46 | 47 | primary 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Did-you-know-master/Did you know.xcodeproj/xcuserdata/hiran.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SCDWidget.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | SharedCoreData.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Did-you-know-master/Facts+CoreDataClass.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Facts+CoreDataClass.swift 3 | // SharedCoreData 4 | // 5 | // Created by iLeaf Solutions on 18/12/17. 6 | // Copyright © 2017 iLeaf. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreData 11 | 12 | @objc(Facts) 13 | public class Facts: NSManagedObject { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Did-you-know-master/Facts+CoreDataProperties.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Facts+CoreDataProperties.swift 3 | // SharedCoreData 4 | // 5 | // Created by iLeaf Solutions on 18/12/17. 6 | // Copyright © 2017 iLeaf. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreData 11 | 12 | 13 | extension Facts { 14 | 15 | @nonobjc public class func fetchRequest() -> NSFetchRequest { 16 | return NSFetchRequest(entityName: "Facts") 17 | } 18 | 19 | @NSManaged public var date: String? 20 | @NSManaged public var fact: String? 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Did-you-know-master/SCDWidget/Base.lproj/MainInterface.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | TimesNewRomanPSMT 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /Did-you-know-master/SCDWidget/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Did you know? 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | NSExtension 24 | 25 | NSExtensionMainStoryboard 26 | MainInterface 27 | NSExtensionPointIdentifier 28 | com.apple.widget-extension 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Did-you-know-master/SCDWidget/SCDWidget.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.com.ileaf.SharedCoreData 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Did-you-know-master/SCDWidget/TodayViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TodayViewController.swift 3 | // SCDWidget 4 | // 5 | // Created by iLeaf Solutions on 14/12/17. 6 | // Copyright © 2017 iLeaf. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import NotificationCenter 11 | import CoreData 12 | 13 | class TodayViewController: UIViewController, NCWidgetProviding { 14 | //Core data context 15 | var managedContext: NSManagedObjectContext? 16 | /// Input is todays fact 17 | @IBOutlet weak var lblFactsDescription: UILabel! 18 | 19 | //MARK: View life cycle 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | // Do any additional setup after loading the view from its nib. 23 | } 24 | 25 | override func didReceiveMemoryWarning() { 26 | super.didReceiveMemoryWarning() 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) { 31 | // Perform any setup necessary in order to update the view. 32 | fetchTodaysFact() 33 | // If an error is encountered, use NCUpdateResult.Failed 34 | // If there's no update required, use NCUpdateResult.NoData 35 | // If there's an update, use NCUpdateResult.NewData 36 | 37 | 38 | completionHandler(NCUpdateResult.newData) 39 | } 40 | // MARK: Helper functions 41 | func getMonth(month:Int) -> String { 42 | switch month { 43 | case 1: 44 | return "Jan" 45 | case 2: 46 | return "Feb" 47 | case 3: 48 | return "Mar" 49 | case 4: 50 | return "Apr" 51 | case 5: 52 | return "May" 53 | case 6: 54 | return "Jun" 55 | case 7: 56 | return "Jul" 57 | case 8: 58 | return "Aug" 59 | case 9: 60 | return "Sep" 61 | case 10: 62 | return "Oct" 63 | case 11: 64 | return "Nov" 65 | default: 66 | return "Dec" 67 | } 68 | } 69 | func fetchTodaysFact() 70 | { 71 | let date = Date() 72 | let calendar = Calendar.current 73 | let components = calendar.dateComponents([.year, .month, .day], from:date) 74 | 75 | // let year = components.year 76 | let month = components.month 77 | 78 | let day:Int = components.day! 79 | let todaysDate = getMonth(month: month!)+" "+String(day) 80 | let data = self.fetchTodaysFact(filter: todaysDate) 81 | let replaced = data.fact.trimmingCharacters(in: NSCharacterSet.whitespaces) 82 | lblFactsDescription.text = replaced 83 | } 84 | 85 | //MARK: Get Facts with filter from coredata 86 | //from DB Function 87 | func fetchTodaysFact(filter:String) ->SCDFactModel{ 88 | 89 | var todaysFact = SCDFactModel() 90 | //var managedContext = context 91 | if #available(iOS 10.0, *) { 92 | managedContext = 93 | SCDCoreDataWrapper.sharedInstance.persistentContainer.viewContext 94 | } else { 95 | // Fallback on earlier versions 96 | managedContext = SCDCoreDataWrapper.sharedInstance.managedObjectContext 97 | } 98 | let fetchRequest = 99 | NSFetchRequest(entityName: "Facts") 100 | do { 101 | //go get the results 102 | fetchRequest.returnsObjectsAsFaults = false 103 | fetchRequest.predicate = NSPredicate(format: "date == %@",filter) 104 | // let Results = try getContext().fetch(fetchRequest) 105 | // print(Results) 106 | let searchResults = try SCDCoreDataWrapper.sharedInstance.getContext().fetch(fetchRequest) 107 | //I like to check the size of the returned results! 108 | print ("num of results = \(String(describing: searchResults.count))") 109 | //You need to convert to NSManagedObject to use 'for' loops 110 | for transPort in searchResults { 111 | //get the Key Value pairs from searchResult () 112 | let data = SCDFactModel() 113 | todaysFact = data.factsMapping(factMapper: transPort) 114 | 115 | 116 | } 117 | 118 | return todaysFact 119 | } 120 | catch { 121 | print("Error with request: \(error)") 122 | return todaysFact 123 | } 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SharedCoreData 4 | // 5 | // Created by iLeaf Solutions on 14/12/17. 6 | // Copyright © 2017 iLeaf. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoreData 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | 18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 19 | // Override point for customization after application launch. 20 | return true 21 | } 22 | 23 | func applicationWillResignActive(_ application: UIApplication) { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 26 | } 27 | 28 | func applicationDidEnterBackground(_ application: UIApplication) { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | func applicationWillEnterForeground(_ application: UIApplication) { 34 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | func applicationDidBecomeActive(_ application: UIApplication) { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | func applicationWillTerminate(_ application: UIApplication) { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | // Saves changes in the application's managed object context before the application terminates. 44 | 45 | } 46 | 47 | 48 | 49 | } 50 | 51 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-App-20x20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-29x29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@2x-1.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-40x40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@2x-1.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-76x76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-83.5x83.5@2x.png", 103 | "scale" : "2x" 104 | } 105 | ], 106 | "info" : { 107 | "version" : 1, 108 | "author" : "xcode" 109 | } 110 | } -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/Icon_bulb.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "s.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "s@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "s@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/Icon_bulb.imageset/s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/Icon_bulb.imageset/s.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/Icon_bulb.imageset/s@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/Icon_bulb.imageset/s@2x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Assets.xcassets/Icon_bulb.imageset/s@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/Notification-Center-Widget/246af18dcab49e8f7bbde76d3e06e49c96597e86/Did-you-know-master/SharedCoreData/Assets.xcassets/Icon_bulb.imageset/s@3x.png -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | TimesNewRomanPSMT 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 42 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | TimesNewRomanPSMT 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 46 | 47 | 48 | 49 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 85 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DataManager/SCDCoreDataWrapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCDCoreDataWrapper.swift 3 | // SharedCoreData 4 | // 5 | // Created by iLeaf Solutions on 15/12/17. 6 | // Copyright © 2017 iLeaf. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoreData 11 | 12 | class SCDCoreDataWrapper: NSObject { 13 | var context: NSManagedObjectContext? 14 | static let sharedInstance : SCDCoreDataWrapper = { 15 | let instance = SCDCoreDataWrapper() 16 | return instance 17 | }() 18 | 19 | // MARK: - Core Data stack 20 | @available(iOS 10.0, *) 21 | lazy var persistentContainer: NSPersistentContainer = { 22 | /* 23 | The persistent container for the application. This implementation 24 | creates and returns a container, having loaded the store for the 25 | application to it. This property is optional since there are legitimate 26 | error conditions that could cause the creation of the store to fail. 27 | */ 28 | let container = NSPersistentContainer(name: "SharedCoreData") 29 | var persistentStoreDescriptions: NSPersistentStoreDescription 30 | 31 | let storeUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.ileaf.SharedCoreData")!.appendingPathComponent("\("SharedCoreData").sqlite") 32 | 33 | let description = NSPersistentStoreDescription() 34 | description.shouldInferMappingModelAutomatically = true 35 | description.shouldMigrateStoreAutomatically = true 36 | description.url = storeUrl 37 | 38 | container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.ileaf.SharedCoreData")!.appendingPathComponent("\("SharedCoreData").sqlite"))] 39 | 40 | container.loadPersistentStores(completionHandler: { (storeDescription, error) in 41 | if let error = error as NSError? { 42 | // Replace this implementation with code to handle the error appropriately. 43 | // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 44 | 45 | /* 46 | Typical reasons for an error here include: 47 | * The parent directory does not exist, cannot be created, or disallows writing. 48 | * The persistent store is not accessible, due to permissions or data protection when the device is locked. 49 | * The device is out of space. 50 | * The store could not be migrated to the current model version. 51 | Check the error message to determine what the actual problem was. 52 | */ 53 | fatalError("Unresolved error \(error), \(error.userInfo)") 54 | } 55 | }) 56 | return container 57 | }() 58 | 59 | 60 | 61 | // MARK: - Core Data Saving support 62 | func saveContext () { 63 | if #available(iOS 10.0, *) { 64 | context = persistentContainer.viewContext 65 | if (context?.hasChanges)! { 66 | do { 67 | try context?.save() 68 | } catch { 69 | } 70 | } 71 | } else { 72 | // Fallback on earlier versions 73 | // iOS 9.0 and below - however you were previously handling it 74 | guard let modelURL = Bundle.main.url(forResource: "SharedCoreData", withExtension:"momd") else { 75 | fatalError("Error loading model from bundle") 76 | } 77 | guard let mom = NSManagedObjectModel(contentsOf: modelURL) else { 78 | fatalError("Error initializing mom from: \(modelURL)") 79 | } 80 | let psc = NSPersistentStoreCoordinator(managedObjectModel: mom) 81 | context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) 82 | let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 83 | let docURL = urls[urls.endIndex-1] 84 | let storeURL = docURL.appendingPathComponent("SharedCoreData.sqlite") 85 | do { 86 | try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil) 87 | } catch { 88 | fatalError("Error migrating store: \(error)") 89 | } 90 | 91 | } 92 | 93 | } 94 | public lazy var managedObjectContext: NSManagedObjectContext = { 95 | let coordinator = self.persistentStoreCoordinator 96 | var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) 97 | managedObjectContext.persistentStoreCoordinator = coordinator 98 | return managedObjectContext 99 | }() 100 | 101 | //MARK:- Get the NSManagedObjectContext 102 | func getContext () -> NSManagedObjectContext { 103 | if #available(iOS 10.0, *) { 104 | return SCDCoreDataWrapper.sharedInstance.persistentContainer.viewContext 105 | } else { 106 | // Fallback on earlier versions 107 | return self.managedObjectContext 108 | //return NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) 109 | } 110 | 111 | } 112 | 113 | private lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = { 114 | do { 115 | return try NSPersistentStoreCoordinator.coordinator(name:"SharedCoreData") 116 | } catch { 117 | print("CoreData: Unresolved error \(error)") 118 | } 119 | return nil 120 | }() 121 | 122 | 123 | //MARK:- Save all did you know facts 124 | func saveFacts(facts:[SCDFactModel], entity:String ) { 125 | 126 | var managedContext = context 127 | if #available(iOS 10.0, *) { 128 | managedContext = 129 | SCDCoreDataWrapper.sharedInstance.persistentContainer.viewContext 130 | } else { 131 | // Fallback on earlier versions 132 | managedContext = self.managedObjectContext 133 | } 134 | // 2 135 | let entity = NSEntityDescription.entity(forEntityName: entity,in: managedContext!)! 136 | 137 | 138 | do { 139 | 140 | for fact in facts 141 | { 142 | let person = NSManagedObject(entity: entity,insertInto: managedContext) 143 | 144 | let factMapper = fact 145 | factMapper.coreDataMapping(data: fact, managedPerson: person) 146 | } 147 | 148 | } 149 | do{ 150 | try managedContext?.save() 151 | }catch{ 152 | debugPrint("error") 153 | } 154 | 155 | } 156 | 157 | //MARK:- Get Facts with filter 158 | //from DB Function 159 | func fetchTodaysFact(filter:String) ->SCDFactModel{ 160 | 161 | var todaysFact = SCDFactModel() 162 | var managedContext = context 163 | if #available(iOS 10.0, *) { 164 | managedContext = 165 | SCDCoreDataWrapper.sharedInstance.persistentContainer.viewContext 166 | } else { 167 | // Fallback on earlier versions 168 | managedContext = self.managedObjectContext 169 | } 170 | let fetchRequest = 171 | NSFetchRequest(entityName: "Facts") 172 | do { 173 | //go get the results 174 | fetchRequest.returnsObjectsAsFaults = false 175 | fetchRequest.predicate = NSPredicate(format: "date == %@",filter) 176 | // let Results = try getContext().fetch(fetchRequest) 177 | // print(Results) 178 | let searchResults = try managedContext?.fetch(fetchRequest) 179 | 180 | 181 | //I like to check the size of the returned results! 182 | print ("num of results = \(String(describing: searchResults?.count))") 183 | //You need to convert to NSManagedObject to use 'for' loops 184 | for transPort in searchResults! { 185 | //get the Key Value pairs from searchResult () 186 | let data = SCDFactModel() 187 | todaysFact = data.factsMapping(factMapper: transPort) 188 | 189 | 190 | } 191 | 192 | return todaysFact 193 | } 194 | catch { 195 | print("Error with request: \(error)") 196 | return todaysFact 197 | } 198 | } 199 | 200 | } 201 | 202 | /// NSPersistentStoreCoordinator extension 203 | extension NSPersistentStoreCoordinator { 204 | 205 | /// NSPersistentStoreCoordinator error types 206 | public enum CoordinatorError: Error { 207 | /// .momd file not found 208 | case modelFileNotFound 209 | /// NSManagedObjectModel creation fail 210 | case modelCreationError 211 | /// Gettings document directory fail 212 | case storePathNotFound 213 | } 214 | 215 | /// Return NSPersistentStoreCoordinator object 216 | static func coordinator(name: String) throws -> NSPersistentStoreCoordinator? { 217 | 218 | guard let modelURL = Bundle.main.url(forResource: name, withExtension: "momd") else { 219 | throw CoordinatorError.modelFileNotFound 220 | } 221 | 222 | guard let model = NSManagedObjectModel(contentsOf: modelURL) else { 223 | throw CoordinatorError.modelCreationError 224 | } 225 | 226 | let coordinator = NSPersistentStoreCoordinator(managedObjectModel: model) 227 | 228 | guard let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last else { 229 | throw CoordinatorError.storePathNotFound 230 | } 231 | do { 232 | let url = documents.appendingPathComponent("\(name).sqlite") 233 | let options = [ NSMigratePersistentStoresAutomaticallyOption : true, 234 | NSInferMappingModelAutomaticallyOption : true ] 235 | try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: options) 236 | } catch { 237 | throw error 238 | } 239 | 240 | return coordinator 241 | } 242 | } 243 | 244 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DataManager/SCDFactModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCDUserModel.swift 3 | // SharedCoreData 4 | // 5 | // Created by iLeaf Solutions on 15/12/17. 6 | // Copyright © 2017 iLeaf. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreData 11 | struct SCDFactModel { 12 | 13 | //MARK:- Properties 14 | 15 | /// know fact 16 | var fact:String = "" 17 | /// date 18 | var date:String = "" 19 | 20 | 21 | 22 | 23 | 24 | //MARK:- Facts saving mapping 25 | 26 | func coreDataMapping(data:SCDFactModel, managedPerson:NSManagedObject) { 27 | managedPerson.setValue(data.fact, forKey: "fact") 28 | managedPerson.setValue(data.date, forKey: "date") 29 | 30 | 31 | } 32 | 33 | //MARK:- Facts retrive mapping 34 | func factsMapping(factMapper:AnyObject) ->SCDFactModel { 35 | 36 | var data = SCDFactModel() 37 | data.fact = factMapper.value(forKey: "fact") as! String 38 | data.date = factMapper.value(forKey: "date") as! String 39 | 40 | return data 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDate.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 22-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | /** 13 | This class defines a day in the week of a certain month and provides 14 | information on whether or not the day falls in the month itself or not. 15 | If not, the day belongs to the previous or next month. 16 | */ 17 | final class JBDay { 18 | 19 | var dayValue: Int 20 | var monthValue: Int 21 | var yearValue: Int 22 | var isInMonth: Bool 23 | 24 | init(dayValue: Int, monthValue: Int, yearValue: Int, isInMonth: Bool) { 25 | self.dayValue = dayValue 26 | self.monthValue = monthValue 27 | self.yearValue = yearValue 28 | self .isInMonth = isInMonth 29 | } 30 | 31 | var date: Date? { 32 | let calendar = Calendar.current 33 | var comps = calendar.dateComponents([.day, .month, .year], from: Date()) 34 | comps.year = yearValue 35 | comps.month = monthValue 36 | comps.day = dayValue 37 | return Calendar.current.date(from: comps) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDateExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDateExtension.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 17-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension Date { 12 | 13 | func stripped() -> Date?{ 14 | 15 | let calendar = Calendar.current 16 | var components = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: self) 17 | components.hour = 0 18 | components.minute = 0 19 | components.second = 0 20 | let strippedDate = calendar.date(from: components) 21 | 22 | return strippedDate 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDatePickerContentVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDatePickerContentVC.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 09-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class JBDatePickerContentVC: UIViewController, UIScrollViewDelegate { 12 | 13 | // MARK: - Properties 14 | unowned let datePickerView: JBDatePickerView 15 | let scrollView: UIScrollView 16 | var presentedMonthView: MonthView 17 | var scrollDirection: JBScrollDirection = .none 18 | private var monthViews = [MonthViewIdentifier : MonthView]() 19 | 20 | ///flag that helps us preventing presentation while another presentation is still going on 21 | private var isPresenting = false 22 | 23 | private var currentPage = 1 24 | private var pageChanged: Bool { 25 | get { 26 | return currentPage == 1 ? false : true 27 | } 28 | } 29 | 30 | private var scrollViewBounds: CGRect { 31 | return scrollView.bounds 32 | } 33 | 34 | 35 | // MARK: - Initialization 36 | 37 | init(datePickerView: JBDatePickerView, frame: CGRect, presentedDate: Date) { 38 | 39 | self.datePickerView = datePickerView 40 | self.scrollView = UIScrollView(frame: frame) 41 | 42 | //create the current Monthview for the current date and fill it with weekviews. 43 | presentedMonthView = MonthView(datePickerView: datePickerView, date: presentedDate, isPresented: true) 44 | presentedMonthView.createWeekViews() 45 | 46 | super.init(nibName: nil, bundle: nil) 47 | 48 | //setup scrollView. Give it a contentsize of 3 times the width because it will hold 3 monthViews 49 | scrollView.contentSize = CGSize(width: frame.width * 3, height: frame.height) 50 | scrollView.showsHorizontalScrollIndicator = false 51 | scrollView.showsVerticalScrollIndicator = false 52 | scrollView.layer.masksToBounds = true 53 | scrollView.isPagingEnabled = true 54 | scrollView.delegate = self 55 | 56 | addInitialMonthViews(for: presentedMonthView.date) 57 | } 58 | 59 | required init?(coder aDecoder: NSCoder) { 60 | fatalError("init(coder:) has not been implemented") 61 | } 62 | 63 | // MARK: - Adding of MonthViews 64 | 65 | /** 66 | Fills the scrollView of the contentController 67 | with the initial three monthViews 68 | 69 | - Parameter date: the Date object to pass 70 | 71 | */ 72 | private func addInitialMonthViews(for date: Date) { 73 | 74 | //add the three monthViews to the scrollview 75 | addMonthView(presentedMonthView, withIdentifier: .presented) 76 | addMonthView(getPreviousMonthView(for: date), withIdentifier: .previous) 77 | addMonthView(getNextMonthView(for: date), withIdentifier: .next) 78 | 79 | } 80 | 81 | 82 | /** 83 | Adds the given monthView to the contentControllers scrollView and updates 84 | the given monthViews frame origin to place it in the correct position. 85 | 86 | - Parameter monthView: the MonthView to be added 87 | - Parameter identifier: can be .previous, .presented or .next 88 | 89 | */ 90 | private func addMonthView(_ monthView: MonthView, withIdentifier identifier: MonthViewIdentifier) { 91 | 92 | monthView.frame.origin = CGPoint(x: scrollView.bounds.width * CGFloat(identifier.rawValue), y: 0) 93 | monthViews[identifier] = monthView 94 | scrollView.addSubview(monthView) 95 | 96 | } 97 | 98 | ///returns the previous monthView for a given date 99 | private func getPreviousMonthView(for date: Date) -> MonthView { 100 | 101 | let cal = Calendar.current 102 | var comps = cal.dateComponents([.month, .year], from: date) 103 | comps.month! -= 1 104 | let firstDateOfPreviousMonth = cal.date(from: comps)! 105 | let previousMonthView = MonthView(datePickerView: datePickerView, date: firstDateOfPreviousMonth, isPresented: false) 106 | 107 | //this is what gives new new monthView it's initial frame 108 | previousMonthView.frame = scrollView.frame 109 | previousMonthView.createWeekViews() 110 | 111 | return previousMonthView 112 | } 113 | 114 | ///returns the next monthView for a given date 115 | private func getNextMonthView(for date: Date) -> MonthView { 116 | 117 | let cal = Calendar.current 118 | var comps = cal.dateComponents([.month, .year], from: date) 119 | comps.month! += 1 120 | let firstDateOfNextMonth = cal.date(from: comps)! 121 | let nextMonthView = MonthView(datePickerView: datePickerView, date: firstDateOfNextMonth, isPresented: false) 122 | 123 | //this is what gives new new monthView it's initial frame 124 | nextMonthView.frame = scrollView.frame 125 | nextMonthView.createWeekViews() 126 | 127 | return nextMonthView 128 | } 129 | 130 | // MARK: - Reloading and replacing of MonthViews 131 | 132 | /** 133 | Updates the frame of the scrollView and reloads the monthViews present 134 | When called, scrolls to presented monthView 135 | 136 | - Parameter frame: the frame to update to 137 | - Note: is only called on initial load of datePicker 138 | 139 | */ 140 | func updateScrollViewFrame(_ frame: CGRect) { 141 | 142 | if frame != .zero { 143 | scrollView.frame = frame 144 | scrollView.contentSize = CGSize(width: frame.size.width * 3, height: frame.size.height) 145 | } 146 | 147 | let monthViewFrame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height) 148 | 149 | for monthView in monthViews.values { 150 | 151 | monthView.reloadSubViewsWithFrame(monthViewFrame) 152 | } 153 | 154 | reloadMonthViews() 155 | 156 | if let presentedMonthView = monthViews[.presented] { 157 | 158 | //scroll to presented month 159 | scrollView.scrollRectToVisible(presentedMonthView.frame, animated: false) 160 | } 161 | } 162 | 163 | 164 | /** 165 | For each monthView this method updates the origin, then removes the monthView from the scrollView 166 | and adds them again. 167 | */ 168 | private func reloadMonthViews() { 169 | 170 | for (identifier, monthView) in monthViews { 171 | 172 | monthView.frame.origin.x = CGFloat(identifier.rawValue) * scrollView.frame.width 173 | 174 | //this will not deinitialize, because there's still a reference to this monthView object 175 | monthView.removeFromSuperview() 176 | scrollView.addSubview(monthView) 177 | } 178 | } 179 | 180 | /** 181 | Replaces the identifier of a monthView with another identifier, so it's gets another role. The presented monthView will, for example, become the next monthView. The frame origin of the monthView involved will also be adjusted and scrolled into position if needed. 182 | 183 | - Parameter monthView: the monthView involved 184 | - Parameter identifier: the new identifier that the monthView will get 185 | - Parameter shouldScrollToPosition: a boolean that determines if the monthView's frame should scroll into position or not 186 | 187 | */ 188 | private func replaceMonthViewIdentifier(_ monthView: MonthView, with identifier: MonthViewIdentifier, shouldScrollToPosition: Bool) { 189 | 190 | //adjust frame to the frame that comes with the new identifier (the new role) 191 | var monthViewFrame = monthView.frame 192 | monthViewFrame.origin.x = monthViewFrame.width * CGFloat(identifier.rawValue) 193 | monthView.frame = monthViewFrame 194 | 195 | //update the monthViews dictionary 196 | monthViews[identifier] = monthView 197 | 198 | //scroll the new 'presented' monthView into the presented position. 199 | //this will also cause the currentPage to be set to 1 again by the didScroll delegate method 200 | if shouldScrollToPosition { 201 | scrollView.scrollRectToVisible(monthViewFrame, animated: false) 202 | } 203 | } 204 | 205 | 206 | // MARK: - Scrolling MonthViews 207 | 208 | private func scrolledToPreviousMonth() { 209 | 210 | guard let previousMonthView = monthViews[.previous], let presentedMonthView = monthViews[.presented] else { return } 211 | 212 | //remove next monthView, this will be replaced by presented monthView 213 | monthViews[.next]?.removeFromSuperview() 214 | 215 | //replace previous monthView identifier with 'presented' identifier and set isPresented value 216 | replaceMonthViewIdentifier(previousMonthView, with: .presented, shouldScrollToPosition: true) 217 | previousMonthView.isPresented = true 218 | 219 | //replace presented monthView identifier with 'next' identifier and set isPresented value 220 | replaceMonthViewIdentifier(presentedMonthView, with: .next, shouldScrollToPosition: false) 221 | presentedMonthView.isPresented = false 222 | 223 | //add new monthView which will become the new 'previous' monthView 224 | addMonthView(getPreviousMonthView(for: previousMonthView.date), withIdentifier: .previous) 225 | 226 | } 227 | 228 | 229 | private func scrolledToNextMonth() { 230 | 231 | guard let nextMonthView = monthViews[.next], let presentedMonthView = monthViews[.presented] else { return } 232 | 233 | //remove previous monthView, this will be replaced by presented monthView 234 | monthViews[.previous]?.removeFromSuperview() 235 | 236 | //replace next monthView identifier with 'presented' identifier and set isPresented value 237 | replaceMonthViewIdentifier(nextMonthView, with: .presented, shouldScrollToPosition: true) 238 | nextMonthView.isPresented = true 239 | 240 | //replace presented monthView identifier with 'previous' identifier and set isPresented value 241 | replaceMonthViewIdentifier(presentedMonthView, with: .previous, shouldScrollToPosition: false) 242 | nextMonthView.isPresented = false 243 | 244 | //add new monthView which will become the new 'next' monthView 245 | addMonthView(getNextMonthView(for: nextMonthView.date), withIdentifier: .next) 246 | } 247 | 248 | // MARK: - UIScrollViewDelegate 249 | 250 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 251 | 252 | let page = Int(floor((scrollView.contentOffset.x - 253 | scrollView.frame.width / 2) / scrollView.frame.width) + 1) 254 | if currentPage != page { 255 | currentPage = page 256 | } 257 | 258 | } 259 | 260 | func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { 261 | 262 | //decide in which direction the user did scroll 263 | if decelerate { 264 | let rightBorderOfScrollView = scrollView.frame.width 265 | if scrollView.contentOffset.x <= rightBorderOfScrollView { 266 | scrollDirection = .toPrevious 267 | } else { 268 | scrollDirection = .toNext 269 | } 270 | } 271 | } 272 | 273 | func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 274 | 275 | if pageChanged { 276 | switch scrollDirection { 277 | case .toNext: scrolledToNextMonth() 278 | case .toPrevious: scrolledToPreviousMonth() 279 | case .none: break 280 | } 281 | } 282 | 283 | scrollDirection = .none 284 | } 285 | 286 | 287 | 288 | // MARK: - Presenting of monthViews 289 | 290 | func presentNextView() { 291 | if !isPresenting { 292 | 293 | guard let previous = monthViews[.previous], let presented = monthViews[.presented], let next = monthViews[.next] else { return } 294 | 295 | isPresenting = true 296 | 297 | UIView.animate(withDuration: 0.5, delay: 0, options: UIViewAnimationOptions(), animations: { 298 | 299 | //animate positions of monthViews 300 | previous.frame.origin.x -= self.scrollView.frame.width 301 | presented.frame.origin.x -= self.scrollView.frame.width 302 | next.frame.origin.x -= self.scrollView.frame.width 303 | 304 | }, completion: {_ in 305 | 306 | //replace identifiers 307 | self.replaceMonthViewIdentifier(presented, with: .previous, shouldScrollToPosition: false) 308 | self.replaceMonthViewIdentifier(next, with: .presented, shouldScrollToPosition: false) 309 | self.presentedMonthView = next 310 | 311 | //set isPresented value 312 | previous.isPresented = false 313 | self.presentedMonthView.isPresented = true 314 | 315 | //remove previous monthView 316 | previous.removeFromSuperview() 317 | 318 | //create and insert new 'next' monthView 319 | self.addMonthView(self.getNextMonthView(for: next.date), withIdentifier: .next) 320 | self.isPresenting = false 321 | 322 | }) 323 | } 324 | } 325 | 326 | 327 | func presentPreviousView() { 328 | if !isPresenting { 329 | 330 | guard let previous = monthViews[.previous], let presented = monthViews[.presented], let next = monthViews[.next] else { return } 331 | 332 | isPresenting = true 333 | 334 | UIView.animate(withDuration: 0.5, delay: 0, options: UIViewAnimationOptions(), animations: { 335 | 336 | //animate positions of monthViews 337 | previous.frame.origin.x += self.scrollView.frame.width 338 | presented.frame.origin.x += self.scrollView.frame.width 339 | next.frame.origin.x += self.scrollView.frame.width 340 | 341 | }, completion: {_ in 342 | 343 | //replace identifiers 344 | self.replaceMonthViewIdentifier(presented, with: .next, shouldScrollToPosition: false) 345 | self.replaceMonthViewIdentifier(previous, with: .presented, shouldScrollToPosition: false) 346 | self.presentedMonthView = previous 347 | 348 | //set isPresented value 349 | next.isPresented = false 350 | self.presentedMonthView.isPresented = true 351 | 352 | //remove previous monthView 353 | next.removeFromSuperview() 354 | 355 | //create and insert new 'previous' monthView 356 | self.addMonthView(self.getPreviousMonthView(for: previous.date), withIdentifier: .previous) 357 | self.isPresenting = false 358 | 359 | }) 360 | } 361 | } 362 | 363 | } 364 | 365 | 366 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDatePickerDayView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDatePickerDayView.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 13-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public final class JBDatePickerDayView: UIView { 12 | 13 | // MARK: - Properties 14 | private var index: Int! 15 | private var dayInfo: JBDay! 16 | weak private var weekView: JBDatePickerWeekView! 17 | weak private var monthView: JBDatePickerMonthView! 18 | weak var datePickerView: JBDatePickerView! 19 | public var date: Date? 20 | 21 | var isToday: Bool { 22 | return date == Date().stripped() 23 | } 24 | 25 | private var textLabel: UILabel! 26 | private weak var selectionView: JBDatePickerSelectionView? 27 | 28 | private let longPressArea: CGFloat = 40 29 | private var longPressAreaMaxX: CGFloat { return bounds.width + longPressArea } 30 | private var longPressAreaMaxY: CGFloat { return bounds.height + longPressArea } 31 | private var longPressAreaMin: CGFloat { return -longPressArea } 32 | 33 | 34 | // MARK: - Initialization 35 | 36 | init(datePickerView: JBDatePickerView, monthView: JBDatePickerMonthView, weekView: JBDatePickerWeekView, index: Int, dayInfo: JBDay) { 37 | 38 | self.datePickerView = datePickerView 39 | self.monthView = monthView 40 | self.weekView = weekView 41 | self.index = index 42 | self.dayInfo = dayInfo 43 | 44 | if let size = datePickerView.dayViewSize { 45 | 46 | let frame = CGRect(x: size.width * CGFloat(index), y: 0, width: size.width, height: size.height) 47 | super.init(frame: frame) 48 | 49 | } 50 | else{ 51 | super.init(frame: .zero) 52 | } 53 | 54 | //backgroundColor = randomColor() 55 | self.date = dayInfo.date 56 | labelSetup() 57 | 58 | if dayInfo.isInMonth { 59 | 60 | //set default color 61 | textLabel.textColor = datePickerView.delegate?.colorForDayLabelInMonth 62 | 63 | //check date is selectable, if not selectable, set colour and don't add gestures 64 | guard datePickerView.dateIsSelectable(date: date) else { 65 | self.textLabel.textColor = datePickerView.delegate?.colorForUnavaibleDay 66 | return 67 | } 68 | 69 | } 70 | else{ 71 | 72 | if let shouldShow = datePickerView.delegate?.shouldShowMonthOutDates { 73 | if shouldShow { 74 | textLabel.textColor = datePickerView.delegate?.colorForDayLabelOutOfMonth 75 | 76 | //check date is selectable, if not selectable, don't add gestures 77 | guard datePickerView.dateIsSelectable(date: date) else {return} 78 | } 79 | else{ 80 | self.isUserInteractionEnabled = false 81 | self.textLabel.isHidden = true 82 | } 83 | } 84 | } 85 | 86 | 87 | //highlight current day. Must come before selection of selected date, because it would override the text color set by select() 88 | if isToday { 89 | self.textLabel.textColor = datePickerView.delegate?.colorForCurrentDay 90 | } 91 | 92 | //select selected day 93 | if date == datePickerView.dateToPresent.stripped() { 94 | guard self.dayInfo.isInMonth else { return } 95 | datePickerView.selectedDateView = self 96 | //self.backgroundColor = randomColor() 97 | } 98 | 99 | //add tapgesture recognizer 100 | let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dayViewTapped)) 101 | self.addGestureRecognizer(tapGesture) 102 | 103 | //add longPress gesture recognizer 104 | let pressGesture = UILongPressGestureRecognizer(target: self, action: #selector(dayViewPressed(_:))) 105 | self.addGestureRecognizer(pressGesture) 106 | 107 | } 108 | 109 | public override init(frame: CGRect) { 110 | super.init(frame: frame) 111 | } 112 | 113 | required public init?(coder aDecoder: NSCoder) { 114 | fatalError("init(coder:) has not been implemented") 115 | } 116 | 117 | 118 | // MARK: - Label setup 119 | 120 | private func labelSetup() { 121 | 122 | textLabel = UILabel() 123 | textLabel.textAlignment = .center 124 | textLabel.translatesAutoresizingMaskIntoConstraints = false 125 | self.addSubview(textLabel) 126 | 127 | textLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true 128 | textLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true 129 | 130 | } 131 | 132 | private func setupLabelFont() { 133 | 134 | //get preferred font 135 | guard let preferredFont = datePickerView.delegate?.fontForDayLabel else { return } 136 | 137 | //get preferred size 138 | let preferredSize = preferredFont.fontSize 139 | let sizeOfFont: CGFloat 140 | 141 | //calculate fontsize to be used 142 | switch preferredSize { 143 | case .verySmall: sizeOfFont = min(frame.size.width, frame.size.height) / 3.5 144 | case .small: sizeOfFont = min(frame.size.width, frame.size.height) / 3 145 | case .medium: sizeOfFont = min(frame.size.width, frame.size.height) / 2.5 146 | case .large: sizeOfFont = min(frame.size.width, frame.size.height) / 2 147 | case .veryLarge: sizeOfFont = min(frame.size.width, frame.size.height) / 1.5 148 | } 149 | 150 | //get font to be used 151 | let fontToUse: UIFont 152 | switch preferredFont.fontName.isEmpty { 153 | case true: 154 | fontToUse = UIFont.systemFont(ofSize: sizeOfFont) 155 | case false: 156 | if let customFont = UIFont(name: preferredFont.fontName, size: sizeOfFont) { 157 | fontToUse = customFont 158 | } 159 | else { 160 | print("custom font '\(preferredFont.fontName)' for dayLabel not available. JBDatePicker will use system font instead") 161 | fontToUse = UIFont.systemFont(ofSize: sizeOfFont) 162 | } 163 | } 164 | 165 | textLabel.attributedText = NSMutableAttributedString(string: String(dayInfo.dayValue), attributes:[NSFontAttributeName: fontToUse]) 166 | 167 | } 168 | 169 | public override func layoutSubviews() { 170 | 171 | textLabel.frame = bounds 172 | setupLabelFont() 173 | } 174 | 175 | 176 | // MARK: - Touch handling 177 | 178 | @objc public func dayViewTapped() { 179 | datePickerView.didTapDayView(dayView: self) 180 | } 181 | 182 | @objc public func dayViewPressed(_ gesture: UILongPressGestureRecognizer) { 183 | 184 | //if selectedDateView exists and is self, return. Long pressing shouldn't do anything on selected day. 185 | if let selectedDate = datePickerView.selectedDateView { 186 | guard selectedDate != self else { return } 187 | } 188 | 189 | let location = gesture.location(in: self) 190 | 191 | switch gesture.state { 192 | case .began: 193 | semiSelect(animated: true) 194 | case .ended: 195 | if let selView = selectionView { 196 | selView.removeFromSuperview() 197 | } 198 | datePickerView.didTapDayView(dayView: self) 199 | 200 | case .changed: 201 | 202 | if !(longPressAreaMin...longPressAreaMaxX).contains(location.x) || !(longPressAreaMin...longPressAreaMaxY).contains(location.y) { 203 | 204 | semiDeselect(animated: true) 205 | 206 | //this will cancel the longpress gesture (and enable it again for the next time) 207 | gesture.isEnabled = false 208 | gesture.isEnabled = true 209 | } 210 | 211 | default: 212 | break 213 | } 214 | } 215 | 216 | // MARK: - Reloading 217 | 218 | public func reloadContent() { 219 | textLabel.frame = bounds 220 | setupLabelFont() 221 | 222 | //reload selectionView 223 | if let selView = selectionView { 224 | 225 | selView.frame = textLabel.frame 226 | selView.setNeedsDisplay() 227 | } 228 | 229 | } 230 | 231 | 232 | // MARK: - Selection & Deselection 233 | 234 | func select() { 235 | 236 | let selView = JBDatePickerSelectionView(dayView: self, frame: self.bounds, isSemiSelected: false) 237 | insertSubview(selView, at: 0) 238 | 239 | selView.translatesAutoresizingMaskIntoConstraints = false 240 | 241 | //pin selectionView horizontally and make it's width equal to the height of the datePickerview. This way it stays centered while rotating the device. 242 | selView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true 243 | selView.widthAnchor.constraint(equalTo: heightAnchor).isActive = true 244 | 245 | //pint it to the left and right 246 | selView.topAnchor.constraint(equalTo: topAnchor).isActive = true 247 | selView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true 248 | 249 | selectionView = selView 250 | 251 | //set textcolor to selected state 252 | textLabel.textColor = datePickerView.delegate?.colorForSelelectedDayLabel 253 | } 254 | 255 | func deselect() { 256 | 257 | if let selectionView = selectionView { 258 | selectionView.removeFromSuperview() 259 | } 260 | 261 | //set textcolor to default color 262 | switch isToday { 263 | case true: 264 | textLabel.textColor = datePickerView.delegate?.colorForCurrentDay 265 | case false: 266 | textLabel.textColor = dayInfo.isInMonth ? datePickerView.delegate?.colorForDayLabelInMonth : datePickerView.delegate?.colorForDayLabelOutOfMonth 267 | } 268 | } 269 | 270 | /** 271 | creates and shows a selection circle with a semi selected color 272 | 273 | - Parameter animated: if true, this will fade in the circle 274 | 275 | */ 276 | private func semiSelect(animated: Bool) { 277 | 278 | if let selectionView = selectionView { 279 | if animated { 280 | insertCircleViewAnimated(selectionView: selectionView) 281 | } 282 | else{ 283 | insertSubview(selectionView, at: 0) 284 | } 285 | } 286 | else { 287 | let selView = JBDatePickerSelectionView(dayView: self, frame: self.bounds, isSemiSelected: true) 288 | if animated { 289 | insertCircleViewAnimated(selectionView: selView) 290 | } 291 | else{ 292 | insertSubview(selView, at: 0) 293 | } 294 | selectionView = selView 295 | } 296 | } 297 | 298 | /** 299 | removes semi selected selection circle and removes circle from superview 300 | 301 | - Parameter animated: if true, this will fade the circle out before removal 302 | 303 | */ 304 | private func semiDeselect(animated: Bool) { 305 | 306 | switch animated { 307 | case true: 308 | removeCircleViewAnimated() 309 | case false: 310 | selectionView?.removeFromSuperview() 311 | } 312 | } 313 | 314 | ///just a helper that inserts the selection circle animated 315 | private func insertCircleViewAnimated(selectionView: JBDatePickerSelectionView) { 316 | 317 | selectionView.alpha = 0.0 318 | insertSubview(selectionView, at: 0) 319 | 320 | UIView.animate(withDuration: 0.2, animations: { 321 | 322 | selectionView.alpha = 1.0 323 | 324 | }) 325 | } 326 | 327 | ///just a helper that removes the selection circle animated 328 | private func removeCircleViewAnimated() { 329 | 330 | UIView.animate(withDuration: 0.2, animations: { 331 | 332 | self.selectionView?.alpha = 0.0 333 | 334 | }, completion: {_ in 335 | self.selectionView?.removeFromSuperview() 336 | }) 337 | } 338 | 339 | 340 | } 341 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDatePickerEnums.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDatePickerEnums.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 09-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum MonthViewIdentifier: Int { case previous, presented, next } 12 | enum JBScrollDirection { case none, toNext, toPrevious } 13 | 14 | //In a calendar, day, week, weekday, month, and year numbers are generally 1-based. So Sunday is 1. 15 | public enum JBWeekDay: Int { case sunday = 1, monday, tuesday, wednesday, thursday, friday, saturday } 16 | public enum JBSelectionShape { case circle, square, roundedRect } 17 | public enum JBFontSize { case verySmall, small, medium, large, veryLarge } 18 | 19 | //only for debugging 20 | func randomColor() -> UIColor{ 21 | 22 | let red = CGFloat(randomInt(min: 0, max: 255)) / 255 23 | let green = CGFloat(randomInt(min: 0, max: 255)) / 255 24 | let blue = CGFloat(randomInt(min: 0, max: 255)) / 255 25 | let randomColor = UIColor(red: red, green: green, blue: blue, alpha: 1) 26 | 27 | return randomColor 28 | } 29 | 30 | func randomInt(min: Int, max:Int) -> Int { 31 | return min + Int(arc4random_uniform(UInt32(max - min + 1))) 32 | } 33 | 34 | func randomFloat(min: Int, max:Int) -> Int { 35 | return min + Int(arc4random_uniform(UInt32(max - min + 1))) 36 | } 37 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDatePickerManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDatePickerManager.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 12-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | final class JBDatePickerManager { 12 | 13 | // MARK: - Properties 14 | private var components: DateComponents 15 | private unowned let datePickerView: JBDatePickerView 16 | private var calendar: Calendar = .current 17 | private var currentDate: Date = Date() 18 | private var startdayOfWeek: Int 19 | 20 | 21 | 22 | // MARK: - Initialization 23 | 24 | init(datePickerView: JBDatePickerView) { 25 | self.datePickerView = datePickerView 26 | self.components = calendar.dateComponents([.month, .day], from: currentDate) 27 | startdayOfWeek = (datePickerView.delegate?.firstWeekDay.rawValue)! 28 | 29 | //let user preference prevail about default 30 | calendar.firstWeekday = startdayOfWeek 31 | 32 | } 33 | 34 | 35 | // MARK: - Date information 36 | 37 | /** 38 | Gets the startdate and the enddate of the month of a certain date and also the amount of weeks 39 | for that month and all the days with their weekViewIndex and value 40 | 41 | - Parameter date: the Date object of the month that we want the info about 42 | - Returns: a tuple holding the startdate, the enddate, the number of weeks and 43 | an array holding dictionaries with the weekDayIndex as key and a JBDay object as value. 44 | The JBDay object holds the value (like 17) and a bool that determines that the day involved 45 | is included in the month or not. 46 | */ 47 | func getMonthInfoForDate(_ date: Date) -> (monthStartDay: Date, monthEndDay: Date, numberOfWeeksInMonth: Int, weekDayInfo: [[Int:JBDay]]) { 48 | 49 | var components = calendar.dateComponents([.year, .month, .weekOfMonth], from: date) 50 | 51 | //first day of the month 52 | components.day = 1 53 | let monthValue = components.month! 54 | let yearValue = components.year! 55 | let monthStartDay = calendar.date(from: components)! 56 | 57 | //last day of the month 58 | components.month! += 1 59 | let nextMonthValue = components.month! 60 | let nextYearValue = components.year! 61 | components.day! -= 1 62 | let monthEndDay = calendar.date(from: components)! 63 | 64 | //reset components 65 | components = calendar.dateComponents([.year, .month, .weekOfMonth], from: date) 66 | 67 | //last day of the previous month. We have to substract two because we went up to get the next month 68 | components.month! -= 1 69 | let previousMonthEndDay = calendar.date(from: components)! 70 | let previousMonthValue = components.month! 71 | let previousYearValue = components.year! 72 | 73 | //count of weeks in month 74 | var numberOfWeeksInMonth: Int = calendar.range(of: .weekOfMonth, in: .month, for: date)!.count 75 | 76 | //get dates that fall within the month 77 | let datesInRange = calendar.range(of: .day, in: .month, for: date) 78 | var monthDatesArray = [Int]() 79 | for value in 1.. 0 { 91 | for value in 1...numberOfDaysInNextMonth { 92 | nextMonthDatesArray.append(value) 93 | } 94 | } 95 | 96 | //get dates that fall within previous month 97 | var previousMonthDatesArray = [Int]() 98 | let datesInRangeOfPreviousMonth = calendar.range(of: .day, in: .month, for: previousMonthEndDay) 99 | let numberOfDaysInPreviousMonth = 7 - (7 - firstDayIndexInWeekView) 100 | let subRangeLowerBound = (datesInRangeOfPreviousMonth?.upperBound)! - numberOfDaysInPreviousMonth 101 | let upperBound = (datesInRangeOfPreviousMonth?.upperBound)! 102 | 103 | if subRangeLowerBound < upperBound { 104 | for value in subRangeLowerBound.. numberOfWeeksInMonth * 7 { 112 | numberOfWeeksInMonth += 1 113 | } 114 | 115 | //create array of dictionaries that we well return in the end 116 | var weeksInMonthInformationToReturn = [[Int:JBDay]]() 117 | 118 | //this value holds 0 to the number of days in a month 119 | var dayOfMonthIndex: Int = 0 120 | 121 | for weekIndex in 0..= 1 else {continue} 141 | 142 | dayOfWeekIndex = firstDayIndexInWeekView 143 | 144 | for _ in 0.. DateComponents { 215 | 216 | return calendar.dateComponents([.year, .month, .weekOfMonth, .day], from: date) 217 | 218 | } 219 | 220 | /** 221 | This is a correctionFactor. A day that falls on a thursday will always have weekday 5. Sunday is 1, Saterday is 7. However, in the weekView, this will be indexnumber 4 when week starts at sunday, and indexnumber 3 when week starts on a monday. If the week was to start on a thursday, the correctionfactor will be 5. Because this day will get index 0 in the weekView in that case. 222 | The function basically returns this dictionary: [-6:1, -5:2, -4:3, -3:4, -2:5, -1:6, 0:0, 1:1, 2:2, 3:3, 4:4, 5:5, 6:6] 223 | */ 224 | private func indexForDate(_ weekDay: Int) -> Int { 225 | 226 | let basicIndex = weekDay - startdayOfWeek 227 | 228 | if basicIndex < 0 { 229 | return basicIndex + 7 230 | } 231 | else{ 232 | return basicIndex 233 | } 234 | 235 | } 236 | 237 | 238 | 239 | } 240 | 241 | 242 | 243 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDatePickerMonthView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDatePickerMonthView.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 09-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public final class JBDatePickerMonthView: UIStackView { 12 | 13 | 14 | // MARK: - Properties 15 | 16 | weak var datePickerView: JBDatePickerView! 17 | var date: Date! 18 | var isPresented: Bool! { 19 | 20 | willSet{ 21 | if newValue == true{ 22 | //this will eventually call the delegate 23 | datePickerView.presentedMonthView = self 24 | } 25 | } 26 | } 27 | 28 | public var monthDescription: String! 29 | var monthInfo: (monthStartDay: Date, monthEndDay: Date, numberOfWeeksInMonth: Int, weekDayInfo: [[Int:JBDay]])! 30 | var numberOfWeeks: Int! 31 | var weekViews: [JBDatePickerWeekView]! 32 | 33 | // MARK: - Initialization 34 | 35 | init(datePickerView: JBDatePickerView, date: Date, isPresented: Bool) { 36 | 37 | self.datePickerView = datePickerView 38 | self.date = date 39 | self.isPresented = isPresented 40 | super.init(frame: .zero) 41 | 42 | self.axis = .vertical 43 | self.distribution = .fillEqually 44 | 45 | //self.backgroundColor = randomColor() 46 | 47 | let datePickerManager = datePickerView.manager 48 | self.monthInfo = datePickerManager?.getMonthInfoForDate(self.date) 49 | self.numberOfWeeks = monthInfo.numberOfWeeksInMonth 50 | self.monthDescription = datePickerView.monthDescriptionForDate(self.date) 51 | 52 | //this is needed to inform the delegate about the presented month 53 | //the property observer isn't called on initialization 54 | if isPresented { 55 | datePickerView.presentedMonthView = self 56 | } 57 | 58 | } 59 | 60 | override init(frame: CGRect) { 61 | super.init(frame: frame) 62 | } 63 | 64 | required public init(coder aDecoder: NSCoder) { 65 | fatalError("init(coder:) has not been implemented") 66 | } 67 | 68 | 69 | // MARK: - Reloading 70 | 71 | func reloadSubViewsWithFrame(_ frame: CGRect) { 72 | self.frame = frame 73 | 74 | } 75 | 76 | // MARK: - Create weekviews 77 | 78 | func createWeekViews() { 79 | 80 | weekViews = [JBDatePickerWeekView]() 81 | 82 | for i in 0...5 { 83 | let weekView = JBDatePickerWeekView(datePickerView: datePickerView, monthView: self, index: i) 84 | weekViews.append(weekView) 85 | self.addArrangedSubview(weekView) 86 | } 87 | } 88 | 89 | 90 | 91 | 92 | } 93 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDatePickerSelectionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDatePickerSelectionView.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 19-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class JBDatePickerSelectionView: UIView { 12 | 13 | // MARK: - Computed properties 14 | 15 | private let padding: CGFloat = 10 16 | 17 | private var radius: CGFloat { 18 | 19 | return (min(frame.height, frame.width) - padding) / 2 20 | } 21 | 22 | 23 | private var circlePath: CGPath { 24 | let arcCenter = CGPoint(x: frame.width / 2, y: frame.height / 2) 25 | let startAngle = CGFloat(0) 26 | let endAngle = CGFloat.pi * 2.0 27 | let clockwise = true 28 | let path = UIBezierPath(arcCenter: arcCenter, radius: radius, 29 | startAngle: startAngle, endAngle: endAngle, clockwise: clockwise).cgPath 30 | 31 | return path 32 | 33 | } 34 | 35 | private var squarePath: CGPath { 36 | 37 | let pathSize = radius * 2 38 | let center = CGPoint(x: frame.width / 2, y: frame.height / 2) 39 | let startPoint = CGPoint(x: center.x - radius, y: center.y - radius) 40 | let path = UIBezierPath(rect: CGRect(x: startPoint.x, y: startPoint.y, width: pathSize, height: pathSize)) 41 | 42 | return path.cgPath 43 | } 44 | 45 | private var roundedRectPath: CGPath { 46 | 47 | let pathSize = radius * 2 48 | let cornerRadiusForShape = radius / 2 49 | let center = CGPoint(x: frame.width / 2, y: frame.height / 2) 50 | let startPoint = CGPoint(x: center.x - radius, y: center.y - radius) 51 | let path = UIBezierPath(roundedRect: CGRect(x: startPoint.x, y: startPoint.y, width: pathSize, height: pathSize), cornerRadius: cornerRadiusForShape) 52 | 53 | return path.cgPath 54 | } 55 | 56 | private var fillColor: UIColor { 57 | 58 | switch isSemiSelected { 59 | case true: 60 | return (dayView.datePickerView.delegate?.colorForSemiSelectedSelectionCircle)! 61 | case false: 62 | switch dayView.isToday { 63 | case true: 64 | return (dayView.datePickerView.delegate?.colorForSelectionCircleForToday)! 65 | case false: 66 | return (dayView.datePickerView.delegate?.colorForSelectionCircleForOtherDate)! 67 | } 68 | } 69 | } 70 | 71 | private var selectionPath: CGPath { 72 | 73 | guard let delegate = dayView.datePickerView.delegate else { return circlePath } 74 | 75 | switch delegate.selectionShape { 76 | case .circle: 77 | return circlePath 78 | case .square: 79 | return squarePath 80 | case .roundedRect: 81 | return roundedRectPath 82 | } 83 | } 84 | 85 | // MARK: - Stored properties 86 | 87 | private unowned let dayView: JBDatePickerDayView 88 | var isSemiSelected: Bool 89 | 90 | // MARK: - Initialization 91 | 92 | init(dayView: JBDatePickerDayView, frame: CGRect, isSemiSelected: Bool) { 93 | self.dayView = dayView 94 | self.isSemiSelected = isSemiSelected 95 | super.init(frame: frame) 96 | backgroundColor = .clear 97 | shapeLayer().fillColor = fillColor.cgColor 98 | } 99 | 100 | required init?(coder aDecoder: NSCoder) { 101 | fatalError("init(coder:) has not been implemented") 102 | } 103 | 104 | override class var layerClass: AnyClass { 105 | return CAShapeLayer.self 106 | } 107 | 108 | private func shapeLayer() -> CAShapeLayer { 109 | return layer as! CAShapeLayer 110 | } 111 | 112 | // MARK: - Drawing 113 | 114 | override func layoutSubviews() { 115 | super.layoutSubviews() 116 | 117 | shapeLayer().path = selectionPath 118 | } 119 | 120 | 121 | 122 | } 123 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDatePickerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDatePickerView.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 09-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | typealias ContentController = JBDatePickerContentVC 12 | typealias Manager = JBDatePickerManager 13 | typealias MonthView = JBDatePickerMonthView 14 | typealias WeekDaysView = JBDatePickerWeekDaysView 15 | 16 | public final class JBDatePickerView: UIView { 17 | 18 | // MARK: - Properties 19 | 20 | var contentController: ContentController! 21 | var manager: Manager! 22 | var weekViewSize: CGSize! 23 | var dayViewSize: CGSize! 24 | var dateToPresent: Date! 25 | var weekdaysView: WeekDaysView! 26 | fileprivate var dateFormatter = DateFormatter() 27 | 28 | public weak var delegate: JBDatePickerViewDelegate? { 29 | didSet{ 30 | commonInit() 31 | } 32 | } 33 | 34 | public var presentedMonthView: JBDatePickerMonthView! { 35 | didSet { 36 | delegate?.didPresentOtherMonth(presentedMonthView) 37 | layoutIfNeeded() 38 | } 39 | } 40 | 41 | public var selectedDateView: JBDatePickerDayView! { 42 | 43 | willSet { 44 | selectedDateView?.deselect() 45 | } 46 | 47 | didSet { 48 | selectedDateView.select() 49 | dateToPresent = selectedDateView.date 50 | } 51 | } 52 | 53 | 54 | // MARK: - Initialization 55 | 56 | private func commonInit() { 57 | 58 | //initialize datePickerManager 59 | manager = Manager(datePickerView: self) 60 | 61 | //initialize contentController with preferred (or current) date 62 | dateToPresent = delegate?.dateToShow ?? Date() 63 | contentController = ContentController(datePickerView: self, frame: bounds, presentedDate: dateToPresent) 64 | 65 | //add scrollView 66 | addSubview(contentController.scrollView) 67 | contentController.scrollView.translatesAutoresizingMaskIntoConstraints = false 68 | 69 | //create and add weekdayView 70 | weekdaysView = WeekDaysView(datePickerView: self) 71 | addSubview(weekdaysView) 72 | weekdaysView.translatesAutoresizingMaskIntoConstraints = false 73 | 74 | //pin datePickerView to left, right and bottom of scrollView. 75 | leftAnchor.constraint(equalTo: contentController.scrollView.leftAnchor).isActive = true 76 | rightAnchor.constraint(equalTo: contentController.scrollView.rightAnchor).isActive = true 77 | bottomAnchor.constraint(equalTo: contentController.scrollView.bottomAnchor).isActive = true 78 | 79 | //pin weekDaysView to left, right and top of datePickerView 80 | weekdaysView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true 81 | weekdaysView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true 82 | weekdaysView.topAnchor.constraint(equalTo: topAnchor).isActive = true 83 | 84 | //add heightconstraint for weekDaysview 85 | weekdaysView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: (delegate?.weekDaysViewHeightRatio)!).isActive = true 86 | 87 | } 88 | } 89 | 90 | 91 | extension JBDatePickerView { 92 | 93 | /** 94 | Updates the layout of JBDatePicker. This makes sure that elements in JBDatePicker that need a frame, will get their frame. 95 | */ 96 | public func updateLayout() { 97 | 98 | guard delegate != nil else { 99 | 100 | print("JBDatePickerView warning: there is no delegate set. This is needed for JBDatePickerView to work correctly") 101 | return 102 | } 103 | 104 | guard weekdaysView != nil else { return } 105 | 106 | let width = bounds.size.width 107 | let availableRectForScrollView = CGRect(x: bounds.origin.x, y: weekdaysView.bounds.height, width: width, height: bounds.size.height - weekdaysView.bounds.height) 108 | 109 | //adjust scrollView frame to available space 110 | contentController.updateScrollViewFrame(availableRectForScrollView) 111 | } 112 | 113 | public override func layoutSubviews() { 114 | super.layoutSubviews() 115 | 116 | updateLayout() 117 | } 118 | } 119 | 120 | 121 | extension JBDatePickerView { 122 | 123 | func monthDescriptionForDate(_ date: Date) -> String { 124 | 125 | let monthFormatString = "MMMM yyyy" 126 | dateFormatter.dateFormat = monthFormatString 127 | if let preferredLanguage = Bundle.main.preferredLocalizations.first { 128 | if delegate?.shouldLocalize == true { 129 | dateFormatter.locale = Locale(identifier: preferredLanguage) 130 | } 131 | } 132 | 133 | return dateFormatter.string(from: date) 134 | } 135 | 136 | func dateIsSelectable(date: Date?) -> Bool { 137 | 138 | //default true, pass check to delegate if exists 139 | return delegate?.shouldAllowSelectionOfDay(date) ?? true 140 | } 141 | 142 | ///this will call the delegate as well as set the selectedDate on the datePicker. 143 | func didTapDayView(dayView: JBDatePickerDayView) { 144 | selectedDateView = dayView 145 | delegate?.didSelectDay(dayView) 146 | } 147 | } 148 | 149 | 150 | extension JBDatePickerView { 151 | 152 | ///scrolls the next month into the visible area and creates an new 'next' month waiting in line. 153 | public func loadNextView() { 154 | contentController.presentNextView() 155 | } 156 | 157 | ///scrolls the previous month into the visible area and creates an new 'previous' month waiting in line. 158 | public func loadPreviousView() { 159 | contentController.presentPreviousView() 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDatePickerViewDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDatePickerViewDelegate.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 17-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol JBDatePickerViewDelegate: class { 12 | 13 | /** 14 | Is called when the user selected a day 15 | - parameter dayView: the dayView the user selected 16 | - note: 17 | Implementing this method is mandatory 18 | */ 19 | func didSelectDay(_ dayView: JBDatePickerDayView) 20 | 21 | /** 22 | Is called when the user swiped (or manually moved) to another month 23 | - parameter monthView: the monthView that is now 'on screen' 24 | - note: 25 | Implementing this method is optional. 26 | */ 27 | func didPresentOtherMonth(_ monthView: JBDatePickerMonthView) 28 | 29 | /** 30 | Is called to check if any particular date is selectable by the picker 31 | - parameter date: the date to check if allowed 32 | - note: 33 | Implementing this method is optional. 34 | */ 35 | func shouldAllowSelectionOfDay(_ date: Date?) -> Bool 36 | 37 | /** 38 | Is called when setting up the calendar view as an override point for customization of weekday labels 39 | - parameter calendar: calendar instance used by the calendar view 40 | - note: 41 | Implementing this method is optional. 42 | */ 43 | func weekdaySymbols(for calendar: Calendar) -> [String] 44 | 45 | /** 46 | Sets the day that determines which month is shown on initial load 47 | - note: 48 | Implementing this variable is optional. It's default is set the current date. 49 | */ 50 | var dateToShow: Date {get} 51 | 52 | 53 | /** 54 | Sets the first day of the week. 55 | - note: 56 | Implementing this variable is optional. It's default is set to the locale. 57 | */ 58 | var firstWeekDay: JBWeekDay {get} 59 | 60 | 61 | /** 62 | Determines if a month should also show the dates of the previous and next month 63 | - note: 64 | Implementing this variable is optional. It's default is set to true. 65 | */ 66 | var shouldShowMonthOutDates: Bool {get} 67 | 68 | /** 69 | Determines if the weekday symbols and the month description should follow available localizations 70 | - note: 71 | Implementing this variable is optional. It's default is set to false. This means that the weekday symbols 72 | and the month description will be in the same language as the device language. If you want it to conform to the 73 | localization of your app, return true here. If you return true and your app is not localized, the weekday symbols and 74 | the month description will be in the development language. 75 | */ 76 | var shouldLocalize: Bool {get} 77 | 78 | 79 | // MARK: - General appearance properties 80 | 81 | /** 82 | Determines the height ratio of the weekDaysView compared to the total height 83 | 84 | - note: 85 | Implementing this variable is optional. It's default is set to 0.1 (10%). 86 | 87 | */ 88 | var weekDaysViewHeightRatio: CGFloat {get} 89 | 90 | /** 91 | Determines the shape that is used to indicate a selected date. Possiblilities are: 92 | .circle, .square, .roundedRect 93 | 94 | - note: 95 | Implementing this variable is optional. It's default is set to .circle. 96 | 97 | */ 98 | var selectionShape: JBSelectionShape { get } 99 | 100 | /** 101 | font of the date labels. Defaults to systemfont with a medium size. 102 | 103 | - Note: you can use any UIFont name you want, as long as it is available. If it's not available, JBDatePicker will 104 | use the systemfont instead. If you want to use the systemfont but customize it's size, use an empty string as the 105 | fontname. 106 | 107 | ## Usage Example: ## 108 | ```` 109 | //set custom font 110 | var fontForDayLabel: JBFont { 111 | return JBFont(name: "AvenirNext-MediumItalic", size: .medium) 112 | } 113 | 114 | //set system font with custom size 115 | var fontForDayLabel: JBFont { 116 | return JBFont(name: "", size: .large) 117 | } 118 | 119 | ```` 120 | */ 121 | var fontForDayLabel: JBFont { get } 122 | 123 | 124 | // MARK: - Text Color appearance properties 125 | 126 | ///color of any date label text that falls within the presented month 127 | var colorForDayLabelInMonth: UIColor { get } 128 | 129 | ///color of any date label text that falls out of the presented month and is part of the next or previous (but not presented) month 130 | var colorForDayLabelOutOfMonth: UIColor { get } 131 | 132 | ///color of any date label text that occurs outside the allowed selectable days (day earlier than earliest selectable or later than last selectable) 133 | var colorForUnavaibleDay: UIColor { get } 134 | 135 | ///color of the 'today' date label text 136 | var colorForCurrentDay: UIColor { get } 137 | 138 | ///color of any label text that is selected 139 | var colorForSelelectedDayLabel: UIColor { get } 140 | 141 | 142 | // MARK: - WeekdaysView appearance properties 143 | 144 | ///color of the bar which shows the 'mon' to 'sun' labels. Defaults to green. 145 | var colorForWeekDaysViewBackground: UIColor { get } 146 | 147 | ///color of the labels in the WeekdaysView bar that say 'mon' to 'sun'. Defaults to white. 148 | var colorForWeekDaysViewText: UIColor { get } 149 | 150 | 151 | /** 152 | font of the labels in the WeekdaysView bar that say 'mon' to 'sun'. Defaults to systemfont with 153 | a medium size. 154 | 155 | - Note: you can use any UIFont name you want, as long as it is available. If it's not available, JBDatePicker will 156 | use the systemfont instead. If you want to use the systemfont but customize it's size, use an empty string as the 157 | fontname. 158 | 159 | ## Usage Example: ## 160 | ```` 161 | //set custom font 162 | var fontForWeekDaysViewText: JBFont { 163 | return JBFont(name: "AvenirNext-MediumItalic", size: .medium) 164 | } 165 | 166 | //set system font with custom size 167 | var fontForWeekDaysViewText: JBFont { 168 | return JBFont(name: "", size: .large) 169 | } 170 | 171 | ```` 172 | */ 173 | var fontForWeekDaysViewText: JBFont { get } 174 | 175 | 176 | // MARK: - Selection Color appearance properties 177 | 178 | ///color of the selection circle for dates that aren't today 179 | var colorForSelectionCircleForOtherDate: UIColor { get } 180 | 181 | ///color of the selection circle for today 182 | var colorForSelectionCircleForToday: UIColor { get } 183 | 184 | ///color of the semi selected selection circle (that shows on a long press) 185 | var colorForSemiSelectedSelectionCircle: UIColor { get } 186 | 187 | } 188 | 189 | /** 190 | This protocol extension is used to make some of the delegate methods and variables optional by giving them a default implementation or value. 191 | */ 192 | public extension JBDatePickerViewDelegate { 193 | 194 | public func didPresentOtherMonth(_ monthView: JBDatePickerMonthView) {} 195 | public func shouldAllowSelectionOfDay(_ date: Date?) -> Bool { return true } 196 | public func weekdaySymbols(for calendar: Calendar) -> [String] { return calendar.shortStandaloneWeekdaySymbols } 197 | 198 | // MARK: - General defaults 199 | 200 | public var dateToShow: Date { return Date()} 201 | public var firstWeekDay: JBWeekDay { 202 | 203 | if let calendarValue = JBWeekDay(rawValue: Calendar.current.firstWeekday){ 204 | return calendarValue 205 | } 206 | else { 207 | return .monday 208 | } 209 | } 210 | 211 | public var shouldShowMonthOutDates: Bool { return true } 212 | public var shouldLocalize: Bool { return false } 213 | public var weekDaysViewHeightRatio: CGFloat { return 0.1 } 214 | public var selectionShape: JBSelectionShape { return .circle } 215 | public var fontForDayLabel: JBFont { return JBFont() } 216 | 217 | // MARK: - Color defaults 218 | 219 | public var colorForDayLabelInMonth: UIColor { return .darkGray } 220 | public var colorForDayLabelOutOfMonth: UIColor { return .lightGray } 221 | public var colorForUnavaibleDay: UIColor { return .lightGray } 222 | public var colorForCurrentDay: UIColor { return .red } 223 | public var colorForSelelectedDayLabel: UIColor { return .white } 224 | public var colorForWeekDaysViewBackground: UIColor { return UIColor(red: 81.0/255.0, green: 182.0/255.0, blue: 185.0/255.0, alpha: 1.0) } 225 | public var colorForWeekDaysViewText: UIColor { return .white } 226 | public var fontForWeekDaysViewText: JBFont { return JBFont() } 227 | public var colorForSelectionCircleForOtherDate: UIColor { return UIColor(red: 81.0/255.0, green: 182.0/255.0, blue: 185.0/255.0, alpha: 1.0) } 228 | public var colorForSelectionCircleForToday: UIColor { return UIColor(red: 255.0/255.0, green: 98.0/255.0, blue: 89.0/255.0, alpha: 1.0) } 229 | public var colorForSemiSelectedSelectionCircle: UIColor { return UIColor(red: 240/255, green: 240/255, blue: 240/255, alpha: 1.0) } 230 | } 231 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/Classes/JBDatePickerWeekDaysView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JBDatePickerWeekDaysView.swift 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 24-10-16. 6 | // Copyright © 2016 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public final class JBDatePickerWeekDaysView: UIStackView { 12 | 13 | // MARK: - Properties 14 | private weak var datePickerView: JBDatePickerView! 15 | private var firstWeekDay: JBWeekDay! 16 | private var weekdayNameSymbols = [String]() 17 | private var weekdayLabels = [UILabel]() 18 | private var weekdayLabelTextColor: UIColor! 19 | 20 | 21 | // MARK: - Initialization 22 | public init(datePickerView: JBDatePickerView) { 23 | self.datePickerView = datePickerView 24 | super.init(frame: .zero) 25 | setup() 26 | } 27 | 28 | public override init(frame: CGRect) { 29 | super.init(frame: frame) 30 | setup() 31 | } 32 | 33 | public required init(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | setup() 36 | } 37 | 38 | // MARK: - Setup 39 | 40 | private func setup() { 41 | guard datePickerView != nil else {return} 42 | 43 | //stackView setup 44 | self.axis = .horizontal 45 | self.distribution = .fillEqually 46 | self.translatesAutoresizingMaskIntoConstraints = false 47 | 48 | //get preferences 49 | firstWeekDay = datePickerView.delegate?.firstWeekDay 50 | 51 | //setup appearance 52 | self.weekdayLabelTextColor = datePickerView.delegate?.colorForWeekDaysViewText 53 | 54 | //get weekday name symbols 55 | var cal = Calendar.current 56 | if let preferredLanguage = Bundle.main.preferredLocalizations.first { 57 | if datePickerView.delegate?.shouldLocalize == true { 58 | cal.locale = Locale(identifier: preferredLanguage) 59 | } 60 | } 61 | weekdayNameSymbols = datePickerView.delegate?.weekdaySymbols(for: cal) ?? cal.shortStandaloneWeekdaySymbols 62 | 63 | //adjust order of weekDayNameSymbols if needed 64 | let firstWeekdayIndex = firstWeekDay.rawValue - 1 65 | if firstWeekdayIndex >= 0 { 66 | 67 | //create new array order by slicing according to firstweekday 68 | let sliceOne = weekdayNameSymbols[firstWeekdayIndex...6] 69 | let sliceTwo = weekdayNameSymbols[0.. 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DatePicker/JBDatePicker/JBDatePicker.h: -------------------------------------------------------------------------------- 1 | // 2 | // JBDatePicker.h 3 | // JBDatePicker 4 | // 5 | // Created by Joost van Breukelen on 04-04-17. 6 | // Copyright © 2017 Joost van Breukelen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for JBDatePicker. 12 | FOUNDATION_EXPORT double JBDatePickerVersionNumber; 13 | 14 | 15 | 16 | //! Project version string for JBDatePicker. 17 | FOUNDATION_EXPORT const unsigned char JBDatePickerVersionString[]; 18 | 19 | // In this header, you should import all the public headers of your framework using statements like #import 20 | 21 | 22 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/DidYouKnowFacts.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "date": "Jan 1", 4 | "fact": " 11% of people are left handed" 5 | }, 6 | { 7 | "date": "Jan 2", 8 | "fact": " August has the highest percentage of births" 9 | }, 10 | { 11 | "date": "Jan 3", 12 | "fact": " unless food is mixed with saliva you can't taste it" 13 | }, 14 | { 15 | "date": "Jan 4", 16 | "fact": " the average person falls asleep in 7 minutes" 17 | }, 18 | { 19 | "date": "Jan 5", 20 | "fact": " a bear has 42 teeth" 21 | }, 22 | { 23 | "date": "Jan 6", 24 | "fact": " an ostrich's eye is bigger than its brain" 25 | }, 26 | { 27 | "date": "Jan 7", 28 | "fact": " lemons contain more sugar than strawberries" 29 | }, 30 | { 31 | "date": "Jan 8", 32 | "fact": " 8% of people have an extra rib" 33 | }, 34 | { 35 | "date": "Jan 9", 36 | "fact": " 85% of plant life is found in the ocean" 37 | }, 38 | { 39 | "date": "Jan 10", 40 | "fact": " Ralph Lauren's original name was Ralph Lifshitz" 41 | }, 42 | { 43 | "date": "Jan 11", 44 | "fact": " rabbits like licorice" 45 | }, 46 | { 47 | "date": "Jan 12", 48 | "fact": " the Hawaiian alphabet has 13 letters" 49 | }, 50 | { 51 | "date": "Jan 13", 52 | "fact": " 'Topolino' is the name for Mickey Mouse Italy" 53 | }, 54 | { 55 | "date": "Jan 14", 56 | "fact": " a lobsters blood is colorless but when exposed to oxygen it turns blue" 57 | }, 58 | { 59 | "date": "Jan 15", 60 | "fact": " armadillos have 4 babies at a time and are all the same sex" 61 | }, 62 | { 63 | "date": "Jan 16", 64 | "fact": " reindeer like bananas" 65 | }, 66 | { 67 | "date": "Jan 17", 68 | "fact": " the longest recorded flight of a chicken was 13 seconds" 69 | }, 70 | { 71 | "date": "Jan 18", 72 | "fact": " birds need gravity to swallow" 73 | }, 74 | { 75 | "date": "Jan 19", 76 | "fact": "the most commonly used letter in the alphabet is E" 77 | }, 78 | { 79 | "date": "Jan 20", 80 | "fact": " the 3 most common languages in the world are Mandarin Chinese, Spanish and English" 81 | }, 82 | { 83 | "date": "Jan 21", 84 | "fact": " dreamt is the only word that ends in mt" 85 | }, 86 | { 87 | "date": "Jan 22", 88 | "fact": " the first letters of the months July through to November spell JASON" 89 | }, 90 | { 91 | "date": "Jan 23", 92 | "fact": " a cat has 32 muscles in each ear" 93 | }, 94 | { 95 | "date": "Jan 24", 96 | "fact": " Perth is Australia's windiest city" 97 | }, 98 | { 99 | "date": "Jan 25", 100 | "fact": " Elvis's middle name was Aron" 101 | }, 102 | { 103 | "date": "Jan 26", 104 | "fact": " goldfish can see both infrared and ultraviolet light" 105 | }, 106 | { 107 | "date": "Jan 27", 108 | "fact": " the smallest bones in the human body are found in your ear" 109 | }, 110 | { 111 | "date": "Jan 28", 112 | "fact": " cats spend 66% of their life asleep" 113 | }, 114 | { 115 | "date": "Jan 29", 116 | "fact": " Switzerland eats the most chocolate equating to 10 kilos per person per year" 117 | }, 118 | { 119 | "date": "Jan 30", 120 | "fact": " money is the number one thing that couples argue about" 121 | }, 122 | { 123 | "date": "Jan 31", 124 | "fact": " macadamia nuts are toxic to dogs" 125 | }, 126 | { 127 | "date": "Feb 1", 128 | "fact": " when lightning strikes it can reach up to 30,000 degrees celsius (54,000 degrees fahrenheit)" 129 | }, 130 | { 131 | "date": "Feb 2", 132 | "fact": " spiders are arachnids and not insects" 133 | }, 134 | { 135 | "date": "Feb 3", 136 | "fact": " each time you see a full moon you always see the same side" 137 | }, 138 | { 139 | "date": "Feb 4", 140 | "fact": " stewardesses is the longest word that is typed with only the left hand" 141 | }, 142 | { 143 | "date": "Feb 5", 144 | "fact": " honey is the only natural food which never spoils" 145 | }, 146 | { 147 | "date": "Feb 6", 148 | "fact": " M&M's chocolate stands for the initials for its inventors Mars and Murrie" 149 | }, 150 | { 151 | "date": "Feb 7", 152 | "fact": " that you burn more calories eating celery than it contains (the more you eat the thinner you become)" 153 | }, 154 | { 155 | "date": "Feb 8", 156 | "fact": " the only continent with no active volcanoes is Australia" 157 | }, 158 | { 159 | "date": "Feb 9", 160 | "fact": " the longest street in the world is Yonge street in Toronto Canada measuring 1,896 km (1,178 miles)" 161 | }, 162 | { 163 | "date": "Feb 10", 164 | "fact": " about 90% of the worlds population kisses" 165 | }, 166 | { 167 | "date": "Feb 11", 168 | "fact": " Coca-Cola originally contained cocaine" 169 | }, 170 | { 171 | "date": "Feb 12", 172 | "fact": " the Internet was originally called ARPANet (Advanced Research Projects Agency Network) designed by the US department of defense" 173 | }, 174 | { 175 | "date": "Feb 13", 176 | "fact": " toilets use 35% of indoor water use" 177 | }, 178 | { 179 | "date": "Feb 14", 180 | "fact": " the fortune cookie was invented in San Francisco" 181 | }, 182 | { 183 | "date": "Feb 15", 184 | "fact": " Koalas sleep around 18 hours a day" 185 | }, 186 | { 187 | "date": "Feb 16", 188 | "fact": " the first Burger King was opened in Florida Miami in 1954" 189 | }, 190 | { 191 | "date": "Feb 17", 192 | "fact": " all insects have 6 legs" 193 | }, 194 | { 195 | "date": "Feb 18", 196 | "fact": " the croissant was invented in Austria" 197 | }, 198 | { 199 | "date": "Feb 19", 200 | "fact": " In eastern Africa you can buy beer brewed from bananas" 201 | }, 202 | { 203 | "date": "Feb 20", 204 | "fact": " African Grey Parrots have vocabularies of over 200 words" 205 | }, 206 | { 207 | "date": "Feb 21", 208 | "fact": " a giraffe can clean its ears with its 21 inch tongue" 209 | }, 210 | { 211 | "date": "Feb 22", 212 | "fact": " Australia was originally called New Holland" 213 | }, 214 | { 215 | "date": "Feb 23", 216 | "fact": " 'Lonely Planet' for travelers is based in Melbourne Australia" 217 | }, 218 | { 219 | "date": "Feb 24", 220 | "fact": " the sentence \"the quick brown fox jumps over the lazy dog\" uses every letter in the English alphabet" 221 | }, 222 | { 223 | "date": "Feb 25", 224 | "fact": " the Grand Canyon can hold around 900 trillion footballs" 225 | }, 226 | { 227 | "date": "Feb 26", 228 | "fact": " all the blinking in one day equates to having your eyes closed for 30 minutes" 229 | }, 230 | { 231 | "date": "Feb 27", 232 | "fact": " your foot has 26 bones in it" 233 | }, 234 | { 235 | "date": "Feb 28", 236 | "fact": " the average human brain contains around 78% water" 237 | }, 238 | { 239 | "date": "Feb 29", 240 | "fact": " 1 nautical knot equates to 1.852 Kph (1.150 mph)" 241 | }, 242 | { 243 | "date": "Mar 1", 244 | "fact": " if you add up all the numbers from 1 to 100 consecutively (1 + 2 + 3...) it totals 5050" 245 | }, 246 | { 247 | "date": "Mar 2", 248 | "fact": " sponges hold more cold water than hot" 249 | }, 250 | { 251 | "date": "Mar 3", 252 | "fact": " lightning strikes the Earth 6,000 times every minute" 253 | }, 254 | { 255 | "date": "Mar 4", 256 | "fact": " fire usually moves faster uphill than downhill" 257 | }, 258 | { 259 | "date": "Mar 5", 260 | "fact": " cats have over 100 vocal chords" 261 | }, 262 | { 263 | "date": "Mar 6", 264 | "fact": " camel's milk doesn't curdle" 265 | }, 266 | { 267 | "date": "Mar 7", 268 | "fact": " elephants sleep between 4 - 5 hours in 24 period" 269 | }, 270 | { 271 | "date": "Mar 8", 272 | "fact": " it's possible to lead a cow up stairs but not down" 273 | }, 274 | { 275 | "date": "Mar 9", 276 | "fact": " frogs can't swallow with their eyes open" 277 | }, 278 | { 279 | "date": "Mar 10", 280 | "fact": " elephants are the only mammal that can't jump" 281 | }, 282 | { 283 | "date": "Mar 11", 284 | "fact": " a 1/4 of your bones are in your feet" 285 | }, 286 | { 287 | "date": "Mar 12", 288 | "fact": " your tongue is the fastest healing part of your body" 289 | }, 290 | { 291 | "date": "Mar 13", 292 | "fact": " on your birthday you share it with 9 million others" 293 | }, 294 | { 295 | "date": "Mar 14", 296 | "fact": " 1 googol is the number 1 followed by 100 zeros" 297 | }, 298 | { 299 | "date": "Mar 15", 300 | "fact": " a 1 minute kiss burns 26 calories" 301 | }, 302 | { 303 | "date": "Mar 16", 304 | "fact": " you burn more calories sleeping than watching TV" 305 | }, 306 | { 307 | "date": "Mar 17", 308 | "fact": " frogs don't usually swallow water (they absorb most of the moisture they need through their skin)" 309 | }, 310 | { 311 | "date": "Mar 18", 312 | "fact": " at birth dalmations are always white" 313 | }, 314 | { 315 | "date": "Mar 19", 316 | "fact": " hummingbirds are the only bird that can fly backwards" 317 | }, 318 | { 319 | "date": "Mar 20", 320 | "fact": " a duck can't walk without bobbing its head" 321 | }, 322 | { 323 | "date": "Mar 21", 324 | "fact": " a hummingbird's heart beats at over a 1,000 times a minute" 325 | }, 326 | { 327 | "date": "Mar 22", 328 | "fact": " dragonflies have 6 legs but can't walk" 329 | }, 330 | { 331 | "date": "Mar 23", 332 | "fact": " a crocodile can't move its tongue" 333 | }, 334 | { 335 | "date": "Mar 24", 336 | "fact": " that the first MTV video played was 'Video killed the radio star' by the Buggles" 337 | }, 338 | { 339 | "date": "Mar 25", 340 | "fact": " in 1878 the first telephone book made contained only 50 names" 341 | }, 342 | { 343 | "date": "Mar 26", 344 | "fact": " pop corn was invented by the Aztec Indians" 345 | }, 346 | { 347 | "date": "Mar 27", 348 | "fact": " an average person will spend 25 years asleep" 349 | }, 350 | { 351 | "date": "Mar 28", 352 | "fact": " hippopotamuses have killed more people in Africa than any other animal" 353 | }, 354 | { 355 | "date": "Mar 29", 356 | "fact": " an elephants ears are used to regulate body temperature" 357 | }, 358 | { 359 | "date": "Mar 30", 360 | "fact": " the Arctic Ocean is the smallest in the world" 361 | }, 362 | { 363 | "date": "Mar 31", 364 | "fact": " the most common mental illnesses are anxiety and depression" 365 | }, 366 | { 367 | "date": "Apr 1", 368 | "fact": " the word laser stands for 'Light Amplification by Stimulated Emission of Radiation'" 369 | }, 370 | { 371 | "date": "Apr 2", 372 | "fact": " crocodiles never outgrow their enclosure" 373 | }, 374 | { 375 | "date": "Apr 3", 376 | "fact": " reindeer hair is hollow inside like a tube" 377 | }, 378 | { 379 | "date": "Apr 4", 380 | "fact": " your skin is the largest organ making up the human body" 381 | }, 382 | { 383 | "date": "Apr 5", 384 | "fact": " cows don't have upper front teeth" 385 | }, 386 | { 387 | "date": "Apr 6", 388 | "fact": " everyday is a holiday somewhere in the world" 389 | }, 390 | { 391 | "date": "Apr 7", 392 | "fact": " the coins thrown into the Trevi fountain in Italy are collected for charity" 393 | }, 394 | { 395 | "date": "Apr 8", 396 | "fact": " french fries are originally from Belgium" 397 | }, 398 | { 399 | "date": "Apr 9", 400 | "fact": " there are 31,557,600 seconds in a year" 401 | }, 402 | { 403 | "date": "Apr 10", 404 | "fact": " there are 22 stars in the Paramount studios logo" 405 | }, 406 | { 407 | "date": "Apr 11", 408 | "fact": " in a deck of cards the king of hearts is the only king without a moustache" 409 | }, 410 | { 411 | "date": "Apr 12", 412 | "fact": " black on yellow are the 2 colors with the strongest impact" 413 | }, 414 | { 415 | "date": "Apr 13", 416 | "fact": " the safest car color is white" 417 | }, 418 | { 419 | "date": "Apr 14", 420 | "fact": " the most commonly forgotten item for travelers is their toothbrush" 421 | }, 422 | { 423 | "date": "Apr 15", 424 | "fact": " Coca Cola launched its 3rd product Sprite in 1961" 425 | }, 426 | { 427 | "date": "Apr 16", 428 | "fact": " apples are more effective at waking you up in the morning than coffee" 429 | }, 430 | { 431 | "date": "Apr 17", 432 | "fact": " room temperature is defined as between 20 to 25C (68 to 77F)" 433 | }, 434 | { 435 | "date": "Apr 18", 436 | "fact": " an octopus pupil is rectangular" 437 | }, 438 | { 439 | "date": "Apr 19", 440 | "fact": " the hyoid bone in your throat is the only bone in your body not attached to any other" 441 | }, 442 | { 443 | "date": "Apr 20", 444 | "fact": " the Australian aircraft carrier QANTAS stands for Queensland And Northern Territories Aerial Service" 445 | }, 446 | { 447 | "date": "Apr 21", 448 | "fact": " the movie Pulp Fiction cost $8 million to make with $5 million going towards actor's salaries" 449 | }, 450 | { 451 | "date": "Apr 22", 452 | "fact": " there are only 4 words in the English language which end in 'dous' (they are: hazardous, horrendous, stupendous and tremendous)" 453 | }, 454 | { 455 | "date": "Apr 23", 456 | "fact": " the oldest word in the English language is 'town'" 457 | }, 458 | { 459 | "date": "Apr 24", 460 | "fact": " cats can't move their jaw sideways" 461 | }, 462 | { 463 | "date": "Apr 25", 464 | "fact": " grapes explode when you put them in the microwave" 465 | }, 466 | { 467 | "date": "Apr 26", 468 | "fact": " its physically impossible for pigs to look up at the sky" 469 | }, 470 | { 471 | "date": "Apr 27", 472 | "fact": " your most sensitive finger is your index finger (closest to your thumb)" 473 | }, 474 | { 475 | "date": "Apr 28", 476 | "fact": " 'Bookkeeper' and 'bookkeeping' are the only 2 words in the English language with three consecutive double letters" 477 | }, 478 | { 479 | "date": "Apr 29", 480 | "fact": " Venetian blinds were invented in Japan" 481 | }, 482 | { 483 | "date": "Apr 30", 484 | "fact": " the average golf ball has 336 dimples" 485 | }, 486 | { 487 | "date": "May 1", 488 | "fact": " the word 'Strengths' is the longest word in the English language with just one vowel" 489 | }, 490 | { 491 | "date": "May 2", 492 | "fact": " the movie 'Wayne's World' was filmed in two weeks" 493 | }, 494 | { 495 | "date": "May 3", 496 | "fact": " the Amazon rainforest produces half the world's oxygen supply" 497 | }, 498 | { 499 | "date": "May 4", 500 | "fact": " a group of frogs is called an army" 501 | }, 502 | { 503 | "date": "May 5", 504 | "fact": " a group of rhinos is called a crash" 505 | }, 506 | { 507 | "date": "May 6", 508 | "fact": " a group of kangaroos is called a mob" 509 | }, 510 | { 511 | "date": "May 7", 512 | "fact": " a group of whales is called a pod" 513 | }, 514 | { 515 | "date": "May 8", 516 | "fact": " a group of geese is called a gaggle" 517 | }, 518 | { 519 | "date": "May 9", 520 | "fact": " a group of owls is called a parliament" 521 | }, 522 | { 523 | "date": "May 10", 524 | "fact": " the first sailing boats were built in Egypt" 525 | }, 526 | { 527 | "date": "May 11", 528 | "fact": " Brazil is named after a tree" 529 | }, 530 | { 531 | "date": "May 12", 532 | "fact": " Brazil covers 50% of the South American continent" 533 | }, 534 | { 535 | "date": "May 13", 536 | "fact": " Brazil borders every country in South America except Chile and Ecuador" 537 | }, 538 | { 539 | "date": "May 14", 540 | "fact": " Hilton was the first international hotel chain" 541 | }, 542 | { 543 | "date": "May 15", 544 | "fact": " the brand Nokia is named after a place in Southern Finland" 545 | }, 546 | { 547 | "date": "May 16", 548 | "fact": " Monopoly is the most played board game in the world" 549 | }, 550 | { 551 | "date": "May 17", 552 | "fact": " 96% of candles sold are purchased by women" 553 | }, 554 | { 555 | "date": "May 18", 556 | "fact": " 42% of men and women 25% don�t wash their hands after using a public toilet" 557 | }, 558 | { 559 | "date": "May 19", 560 | "fact": " if you filled a matchbox with gold it could be flattened into a sheet the size of a tennis court" 561 | }, 562 | { 563 | "date": "May 20", 564 | "fact": " Jamaica has 120 rivers" 565 | }, 566 | { 567 | "date": "May 21", 568 | "fact": " a cats urine glows under a blacklight" 569 | }, 570 | { 571 | "date": "May 22", 572 | "fact": " white cats with blue eyes are usually deaf" 573 | }, 574 | { 575 | "date": "May 23", 576 | "fact": " cats have a peripheral vision of 285 degrees" 577 | }, 578 | { 579 | "date": "May 24", 580 | "fact": " small dogs usually live longer than larger breeds" 581 | }, 582 | { 583 | "date": "May 25", 584 | "fact": " domestic cats dislike citrus scents" 585 | }, 586 | { 587 | "date": "May 26", 588 | "fact": " cats can jump up to 7 times their tail length" 589 | }, 590 | { 591 | "date": "May 27", 592 | "fact": " China manufacturers 70% of the worlds toys" 593 | }, 594 | { 595 | "date": "May 28", 596 | "fact": " The Great Wall of China is approximately 6,430 Km long (3,995 miles)" 597 | }, 598 | { 599 | "date": "May 29", 600 | "fact": " paper originated from China" 601 | }, 602 | { 603 | "date": "May 30", 604 | "fact": " the wheelbarrow is invented in China" 605 | }, 606 | { 607 | "date": "May 31", 608 | "fact": " tree hugging is forbidden in china" 609 | }, 610 | { 611 | "date": "Jun 1", 612 | "fact": " the film 'Mary Poppins' was filmed entirely indoors" 613 | }, 614 | { 615 | "date": "Jun 2", 616 | "fact": " all of the clocks in the movie 'Pulp Fiction' are fixed to 4:20" 617 | }, 618 | { 619 | "date": "Jun 3", 620 | "fact": " instant coffee was invented in 1901" 621 | }, 622 | { 623 | "date": "Jun 4", 624 | "fact": " the human body of a 70 kg person contains 0.2mg of gold" 625 | }, 626 | { 627 | "date": "Jun 5", 628 | "fact": " rice is the staple food for 50% of the worlds population" 629 | }, 630 | { 631 | "date": "Jun 6", 632 | "fact": " Pearls melt in vinegar" 633 | }, 634 | { 635 | "date": "Jun 7", 636 | "fact": " a hard boiled eggs spin (uncooked or soft boiled don�t)" 637 | }, 638 | { 639 | "date": "Jun 8", 640 | "fact": " there is no butter in buttermilk" 641 | }, 642 | { 643 | "date": "Jun 9", 644 | "fact": " giraffes and rats can last longer without water than camels" 645 | }, 646 | { 647 | "date": "Jun 10", 648 | "fact": " the dot on top of the letter 'i' is called a tittle" 649 | }, 650 | { 651 | "date": "Jun 11", 652 | "fact": " the electric chair was invented by a dentist" 653 | }, 654 | { 655 | "date": "Jun 12", 656 | "fact": " you're more likely to be killed by a champagne cork than by a poisonous spider" 657 | }, 658 | { 659 | "date": "Jun 13", 660 | "fact": " a crocodile can't stick out its tongue" 661 | }, 662 | { 663 | "date": "Jun 14", 664 | "fact": " rubber bands last longer when kept refrigerated" 665 | }, 666 | { 667 | "date": "Jun 15", 668 | "fact": " women blink twice as much as men" 669 | }, 670 | { 671 | "date": "Jun 16", 672 | "fact": " ostriches don't bury their heads in sand" 673 | }, 674 | { 675 | "date": "Jun 17", 676 | "fact": " only female mosquitoes bite" 677 | }, 678 | { 679 | "date": "Jun 18", 680 | "fact": " Scotland has the most redheads" 681 | }, 682 | { 683 | "date": "Jun 19", 684 | "fact": " household dust is made of dead skin cells" 685 | }, 686 | { 687 | "date": "Jun 20", 688 | "fact": " the past tense for the English word 'dare' is 'durst'" 689 | }, 690 | { 691 | "date": "Jun 21", 692 | "fact": " hummingbirds can't walk" 693 | }, 694 | { 695 | "date": "Jun 22", 696 | "fact": " wind doesn�t make a sound until it blows against an object" 697 | }, 698 | { 699 | "date": "Jun 23", 700 | "fact": " the naming of tropical storms and hurricanes officially began in 1953" 701 | }, 702 | { 703 | "date": "Jun 24", 704 | "fact": " India has the most post offices than any other country (over 100,000)" 705 | }, 706 | { 707 | "date": "Jun 25", 708 | "fact": " India is home to over 200 million cows" 709 | }, 710 | { 711 | "date": "Jun 26", 712 | "fact": " the Taj Mahal in India is made entirely out of marble" 713 | }, 714 | { 715 | "date": "Jun 27", 716 | "fact": " Bali has the worlds largest variety of flora" 717 | }, 718 | { 719 | "date": "Jun 28", 720 | "fact": " Bill Gates began programming computers at the of age 13" 721 | }, 722 | { 723 | "date": "Jun 29", 724 | "fact": " every single possible 3 character .com domain has been registered" 725 | }, 726 | { 727 | "date": "Jun 30", 728 | "fact": " the word 'uncopyrightable' is the is the only 15 letter word that can be spelled without repeating any letter" 729 | }, 730 | { 731 | "date": "Jul 1", 732 | "fact": " the word 'testify' derived from a time when men were required to swear on their testicles" 733 | }, 734 | { 735 | "date": "Jul 2", 736 | "fact": " the word typewriter is the longest word that can be typed using only the top row of a keyboard" 737 | }, 738 | { 739 | "date": "Jul 3", 740 | "fact": " that you can spell the word 'level' the same backwards" 741 | }, 742 | { 743 | "date": "Jul 4", 744 | "fact": " Madonna and Michael Jackson were both born in 1958" 745 | }, 746 | { 747 | "date": "Jul 5", 748 | "fact": " almonds are members of the peach family" 749 | }, 750 | { 751 | "date": "Jul 6", 752 | "fact": " an egg contains every vitamin except vitamin C" 753 | }, 754 | { 755 | "date": "Jul 7", 756 | "fact": " owls can't move their eyes from side to side" 757 | }, 758 | { 759 | "date": "Jul 8", 760 | "fact": " you take over 23,000 breaths everyday" 761 | }, 762 | { 763 | "date": "Jul 9", 764 | "fact": " gold never erodes" 765 | }, 766 | { 767 | "date": "Jul 10", 768 | "fact": " scorpions glow under ultra violet light" 769 | }, 770 | { 771 | "date": "Jul 11", 772 | "fact": " when water freezes it expans by 9%" 773 | }, 774 | { 775 | "date": "Jul 12", 776 | "fact": " ants stretch when they wake up in the morning" 777 | }, 778 | { 779 | "date": "Jul 13", 780 | "fact": " your foot and your forearm are the same length" 781 | }, 782 | { 783 | "date": "Jul 14", 784 | "fact": " diamonds are the hardest natural substance" 785 | }, 786 | { 787 | "date": "Jul 15", 788 | "fact": " 111,111,111 x 111,111,111 = 12,345,678,987,654,321" 789 | }, 790 | { 791 | "date": "Jul 16", 792 | "fact": " the longest possible eclipse of the sun is 7.31 minutes" 793 | }, 794 | { 795 | "date": "Jul 17", 796 | "fact": " Halley's comet passes the Earth every 76 years (the next time it will return will be 2062)" 797 | }, 798 | { 799 | "date": "Jul 18", 800 | "fact": " there is no sound in space" 801 | }, 802 | { 803 | "date": "Jul 19", 804 | "fact": " tennis was originally played with bare hands" 805 | }, 806 | { 807 | "date": "Jul 20", 808 | "fact": " the Olympic flag was designed in 1913" 809 | }, 810 | { 811 | "date": "Jul 21", 812 | "fact": " a bowling pin will fall at a tilt of 7.5 degrees" 813 | }, 814 | { 815 | "date": "Jul 22", 816 | "fact": " there are 31,536,000 seconds in a year" 817 | }, 818 | { 819 | "date": "Jul 23", 820 | "fact": " a piece of paper cannot be folded more than 7 times" 821 | }, 822 | { 823 | "date": "Jul 24", 824 | "fact": " the opposite sides of a die always adds up to 7" 825 | }, 826 | { 827 | "date": "Jul 25", 828 | "fact": " VHS stands for Video Home System" 829 | }, 830 | { 831 | "date": "Jul 26", 832 | "fact": " the WD in WD-40 stands for Water Displacer" 833 | }, 834 | { 835 | "date": "Jul 27", 836 | "fact": " the electric toothbrush was invented in 1939" 837 | }, 838 | { 839 | "date": "Jul 28", 840 | "fact": " Porsche also builds tractors" 841 | }, 842 | { 843 | "date": "Jul 29", 844 | "fact": " the Eiffel Tower has 1,792 steps" 845 | }, 846 | { 847 | "date": "Jul 30", 848 | "fact": " Isaac Newton invented the cat door" 849 | }, 850 | { 851 | "date": "Jul 31", 852 | "fact": " the Titanic was built in Belfast" 853 | }, 854 | { 855 | "date": "Aug 1", 856 | "fact": " Buckingham Palace has over 600 rooms" 857 | }, 858 | { 859 | "date": "Aug 2", 860 | "fact": " Hawaii was originally called the Sandwich Islands" 861 | }, 862 | { 863 | "date": "Aug 3", 864 | "fact": " Americans eat 35,000 tons of pasta a year" 865 | }, 866 | { 867 | "date": "Aug 4", 868 | "fact": " Hawaii is the only US state that grows coffee" 869 | }, 870 | { 871 | "date": "Aug 5", 872 | "fact": " Americans throw away 44 million newspapers a day" 873 | }, 874 | { 875 | "date": "Aug 6", 876 | "fact": " Einstein slept 10 hours a night" 877 | }, 878 | { 879 | "date": "Aug 7", 880 | "fact": " Germany borders 9 other countries" 881 | }, 882 | { 883 | "date": "Aug 8", 884 | "fact": " Peru has more pyramids than Egypt" 885 | }, 886 | { 887 | "date": "Aug 9", 888 | "fact": " Christmas trees originated from Germany" 889 | }, 890 | { 891 | "date": "Aug 10", 892 | "fact": " more people die from falling coconuts then from shark attacks" 893 | }, 894 | { 895 | "date": "Aug 11", 896 | "fact": " the original design of Monopoly was circular" 897 | }, 898 | { 899 | "date": "Aug 12", 900 | "fact": " the Earth is struck by lightning over 100 times every second" 901 | }, 902 | { 903 | "date": "Aug 13", 904 | "fact": " over 2,500 left handed people are killed a year from using right handed products" 905 | }, 906 | { 907 | "date": "Aug 14", 908 | "fact": " gorillas sleep 14 hours a day" 909 | }, 910 | { 911 | "date": "Aug 15", 912 | "fact": " the lifespan of a squirrel is 9 years" 913 | }, 914 | { 915 | "date": "Aug 16", 916 | "fact": " the stomach acids found in a snakes stomach can digest bones and teeth but not fur or hair" 917 | }, 918 | { 919 | "date": "Aug 17", 920 | "fact": " the word racecar can be spelled the same way backwards" 921 | }, 922 | { 923 | "date": "Aug 18", 924 | "fact": " a giraffe can go longer without water than a camel" 925 | }, 926 | { 927 | "date": "Aug 19", 928 | "fact": " you burn more calories sleeping than watching television" 929 | }, 930 | { 931 | "date": "Aug 20", 932 | "fact": " the word 'underground is the only word that begins and ends with the letters 'und'" 933 | }, 934 | { 935 | "date": "Aug 21", 936 | "fact": " 56% of typing is completed by your left hand" 937 | }, 938 | { 939 | "date": "Aug 22", 940 | "fact": " there are more chickens than people" 941 | }, 942 | { 943 | "date": "Aug 23", 944 | "fact": " for every human there are 200 million insects" 945 | }, 946 | { 947 | "date": "Aug 24", 948 | "fact": " the average bed contains over 6 billion dust mites" 949 | }, 950 | { 951 | "date": "Aug 25", 952 | "fact": " an iguana can stay under water for 28 minutes" 953 | }, 954 | { 955 | "date": "Aug 26", 956 | "fact": " emus can't walk backwards" 957 | }, 958 | { 959 | "date": "Aug 27", 960 | "fact": " the Eifel Tower has 2,500,000 rivets" 961 | }, 962 | { 963 | "date": "Aug 28", 964 | "fact": " Americas top selling ice cream flavour is vanilla" 965 | }, 966 | { 967 | "date": "Aug 29", 968 | "fact": " the doorbell was invented in 1831" 969 | }, 970 | { 971 | "date": "Aug 30", 972 | "fact": " there are 7 points on the Statue of Liberty's crown" 973 | }, 974 | { 975 | "date": "Aug 31", 976 | "fact": " the oldest known vegetable is the pea" 977 | }, 978 | { 979 | "date": "Sep 1", 980 | "fact": " the most fatal car accidents occur on Saturdays" 981 | }, 982 | { 983 | "date": "Sep 2", 984 | "fact": " the average hen lays 228 eggs a year" 985 | }, 986 | { 987 | "date": "Sep 3", 988 | "fact": " the Eiffel Tower has 1,792 steps" 989 | }, 990 | { 991 | "date": "Sep 4", 992 | "fact": " Iceland consumes more Coca Cola than any other country" 993 | }, 994 | { 995 | "date": "Sep 5", 996 | "fact": " Oak trees don't produce acorns until they are 50 years old" 997 | }, 998 | { 999 | "date": "Sep 6", 1000 | "fact": " the word 'almost' is the longest word spelt alphabetically" 1001 | }, 1002 | { 1003 | "date": "Sep 7", 1004 | "fact": " human thigh bones are stronger than concrete" 1005 | }, 1006 | { 1007 | "date": "Sep 8", 1008 | "fact": " Earth is the only planet not named after a god" 1009 | }, 1010 | { 1011 | "date": "Sep 9", 1012 | "fact": " months that start on a Sunday will always have a Friday the 13th" 1013 | }, 1014 | { 1015 | "date": "Sep 10", 1016 | "fact": " more people are allergic to cows milk than any other food" 1017 | }, 1018 | { 1019 | "date": "Sep 11", 1020 | "fact": " more people are killed from bees than snakes" 1021 | }, 1022 | { 1023 | "date": "Sep 12", 1024 | "fact": " the average person laughs 10 times a day" 1025 | }, 1026 | { 1027 | "date": "Sep 13", 1028 | "fact": " the Atlantic Ocean is saltier than the Pacific" 1029 | }, 1030 | { 1031 | "date": "Sep 14", 1032 | "fact": " your mouth produces 1 litre of saliva a day" 1033 | }, 1034 | { 1035 | "date": "Sep 15", 1036 | "fact": " your head contains 22 bones" 1037 | }, 1038 | { 1039 | "date": "Sep 16", 1040 | "fact": " the coloured part of your eye is called the iris" 1041 | }, 1042 | { 1043 | "date": "Sep 17", 1044 | "fact": " if your DNA was stretched out it would reach to the moon 6,000 times" 1045 | }, 1046 | { 1047 | "date": "Sep 18", 1048 | "fact": " everyone has a unique tongue print" 1049 | }, 1050 | { 1051 | "date": "Sep 19", 1052 | "fact": " you begin to feel thirsty when your body losses 1% of water" 1053 | }, 1054 | { 1055 | "date": "Sep 20", 1056 | "fact": " hiccups usually lasts for 5 minutes" 1057 | }, 1058 | { 1059 | "date": "Sep 21", 1060 | "fact": " not all your taste buds are on our tongue (10% are on the insides of you cheeks)" 1061 | }, 1062 | { 1063 | "date": "Sep 22", 1064 | "fact": " the life span of a house fly is between 10 to 25 days" 1065 | }, 1066 | { 1067 | "date": "Sep 23", 1068 | "fact": " a dolphins top speed is 60kmh (37mph)" 1069 | }, 1070 | { 1071 | "date": "Sep 24", 1072 | "fact": " the smallest dog is the Chihuahua" 1073 | }, 1074 | { 1075 | "date": "Sep 25", 1076 | "fact": " a sharks top speed is 70kmh (44mph)" 1077 | }, 1078 | { 1079 | "date": "Sep 26", 1080 | "fact": " there are 70 million sheep in New Zealand (with 4 million people)" 1081 | }, 1082 | { 1083 | "date": "Sep 27", 1084 | "fact": " the worlds smallest bird is the 'bee hummingbird' found in Cuba" 1085 | }, 1086 | { 1087 | "date": "Sep 28", 1088 | "fact": " African elephants only have 4 teeth" 1089 | }, 1090 | { 1091 | "date": "Sep 29", 1092 | "fact": " The first English dictionary was written in 1755" 1093 | }, 1094 | { 1095 | "date": "Sep 30", 1096 | "fact": " the rarest type of diamond is green" 1097 | }, 1098 | { 1099 | "date": "Oct 1", 1100 | "fact": " MasterCard was originally called MasterCharge" 1101 | }, 1102 | { 1103 | "date": "Oct 2", 1104 | "fact": " the US flag has 13 stripes (representing the original 13 states)" 1105 | }, 1106 | { 1107 | "date": "Oct 3", 1108 | "fact": " men are stuck by lightning 7 times more than women" 1109 | }, 1110 | { 1111 | "date": "Oct 4", 1112 | "fact": " Tokyo was once known as Edo" 1113 | }, 1114 | { 1115 | "date": "Oct 5", 1116 | "fact": " women make up 49% of the worlds population" 1117 | }, 1118 | { 1119 | "date": "Oct 6", 1120 | "fact": " wine is sold in tinted bottles because it spoils when exposed to light" 1121 | }, 1122 | { 1123 | "date": "Oct 7", 1124 | "fact": " the tea bag was invented in 1908" 1125 | }, 1126 | { 1127 | "date": "Oct 8", 1128 | "fact": " carrots contain 0% fat" 1129 | }, 1130 | { 1131 | "date": "Oct 9", 1132 | "fact": " 1 billion snails are served in restaurants each year" 1133 | }, 1134 | { 1135 | "date": "Oct 10", 1136 | "fact": " plastic bottles were first used for soft drinks in 1970" 1137 | }, 1138 | { 1139 | "date": "Oct 11", 1140 | "fact": " the $ sign was introduced in 1788" 1141 | }, 1142 | { 1143 | "date": "Oct 12", 1144 | "fact": " the meaning of 'Blue Chip' comes from blue casino chips which have a high value" 1145 | }, 1146 | { 1147 | "date": "Oct 13", 1148 | "fact": " DVDs are physically the same size as a CDs but can store 13 times more data" 1149 | }, 1150 | { 1151 | "date": "Oct 14", 1152 | "fact": " the term 'disc jockey' was first used in 1937" 1153 | }, 1154 | { 1155 | "date": "Oct 15", 1156 | "fact": " sound travels 4.3 times faster through water than in air" 1157 | }, 1158 | { 1159 | "date": "Oct 16", 1160 | "fact": " the average soccer ball is made up of 32 leather panels and held together by 642 stitches" 1161 | }, 1162 | { 1163 | "date": "Oct 17", 1164 | "fact": " soccer is the most followed sport" 1165 | }, 1166 | { 1167 | "date": "Oct 18", 1168 | "fact": " volleyball was invented in 1895" 1169 | }, 1170 | { 1171 | "date": "Oct 19", 1172 | "fact": " that in developed countries 27% of food is thrown away" 1173 | }, 1174 | { 1175 | "date": "Oct 20", 1176 | "fact": " the odds of being struck by lightning are 600,000 to 1" 1177 | }, 1178 | { 1179 | "date": "Oct 21", 1180 | "fact": " the first train reached a top speed of only 8 kmh (5 mph)" 1181 | }, 1182 | { 1183 | "date": "Oct 22", 1184 | "fact": " Niagara Falls could fill 4,000 bathtubs every second" 1185 | }, 1186 | { 1187 | "date": "Oct 23", 1188 | "fact": " it takes 1 alligator to make a pair of shoes and 3 for a pair of boots" 1189 | }, 1190 | { 1191 | "date": "Oct 24", 1192 | "fact": " your most active muscles are in your eye" 1193 | }, 1194 | { 1195 | "date": "Oct 25", 1196 | "fact": " a banana contains 75% water" 1197 | }, 1198 | { 1199 | "date": "Oct 26", 1200 | "fact": " 13 people die every year from vending machines" 1201 | }, 1202 | { 1203 | "date": "Oct 27", 1204 | "fact": " rain contains vitamin B12" 1205 | }, 1206 | { 1207 | "date": "Oct 28", 1208 | "fact": " your liver has over 500 functions" 1209 | }, 1210 | { 1211 | "date": "Oct 29", 1212 | "fact": " your brain uses 25% of all the oxygen your breathe" 1213 | }, 1214 | { 1215 | "date": "Oct 30", 1216 | "fact": " after Hawaii, New York is the state surrounded by the most water" 1217 | }, 1218 | { 1219 | "date": "Oct 31", 1220 | "fact": " ice skating rinks always go counter clock wise (for the majority of people that are right handed needing to hang onto the rail)" 1221 | }, 1222 | { 1223 | "date": "Nov 1", 1224 | "fact": " a flea can jump 350 times its body length" 1225 | }, 1226 | { 1227 | "date": "Nov 2", 1228 | "fact": " cucumbers are 96% water." 1229 | }, 1230 | { 1231 | "date": "Nov 3", 1232 | "fact": " a full moon is 9 times brighter than a half moon" 1233 | }, 1234 | { 1235 | "date": "Nov 4", 1236 | "fact": " a honeybee's top speed is 24kph (15mph)" 1237 | }, 1238 | { 1239 | "date": "Nov 5", 1240 | "fact": " a humming bird flaps its wings up to 90 times a second (5,400 times a minute)" 1241 | }, 1242 | { 1243 | "date": "Nov 6", 1244 | "fact": " flys always launch backwards for a quick getaway" 1245 | }, 1246 | { 1247 | "date": "Nov 7", 1248 | "fact": " horses have 18 more bones than humans" 1249 | }, 1250 | { 1251 | "date": "Nov 8", 1252 | "fact": " a cheetahs top speed is 114kph (70mph)" 1253 | }, 1254 | { 1255 | "date": "Nov 9", 1256 | "fact": " horses sleep standing up" 1257 | }, 1258 | { 1259 | "date": "Nov 10", 1260 | "fact": " a jellyfish is 95% water" 1261 | }, 1262 | { 1263 | "date": "Nov 11", 1264 | "fact": " bats are the only mammals that fly" 1265 | }, 1266 | { 1267 | "date": "Nov 12", 1268 | "fact": " a cat uses its whiskers to determine if a space is too small to squeeze through" 1269 | }, 1270 | { 1271 | "date": "Nov 13", 1272 | "fact": " every day 7% of the US eats at McDonalds" 1273 | }, 1274 | { 1275 | "date": "Nov 14", 1276 | "fact": " a snail can sleep for 3 years" 1277 | }, 1278 | { 1279 | "date": "Nov 15", 1280 | "fact": " tigers have striped skin as well as fur" 1281 | }, 1282 | { 1283 | "date": "Nov 16", 1284 | "fact": " crocodiles are colour blind" 1285 | }, 1286 | { 1287 | "date": "Nov 17", 1288 | "fact": " a chameleons tongue is twice the length of its body" 1289 | }, 1290 | { 1291 | "date": "Nov 18", 1292 | "fact": " dogs sweat through the pads on their feet" 1293 | }, 1294 | { 1295 | "date": "Nov 19", 1296 | "fact": " hippopotamuses are born under water" 1297 | }, 1298 | { 1299 | "date": "Nov 20", 1300 | "fact": " bananas grow pointing upwards." 1301 | }, 1302 | { 1303 | "date": "Nov 21", 1304 | "fact": " whales can't swim backwards" 1305 | }, 1306 | { 1307 | "date": "Nov 22", 1308 | "fact": " camels are born without humps" 1309 | }, 1310 | { 1311 | "date": "Nov 23", 1312 | "fact": " only female mosquitoes bite" 1313 | }, 1314 | { 1315 | "date": "Nov 24", 1316 | "fact": " the average porcupine has 30,000 spikes" 1317 | }, 1318 | { 1319 | "date": "Nov 25", 1320 | "fact": " tarantula spiders can survive 2 and a half years without food" 1321 | }, 1322 | { 1323 | "date": "Nov 26", 1324 | "fact": " crocodiles are responsible for over a 1,000 deaths each year by the Banks of the Nile river" 1325 | }, 1326 | { 1327 | "date": "Nov 27", 1328 | "fact": " there are more insects in the world than all other animals combined" 1329 | }, 1330 | { 1331 | "date": "Nov 28", 1332 | "fact": " giraffes can't swim" 1333 | }, 1334 | { 1335 | "date": "Nov 29", 1336 | "fact": " crocodiles swallow rocks to help them dive deeper" 1337 | }, 1338 | { 1339 | "date": "Nov 30", 1340 | "fact": " an elephant's trunk can hold over 5 litres of water" 1341 | }, 1342 | { 1343 | "date": "Dec 1", 1344 | "fact": " bull's can run faster uphill than down" 1345 | }, 1346 | { 1347 | "date": "Dec 2", 1348 | "fact": " a shark's teeth are literally as hard as steel" 1349 | }, 1350 | { 1351 | "date": "Dec 3", 1352 | "fact": " a moth has no stomach" 1353 | }, 1354 | { 1355 | "date": "Dec 4", 1356 | "fact": " grasshoppers have white blood" 1357 | }, 1358 | { 1359 | "date": "Dec 5", 1360 | "fact": " it takes 50 minutes to soft boil and two hours to hard boil an ostrich egg" 1361 | }, 1362 | { 1363 | "date": "Dec 6", 1364 | "fact": " New York was once called New Amsterdam" 1365 | }, 1366 | { 1367 | "date": "Dec 7", 1368 | "fact": " there is 200 times more gold in the world's oceans than has been mined" 1369 | }, 1370 | { 1371 | "date": "Dec 8", 1372 | "fact": " Brazil got its name from the Brazilian nut (not the other way around)" 1373 | }, 1374 | { 1375 | "date": "Dec 9", 1376 | "fact": " the moon orbits the Earth every 27.32 days" 1377 | }, 1378 | { 1379 | "date": "Dec 10", 1380 | "fact": " more than 75% of all countries are north of the equator" 1381 | }, 1382 | { 1383 | "date": "Dec 11", 1384 | "fact": " 2 million hydrogen atoms would be required to cover a full stop (.)" 1385 | }, 1386 | { 1387 | "date": "Dec 12", 1388 | "fact": " Hawaii officially became apart of the US in 1900" 1389 | }, 1390 | { 1391 | "date": "Dec 13", 1392 | "fact": " the D.C. in Washington D.C. stands for District of Columbia" 1393 | }, 1394 | { 1395 | "date": "Dec 14", 1396 | "fact": " New York contains 920km (571miles) of shoreline" 1397 | }, 1398 | { 1399 | "date": "Dec 15", 1400 | "fact": " The Dead Sea is actually an inland lake" 1401 | }, 1402 | { 1403 | "date": "Dec 16", 1404 | "fact": " there are no rivers in Saudi Arabia" 1405 | }, 1406 | { 1407 | "date": "Dec 17", 1408 | "fact": " the largest exporter of sugar is Cuba" 1409 | }, 1410 | { 1411 | "date": "Dec 18", 1412 | "fact": " dirty snow melts quicker than clean snow" 1413 | }, 1414 | { 1415 | "date": "Dec 19", 1416 | "fact": " Icelandic phone books are listed by first names (not surnames)" 1417 | }, 1418 | { 1419 | "date": "Dec 20", 1420 | "fact": " 1 gigayear = 1,000,000,000,000 years" 1421 | }, 1422 | { 1423 | "date": "Dec 21", 1424 | "fact": " the water in the Dead Sea is so salty that its easier to float than sink" 1425 | }, 1426 | { 1427 | "date": "Dec 22", 1428 | "fact": " Rio de Janeiro translates to river of January" 1429 | }, 1430 | { 1431 | "date": "Dec 23", 1432 | "fact": " the Moons diameter is 3,476km" 1433 | }, 1434 | { 1435 | "date": "Dec 24", 1436 | "fact": " New York's Central Park was opened in 1876" 1437 | }, 1438 | { 1439 | "date": "Dec 25", 1440 | "fact": " the subject of the first printed book in England was about chess" 1441 | }, 1442 | { 1443 | "date": "Dec 26", 1444 | "fact": " the word old English word 'juke' meaning dancing lends its name to the juke box" 1445 | }, 1446 | { 1447 | "date": "Dec 27", 1448 | "fact": " EMI awards stands for 'Electrical and Musical Instruments'" 1449 | }, 1450 | { 1451 | "date": "Dec 28", 1452 | "fact": " the most sung song is happy birthday" 1453 | }, 1454 | { 1455 | "date": "Dec 29", 1456 | "fact": " the first rugby club was formed in 1843" 1457 | }, 1458 | { 1459 | "date": "Dec 30", 1460 | "fact": " the most common injury in ten pin bowling is a sore thumb" 1461 | }, 1462 | { 1463 | "date": "Dec 31", 1464 | "fact": " the yo-yo was originally used as a weapon for hunting the in the Philippines" 1465 | } 1466 | ] 1467 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/HomeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HomeViewController.swift 3 | // SharedCoreData 4 | // 5 | // Created by iLeaf Solutions on 18/12/17. 6 | // Copyright © 2017 iLeaf. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class HomeViewController: UIViewController,JBDatePickerViewDelegate{ 12 | 13 | ///Input is month name 14 | @IBOutlet weak var lblCurrentMnth: UILabel! 15 | /// calender view 16 | @IBOutlet weak var datePickerView: JBDatePickerView! 17 | /// Input is todays did you know fact 18 | @IBOutlet weak var lblFactsDescription: UILabel! 19 | /// Contain all facts 20 | var arrayFacts = [SCDFactModel]() 21 | /// Know facts model 22 | var factsModel = SCDFactModel() 23 | /// Date formatter 24 | lazy var dateFormatter: DateFormatter = { 25 | 26 | var formatter = DateFormatter() 27 | formatter.dateFormat = "MMM d" 28 | return formatter 29 | }() 30 | 31 | // MARK: View life cycle 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | // Do any additional setup after loading the view, typically from a nib. 35 | datePickerView.delegate = self 36 | if !isAppAlreadyLaunchedOnce(){ 37 | 38 | //Read json and save it to coredata 39 | readJson() 40 | } 41 | else 42 | { //Fetch todays fact 43 | fetchTodaysFact() 44 | } 45 | 46 | 47 | //let arry = SCDCoreDataWrapper.sharedInstance.getUser(entity: "User") 48 | 49 | 50 | } 51 | override func didReceiveMemoryWarning() { 52 | super.didReceiveMemoryWarning() 53 | // Dispose of any resources that can be recreated. 54 | } 55 | // MARK: Helper functions 56 | func getMonth(month:Int) -> String { 57 | switch month { 58 | case 1: 59 | return "Jan" 60 | case 2: 61 | return "Feb" 62 | case 3: 63 | return "Mar" 64 | case 4: 65 | return "Apr" 66 | case 5: 67 | return "May" 68 | case 6: 69 | return "Jun" 70 | case 7: 71 | return "Jul" 72 | case 8: 73 | return "Aug" 74 | case 9: 75 | return "Sep" 76 | case 10: 77 | return "Oct" 78 | case 11: 79 | return "Nov" 80 | default: 81 | return "Dec" 82 | } 83 | } 84 | func fetchTodaysFact() 85 | { 86 | let date = Date() 87 | let calendar = Calendar.current 88 | let components = calendar.dateComponents([.year, .month, .day], from:date) 89 | let month = components.month 90 | 91 | let day:Int = components.day! 92 | let todaysDate = getMonth(month: month!)+" "+String(day) 93 | let data = SCDCoreDataWrapper.sharedInstance.fetchTodaysFact(filter: todaysDate) 94 | let replaced = data.fact.trimmingCharacters(in: NSCharacterSet.whitespaces) 95 | lblFactsDescription.text = replaced.capitalizingFirstLetter() 96 | } 97 | 98 | // MARK: - JBDatePickerViewDelegate implementation 99 | 100 | func didSelectDay(_ dayView: JBDatePickerDayView) { 101 | //Fetching todays fact from coredata 102 | let data = SCDCoreDataWrapper.sharedInstance.fetchTodaysFact(filter: dateFormatter.string(from: datePickerView.selectedDateView.date!)) 103 | let replaced = data.fact.trimmingCharacters(in: NSCharacterSet.whitespaces) 104 | 105 | lblFactsDescription.text = replaced.capitalizingFirstLetter() 106 | 107 | } 108 | 109 | func didPresentOtherMonth(_ monthView: JBDatePickerMonthView) { 110 | self.lblCurrentMnth.text = datePickerView.presentedMonthView.monthDescription 111 | 112 | } 113 | // MARK: - JBDatePickerViewDelegate custom colors 114 | var colorForWeekDaysViewBackground: UIColor { 115 | return UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0) 116 | } 117 | 118 | var colorForSelectionCircleForOtherDate: UIColor { 119 | return UIColor(red: 81.0/255.0, green: 92.0/255.0, blue: 229.0/255.0, alpha: 1.0) 120 | } 121 | var colorForSelectionCircleForToday: UIColor 122 | { 123 | return UIColor(red: 81.0/255.0, green: 92.0/255.0, blue: 229.0/255.0, alpha: 1.0) 124 | } 125 | var colorForWeekDaysViewText : UIColor 126 | { 127 | return UIColor(red: 81.0/255.0, green: 92.0/255.0, blue: 229.0/255.0, alpha: 1.0) 128 | } 129 | //MARK:App already launched or not 130 | 131 | /// App already launched or not 132 | /// 133 | /// - Returns: App already launched true or false 134 | func isAppAlreadyLaunchedOnce()->Bool{ 135 | let defaults = UserDefaults.standard 136 | if let isAppAlreadyLaunchedOnce = defaults.string(forKey: "kIsAppAlreadyLaunchedOnce"){ 137 | print("App already launched : \(isAppAlreadyLaunchedOnce)") 138 | return true 139 | }else{ 140 | defaults.set(true, forKey: "kIsAppAlreadyLaunchedOnce") 141 | return false 142 | } 143 | } 144 | //MARK: Read json and save to coredata 145 | private func readJson() { 146 | do { 147 | if let file = Bundle.main.url(forResource: "DidYouKnowFacts", withExtension: "json") { 148 | let data = try Data(contentsOf: file) 149 | let json = try JSONSerialization.jsonObject(with: data, options: []) 150 | if let object = json as? [String: Any] { 151 | // json is a dictionary 152 | print(object) 153 | } else if let object = json as? [Any] { 154 | // json is an array 155 | for data in object{ 156 | if let items : NSDictionary = data as? NSDictionary 157 | { 158 | self.factsModel.fact = items["fact"] as!String 159 | self.factsModel.date = items["date"] as! String 160 | arrayFacts.append(self.factsModel) 161 | } 162 | 163 | } 164 | SCDCoreDataWrapper.sharedInstance.saveFacts(facts: arrayFacts, entity: "Facts") 165 | fetchTodaysFact() 166 | print(object) 167 | } else { 168 | print("JSON is invalid") 169 | } 170 | } else { 171 | print("no file") 172 | } 173 | } catch { 174 | print(error.localizedDescription) 175 | } 176 | } 177 | 178 | 179 | } 180 | extension String { 181 | func capitalizingFirstLetter() -> String { 182 | let first = String(characters.prefix(1)).capitalized 183 | let other = String(characters.dropFirst()) 184 | return first + other 185 | } 186 | 187 | mutating func capitalizeFirstLetter() { 188 | self = self.capitalizingFirstLetter() 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Did you know? 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/SharedCoreData.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.com.ileaf.SharedCoreData 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/SharedCoreData.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | SharedCoreData.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreData/SharedCoreData.xcdatamodeld/SharedCoreData.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreDataTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreDataTests/SharedCoreDataTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SharedCoreDataTests.swift 3 | // SharedCoreDataTests 4 | // 5 | // Created by iLeaf Solutions on 14/12/17. 6 | // Copyright © 2017 iLeaf. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SharedCoreData 11 | 12 | class SharedCoreDataTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreDataUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Did-you-know-master/SharedCoreDataUITests/SharedCoreDataUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SharedCoreDataUITests.swift 3 | // SharedCoreDataUITests 4 | // 5 | // Created by iLeaf Solutions on 14/12/17. 6 | // Copyright © 2017 iLeaf. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class SharedCoreDataUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Did you Know? 2 | A notification center widget with shared core data. 3 | Example project for sharing data between iOS app extension and container app through shared core data. 4 | 5 | 6 | 7 | ## Preview 8 | 9 | 10 | ## Installation 11 | 12 | ### Compatibility 13 | 14 | - iOS 10.3+ 15 | 16 | - Xcode 8.0+ 17 | 18 | ## Usage 19 | 20 | 1. Create an app group 21 | 22 | App Groups are the scheme iOS uses to allow different apps to share data. If the apps have the right entitlements and proper provisioning, they can access a shared directory outside of their normal iOS sandbox. To share data between widget extension and container app, select the target for your app and go to the capabilities tab. There, enable app groups. Repeat the same in the target of your widget extension 23 | 24 | 25 | 26 | When you flip that switch, Xcode will talk to the developer center to configure your app ID for app groups. Next it'll ask you for a group name. Give it one and it'll create and download a new provisioning profile. Now, your app and its extension are ready to share the container, so it’s time to put the data in it. 27 | 28 | 2. Create your core data in shared container 29 | 30 | - Move SCDCoreDataWrapper.swift class, the .xcdatamodeled and NSManagedObject subclass to my SharedCode Framework. 31 | - Get the URL of the group container with containerURL(forSecurityApplicationGroupIdentifier: of FileManager passing the container identifier. You need to point to the security group as your store url so that they are both being stored to that. 32 | 33 | ## Author 34 | iLeaf Solutions 35 | [http://www.ileafsolutions.com](http://www.ileafsolutions.com) 36 | --------------------------------------------------------------------------------