| @@ -0,0 +1,56 @@ | ||
| // | ||
| // Remind_Before.swift | ||
| // SAReminder | ||
| // | ||
| // Created by Alexei Sitalov on 3/28/16. | ||
| // Copyright © 2016 Admin. All rights reserved. | ||
| // | ||
| import UIKit | ||
|
|
||
| class Remind_Before { | ||
|
|
||
|
|
||
| static func scheduleBefore(index:Int) -> NSDateComponents { | ||
|
|
||
| let dateComponents = NSDateComponents () | ||
|
|
||
| if index == 1 { | ||
| dateComponents.minute = -5 | ||
| } else if index == 2 { | ||
| dateComponents.minute = -10 | ||
| }else if index == 3 { | ||
| dateComponents.minute = -15 | ||
| }else if index == 4 { | ||
| dateComponents.minute = -30 | ||
| } else if index == 5 { | ||
| dateComponents.minute = -60 | ||
| } else if index == 6 { | ||
| dateComponents.minute = -1140 | ||
|
|
||
| } | ||
|
|
||
| return dateComponents | ||
| } | ||
|
|
||
|
|
||
| static func truncateSecondsForDate(fromDate: NSDate) -> NSDate { | ||
|
|
||
| let calendar : NSCalendar = NSCalendar.currentCalendar() | ||
| let unitFlags : NSCalendarUnit = [.Era, .Year, .Month, .Day, .Hour, .Minute] | ||
| let fromDateComponents: NSDateComponents = calendar.components(unitFlags, fromDate: fromDate) | ||
|
|
||
| return calendar.dateFromComponents(fromDateComponents)! | ||
|
|
||
| } | ||
|
|
||
| static func truncateDaysForDate(fromDate: NSDate) -> NSDate { | ||
|
|
||
| let calendar: NSCalendar = NSCalendar.currentCalendar() | ||
| let unitFlags : NSCalendarUnit = [.Year, .Month, .Day] | ||
| let fromDateComponents: NSDateComponents = calendar.components(unitFlags, fromDate: fromDate) | ||
|
|
||
| return calendar.dateFromComponents(fromDateComponents)! | ||
|
|
||
| } | ||
| } |
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "info" : { | ||
| "version" : 1, | ||
| "author" : "xcode" | ||
| } | ||
| } |
| @@ -0,0 +1,142 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "iphone", | ||
| "extent" : "full-screen", | ||
| "minimum-system-version" : "8.0", | ||
| "subtype" : "736h", | ||
| "scale" : "3x" | ||
| }, | ||
| { | ||
| "orientation" : "landscape", | ||
| "idiom" : "iphone", | ||
| "extent" : "full-screen", | ||
| "minimum-system-version" : "8.0", | ||
| "subtype" : "736h", | ||
| "scale" : "3x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "iphone", | ||
| "extent" : "full-screen", | ||
| "minimum-system-version" : "8.0", | ||
| "subtype" : "667h", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "iphone", | ||
| "extent" : "full-screen", | ||
| "minimum-system-version" : "7.0", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "iphone", | ||
| "extent" : "full-screen", | ||
| "minimum-system-version" : "7.0", | ||
| "subtype" : "retina4", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "ipad", | ||
| "extent" : "full-screen", | ||
| "minimum-system-version" : "7.0", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "orientation" : "landscape", | ||
| "idiom" : "ipad", | ||
| "extent" : "full-screen", | ||
| "minimum-system-version" : "7.0", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "ipad", | ||
| "extent" : "full-screen", | ||
| "minimum-system-version" : "7.0", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "orientation" : "landscape", | ||
| "idiom" : "ipad", | ||
| "extent" : "full-screen", | ||
| "minimum-system-version" : "7.0", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "iphone", | ||
| "extent" : "full-screen", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "iphone", | ||
| "extent" : "full-screen", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "iphone", | ||
| "extent" : "full-screen", | ||
| "subtype" : "retina4", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "ipad", | ||
| "extent" : "to-status-bar", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "ipad", | ||
| "extent" : "full-screen", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "orientation" : "landscape", | ||
| "idiom" : "ipad", | ||
| "extent" : "to-status-bar", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "orientation" : "landscape", | ||
| "idiom" : "ipad", | ||
| "extent" : "full-screen", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "ipad", | ||
| "extent" : "to-status-bar", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "orientation" : "portrait", | ||
| "idiom" : "ipad", | ||
| "extent" : "full-screen", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "orientation" : "landscape", | ||
| "idiom" : "ipad", | ||
| "extent" : "to-status-bar", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "orientation" : "landscape", | ||
| "idiom" : "ipad", | ||
| "extent" : "full-screen", | ||
| "scale" : "2x" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "version" : 1, | ||
| "author" : "xcode" | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "1x", | ||
| "filename" : "child-selected.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "2x", | ||
| "filename" : "child-selected@2x.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "3x", | ||
| "filename" : "child-selected@3x.png" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "version" : 1, | ||
| "author" : "xcode" | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "1x", | ||
| "filename" : "child.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "2x", | ||
| "filename" : "child@2x.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "3x", | ||
| "filename" : "child@3x.png" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "version" : 1, | ||
| "author" : "xcode" | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "1x", | ||
| "filename" : "phone-selected.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "2x", | ||
| "filename" : "phone-selected@2x.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "3x", | ||
| "filename" : "phone-selected@3x.png" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "version" : 1, | ||
| "author" : "xcode" | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "1x", | ||
| "filename" : "phone.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "2x", | ||
| "filename" : "phone@2x.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "3x", | ||
| "filename" : "phone@3x.png" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "version" : 1, | ||
| "author" : "xcode" | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "1x", | ||
| "filename" : "shopping-cart-selected.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "2x", | ||
| "filename" : "shopping-cart-selected@2x.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "3x", | ||
| "filename" : "shopping-cart-selected@3x.png" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "version" : 1, | ||
| "author" : "xcode" | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "1x", | ||
| "filename" : "shopping-cart.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "2x", | ||
| "filename" : "shopping-cart@2x.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "3x", | ||
| "filename" : "shopping-cart@3x.png" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "version" : 1, | ||
| "author" : "xcode" | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "1x", | ||
| "filename" : "travel-selected.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "2x", | ||
| "filename" : "travel-selected@2x.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "3x", | ||
| "filename" : "travel-selected@3x.png" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "version" : 1, | ||
| "author" : "xcode" | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "1x", | ||
| "filename" : "travel.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "2x", | ||
| "filename" : "travel@2x.png" | ||
| }, | ||
| { | ||
| "idiom" : "universal", | ||
| "scale" : "3x", | ||
| "filename" : "travel@3x.png" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "version" : 1, | ||
| "author" : "xcode" | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| // | ||
| // BasicViewController.h | ||
| // Example | ||
| // | ||
| // Created by Jonathan Tribouharet. | ||
| // | ||
|
|
||
| #import <UIKit/UIKit.h> | ||
|
|
||
| #import <JTCalendar/JTCalendar.h> | ||
|
|
||
| @interface BasicViewController : UIViewController <JTCalendarDelegate> | ||
|
|
||
| @property (weak, nonatomic) IBOutlet JTCalendarMenuView *calendarMenuView; | ||
| @property (weak, nonatomic) IBOutlet JTHorizontalCalendarView *calendarContentView; | ||
|
|
||
| @property (strong, nonatomic) JTCalendarManager *calendarManager; | ||
|
|
||
| - (NSArray*)getEntityDescriptionArray; | ||
|
|
||
| //@property (weak, nonatomic) IBOutlet NSLayoutConstraint *calendarContentViewHeight; | ||
|
|
||
| @end |
| @@ -0,0 +1,317 @@ | ||
| // | ||
| // BasicViewController.m | ||
| // Example | ||
| // | ||
| // Created by Jonathan Tribouharet. | ||
| // | ||
|
|
||
| #import "BasicViewController.h" | ||
| #import <CoreData/CoreData.h> | ||
| #import "SAReminder-swift.h" | ||
|
|
||
|
|
||
| @interface BasicViewController() <NSFetchedResultsControllerDelegate> { | ||
|
|
||
| NSMutableDictionary *_eventsByDate; | ||
|
|
||
| NSDate *_todayDate; | ||
| NSDate *_minDate; | ||
| NSDate *_maxDate; | ||
|
|
||
| NSDate *_dateSelected; | ||
| NSDate *_newDate1; | ||
| } | ||
|
|
||
| @property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; | ||
| @property (strong, nonatomic) NSManagedObjectContext *context; | ||
|
|
||
| @end | ||
|
|
||
| @implementation BasicViewController | ||
|
|
||
| - (void)initializeFetchedResultsController | ||
| { | ||
| NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Notes"]; | ||
|
|
||
| NSSortDescriptor *lastNameSort = [NSSortDescriptor sortDescriptorWithKey:@"dateInDateFormat" ascending:YES]; | ||
| [request setPropertiesToFetch:@[@"dateInDateFormat"]]; | ||
|
|
||
| [request setSortDescriptors:@[lastNameSort]]; | ||
|
|
||
| // NSManagedObjectContext *moc = …; //Retrieve the main queue NSManagedObjectContext | ||
|
|
||
| [self setFetchedResultsController:[[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.context sectionNameKeyPath:nil cacheName:nil]]; | ||
| [[self fetchedResultsController] setDelegate:self]; | ||
|
|
||
| NSError *error = nil; | ||
| if (![[self fetchedResultsController] performFetch:&error]) { | ||
| NSLog(@"Failed to initialize FetchedResultsController: %@\n%@", [error localizedDescription], [error userInfo]); | ||
| abort(); | ||
| } | ||
| } | ||
|
|
||
| - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil | ||
| { | ||
| self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; | ||
| if(!self){ | ||
| return nil; | ||
| } | ||
|
|
||
| self.title = @"Basic"; | ||
|
|
||
| return self; | ||
| } | ||
|
|
||
| #pragma mark - Buttons callback | ||
|
|
||
| - (IBAction)didGoTodayTouch | ||
| { | ||
| [_calendarManager setDate:_todayDate]; | ||
| } | ||
|
|
||
| - (IBAction)didChangeModeTouch | ||
| { | ||
| _calendarManager.settings.weekModeEnabled = !_calendarManager.settings.weekModeEnabled; | ||
| [_calendarManager reload]; | ||
|
|
||
| CGFloat newHeight = 300; | ||
| if(_calendarManager.settings.weekModeEnabled){ | ||
| newHeight = 85.; | ||
| } | ||
|
|
||
| //self.calendarContentViewHeight.constant = newHeight; | ||
| [self.view layoutIfNeeded]; | ||
| } | ||
|
|
||
| #pragma mark - CalendarManager delegate | ||
|
|
||
| // Exemple of implementation of prepareDayView method | ||
| // Used to customize the appearance of dayView | ||
| - (void)calendar:(JTCalendarManager *)calendar prepareDayView:(JTCalendarDayView *)dayView | ||
| { | ||
|
|
||
| // Today | ||
| if([_calendarManager.dateHelper date:[NSDate date] isTheSameDayThan:dayView.date]){ | ||
| dayView.circleView.hidden = NO; | ||
| dayView.circleView.backgroundColor = [UIColor blueColor]; | ||
| dayView.dotView.backgroundColor = [UIColor whiteColor]; | ||
| dayView.textLabel.textColor = [UIColor whiteColor]; | ||
| } | ||
| // Selected date | ||
| else if(_dateSelected && [_calendarManager.dateHelper date:_dateSelected isTheSameDayThan:dayView.date]){ | ||
| dayView.circleView.hidden = NO; | ||
| dayView.circleView.backgroundColor = [UIColor redColor]; | ||
| dayView.dotView.backgroundColor = [UIColor whiteColor]; | ||
| dayView.textLabel.textColor = [UIColor whiteColor]; | ||
| } | ||
| // Other month | ||
| else if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){ | ||
| dayView.circleView.hidden = YES; | ||
| dayView.dotView.backgroundColor = [UIColor redColor]; | ||
| dayView.textLabel.textColor = [UIColor brownColor]; | ||
| } | ||
| // Another day of the current month | ||
| else{ | ||
| dayView.circleView.hidden = YES; | ||
| dayView.dotView.backgroundColor = [UIColor redColor]; | ||
| dayView.textLabel.textColor = [UIColor blackColor]; | ||
| } | ||
|
|
||
| if([self haveEventForDay:dayView.date]){ | ||
| dayView.dotView.hidden = NO; | ||
| } | ||
| else{ | ||
| dayView.dotView.hidden = YES; | ||
| } | ||
| } | ||
|
|
||
| - (void)calendar:(JTCalendarManager *)calendar didTouchDayView:(JTCalendarDayView *)dayView | ||
| { | ||
| _dateSelected = dayView.date; | ||
|
|
||
| _newDate1 = [_dateSelected dateByAddingTimeInterval:60*60*24]; | ||
|
|
||
| // Animation for the circleView | ||
| dayView.circleView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1); | ||
| [UIView transitionWithView:dayView | ||
| duration:.3 | ||
| options:0 | ||
| animations:^{ | ||
| dayView.circleView.transform = CGAffineTransformIdentity; | ||
| [_calendarManager reload]; | ||
| } completion:nil]; | ||
|
|
||
|
|
||
|
|
||
| [self compareDates]; | ||
|
|
||
| // Load the previous or next page if touch a day from another month | ||
| if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){ | ||
| if([_calendarContentView.date compare:dayView.date] == NSOrderedAscending){ | ||
| [_calendarContentView loadNextPageWithAnimation]; | ||
| } | ||
| else{ | ||
| [_calendarContentView loadPreviousPageWithAnimation]; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #pragma mark - CalendarManager delegate - Page mangement | ||
|
|
||
| // Used to limit the date for the calendar, optional | ||
| - (BOOL)calendar:(JTCalendarManager *)calendar canDisplayPageWithDate:(NSDate *)date | ||
| { | ||
| return [_calendarManager.dateHelper date:date isEqualOrAfter:_minDate andEqualOrBefore:_maxDate]; | ||
| } | ||
|
|
||
| - (void)calendarDidLoadNextPage:(JTCalendarManager *)calendar | ||
| { | ||
| // NSLog(@"Next page loaded"); | ||
| } | ||
|
|
||
| - (void)calendarDidLoadPreviousPage:(JTCalendarManager *)calendar | ||
| { | ||
| // NSLog(@"Previous page loaded"); | ||
| } | ||
|
|
||
| #pragma mark - Fake data | ||
|
|
||
| - (void)createMinAndMaxDate | ||
| { | ||
| _todayDate = [NSDate date]; | ||
|
|
||
| // Min date will be 2 month before today | ||
| _minDate = [_calendarManager.dateHelper addToDate:_todayDate months:0]; | ||
|
|
||
| // Max date will be 2 month after today | ||
| _maxDate = [_calendarManager.dateHelper addToDate:_todayDate months:5]; | ||
| } | ||
|
|
||
| // Used only to have a key for _eventsByDate | ||
| - (NSDateFormatter *)dateFormatter | ||
| { | ||
| static NSDateFormatter *dateFormatter; | ||
| if(!dateFormatter){ | ||
| dateFormatter = [NSDateFormatter new]; | ||
| dateFormatter.dateFormat = @"dd-MM-yyyy"; | ||
| } | ||
|
|
||
| return dateFormatter; | ||
| } | ||
|
|
||
| - (BOOL)haveEventForDay:(NSDate *)date | ||
| { | ||
| NSString *key = [[self dateFormatter] stringFromDate:date]; | ||
|
|
||
| if(_eventsByDate[key] && [_eventsByDate[key] count] > 0){ | ||
| return YES; | ||
| } | ||
|
|
||
| return NO; | ||
|
|
||
| } | ||
|
|
||
| - (NSArray*)getEntityDescriptionArray { | ||
|
|
||
| NSEntityDescription *entity = [NSEntityDescription entityForName:@"Notes" inManagedObjectContext:_context]; | ||
|
|
||
| NSFetchRequest *request = [[NSFetchRequest alloc] init]; | ||
| [request setEntity:entity]; | ||
| [request setResultType:NSDictionaryResultType]; | ||
| [request setReturnsDistinctResults:YES]; | ||
| [request setPropertiesToFetch:@[@"dateInDateFormat"]]; | ||
|
|
||
| // Execute the fetch. | ||
| NSError *error; | ||
| NSArray *objects = [_context executeFetchRequest:request error:&error]; | ||
| if (objects == nil) { | ||
| // Handle the error. | ||
| } | ||
|
|
||
| return objects; | ||
| } | ||
|
|
||
| - (void)viewDidLoad | ||
| { | ||
| [super viewDidLoad]; | ||
|
|
||
| self.view.backgroundColor = [UIColor colorWithPatternImage:[GetBackgroundImage getImage]]; | ||
| self.tabBarController.tabBar.backgroundImage = [UIImage imageNamed:@"tabbar"]; | ||
|
|
||
| self.context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; | ||
|
|
||
| _calendarManager = [JTCalendarManager new]; | ||
| _calendarManager.delegate = self; | ||
| [self getEntityDescriptionArray]; | ||
| // Generate random events sort by date using a dateformatter for the demonstration | ||
| [self createRandomEvents]; | ||
|
|
||
| // Create a min and max date for limit the calendar, optional | ||
| [self createMinAndMaxDate]; | ||
|
|
||
| [_calendarManager setMenuView:_calendarMenuView]; | ||
| [_calendarManager setContentView:_calendarContentView]; | ||
| [_calendarManager setDate:_todayDate]; | ||
| } | ||
|
|
||
| -(void)viewWillAppear:(BOOL)animated | ||
| { | ||
| [super viewWillAppear:animated]; | ||
|
|
||
| [self getEntityDescriptionArray]; | ||
| [self createRandomEvents]; | ||
|
|
||
| } | ||
|
|
||
|
|
||
|
|
||
| - (void) compareDates { | ||
|
|
||
| for(int i = 0; i < [self.getEntityDescriptionArray count]; ++i){ | ||
|
|
||
| NSDictionary *dict = [self.getEntityDescriptionArray objectAtIndex:i]; | ||
| NSDate *dateToCompare = [dict[@"dateInDateFormat"] dateByAddingTimeInterval:60*60*24]; | ||
|
|
||
| NSCalendar* calendar = [NSCalendar currentCalendar]; | ||
| unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay; | ||
|
|
||
| NSDateComponents *comp1 = [calendar components:unitFlags fromDate:_newDate1]; | ||
| NSDateComponents *comp2 = [calendar components:unitFlags fromDate:dateToCompare]; | ||
|
|
||
| NSDate *dte1 = [calendar dateFromComponents:comp1]; | ||
| NSDate *dte2 = [calendar dateFromComponents:comp2]; | ||
|
|
||
| if ([dte1 isEqualToDate:dte2]) { | ||
| NSLog(@"equal dates"); | ||
| NSMutableDictionary *dict = [NSMutableDictionary new]; | ||
| [dict setValue:dte1 forKey:@"searchDate"]; | ||
| NSNotification *notification = [NSNotification notificationWithName:@"MyNotification" object:nil userInfo:dict]; | ||
| [[NSNotificationCenter defaultCenter] postNotification:notification]; | ||
|
|
||
| [self.tabBarController setSelectedIndex:0]; | ||
| } | ||
|
|
||
|
|
||
| } | ||
| } | ||
|
|
||
| - (void)createRandomEvents | ||
| { | ||
|
|
||
| _eventsByDate = [NSMutableDictionary new]; | ||
|
|
||
| for(int i = 0; i < [self.getEntityDescriptionArray count]; ++i){ | ||
|
|
||
| NSDictionary *dict = [self.getEntityDescriptionArray objectAtIndex:i]; | ||
|
|
||
| NSString *key = [[self dateFormatter] stringFromDate:dict[@"dateInDateFormat"]]; // randomDate IN STRING FORMAT | ||
|
|
||
| if(!_eventsByDate[key]){ | ||
| _eventsByDate[key] = [NSMutableArray new]; | ||
| } | ||
|
|
||
| [_eventsByDate[key] addObject:dict]; | ||
| } | ||
| } | ||
|
|
||
| @end |
| @@ -0,0 +1,144 @@ | ||
| /* | ||
| The MIT License (MIT) | ||
| Copyright (c) 2015 AhmetKeskin | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| */ | ||
|
|
||
| import Foundation | ||
| import AVKit | ||
|
|
||
| class LocalNotificationHelper: NSObject { | ||
|
|
||
| let LOCAL_NOTIFICATION_CATEGORY : String = "LocalNotificationCategory" | ||
|
|
||
| // MARK: - Shared Instance | ||
| class func sharedInstance() -> LocalNotificationHelper { | ||
| struct Singleton { | ||
| static var sharedInstance = LocalNotificationHelper() | ||
| } | ||
| return Singleton.sharedInstance | ||
| } | ||
|
|
||
| // MARK: - Schedule Notification | ||
| func scheduleNotificationWithKey(key: String, title: String, message: String, seconds: NSDate, userInfo: [NSObject: AnyObject]?) { | ||
| // let date = NSDate(timeIntervalSinceNow: NSTimeInterval(seconds)!) | ||
| let date = NSDate () | ||
| let notification = notificationWithTitle(key, title: title, message: message, date: date, userInfo: userInfo, soundName: nil, hasAction: true) | ||
| notification.category = LOCAL_NOTIFICATION_CATEGORY | ||
| UIApplication.sharedApplication().scheduleLocalNotification(notification) | ||
| } | ||
|
|
||
| func scheduleNotificationWithKey(key: String, title: String, message: String, date: NSDate, userInfo: [NSObject: AnyObject]?){ | ||
| let notification = notificationWithTitle(key, title: title, message: message, date: date, userInfo: ["key": key], soundName: nil, hasAction: true) | ||
| notification.category = LOCAL_NOTIFICATION_CATEGORY | ||
| UIApplication.sharedApplication().scheduleLocalNotification(notification) | ||
| } | ||
|
|
||
| func cancelNotificationWithKey(key: String, title: String, message: String, date: NSDate, userInfo: [NSObject: AnyObject]?){ | ||
| let notification = notificationWithTitle(key, title: title, message: message, date: date, userInfo: ["key": key], soundName: nil, hasAction: true) | ||
| notification.category = LOCAL_NOTIFICATION_CATEGORY | ||
| UIApplication.sharedApplication().cancelLocalNotification(notification) | ||
| } | ||
|
|
||
| func scheduleNotificationWithKey(key: String, title: String, message: String, seconds: Double, soundName: String, userInfo: [NSObject: AnyObject]?){ | ||
| let date = NSDate(timeIntervalSinceNow: NSTimeInterval(seconds)) | ||
| let notification = notificationWithTitle(key, title: title, message: message, date: date, userInfo: ["key": key], soundName: soundName, hasAction: true) | ||
| UIApplication.sharedApplication().scheduleLocalNotification(notification) | ||
| } | ||
|
|
||
| func scheduleNotificationWithKey(key: String, title: String, message: String, date: NSDate, soundName: String, userInfo: [NSObject: AnyObject]?){ | ||
| let notification = notificationWithTitle(key, title: title, message: message, date: date, userInfo: ["key": key], soundName: soundName, hasAction: true) | ||
| UIApplication.sharedApplication().scheduleLocalNotification(notification) | ||
| } | ||
|
|
||
| // MARK: - Present Notification | ||
| func presentNotificationWithKey(key: String, title: String, message: String, soundName: String, userInfo: [NSObject: AnyObject]?) { | ||
| let notification = notificationWithTitle(key, title: title, message: message, date: nil, userInfo: ["key": key], soundName: nil, hasAction: true) | ||
| UIApplication.sharedApplication().presentLocalNotificationNow(notification) | ||
| } | ||
|
|
||
| // MARK: - Create Notification | ||
| func notificationWithTitle(key : String, title: String, message: String, date: NSDate?, userInfo: [NSObject: AnyObject]?, soundName: String?, hasAction: Bool) -> UILocalNotification { | ||
|
|
||
| var dct : Dictionary<String,AnyObject> = userInfo as! Dictionary<String,AnyObject> | ||
| dct["key"] = NSString(string: key) as String | ||
|
|
||
| let notification = UILocalNotification() | ||
| notification.alertAction = title | ||
| notification.alertBody = message | ||
| notification.userInfo = dct | ||
| notification.soundName = soundName ?? UILocalNotificationDefaultSoundName | ||
| notification.fireDate = date | ||
| notification.hasAction = hasAction | ||
| notification.applicationIconBadgeNumber = 1 | ||
| return notification | ||
| } | ||
|
|
||
| func getNotificationWithKey(key : String) -> UILocalNotification { | ||
|
|
||
| var notif : UILocalNotification? | ||
|
|
||
| for notification in UIApplication.sharedApplication().scheduledLocalNotifications! where notification.userInfo!["key"] as! String == key{ | ||
| notif = notification | ||
| break | ||
| } | ||
|
|
||
| return notif! | ||
| } | ||
|
|
||
| func cancelNotification(key : String){ | ||
|
|
||
| for notification in UIApplication.sharedApplication().scheduledLocalNotifications! where notification.userInfo!["key"] as! String == key{ | ||
| UIApplication.sharedApplication().cancelLocalNotification(notification) | ||
| break | ||
| } | ||
| } | ||
|
|
||
| func getAllNotifications() -> [UILocalNotification]? { | ||
| return UIApplication.sharedApplication().scheduledLocalNotifications | ||
| } | ||
|
|
||
| func cancelAllNotifications() { | ||
| UIApplication.sharedApplication().cancelAllLocalNotifications() | ||
| } | ||
|
|
||
| func registerUserNotificationWithActionButtons(actions actions : [UIUserNotificationAction]){ | ||
|
|
||
| let category = UIMutableUserNotificationCategory() | ||
| category.identifier = LOCAL_NOTIFICATION_CATEGORY | ||
|
|
||
| category.setActions(actions, forContext: UIUserNotificationActionContext.Default) | ||
|
|
||
| let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: NSSet(object: category) as? Set<UIUserNotificationCategory>) | ||
| UIApplication.sharedApplication().registerUserNotificationSettings(settings) | ||
| } | ||
|
|
||
| func registerUserNotification(){ | ||
|
|
||
| let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil) | ||
| UIApplication.sharedApplication().registerUserNotificationSettings(settings) | ||
| } | ||
|
|
||
| func createUserNotificationActionButton(identifier identifier : String, title : String) -> UIUserNotificationAction{ | ||
|
|
||
| let actionButton = UIMutableUserNotificationAction() | ||
| actionButton.identifier = identifier | ||
| actionButton.title = title | ||
| actionButton.activationMode = UIUserNotificationActivationMode.Background | ||
| actionButton.authenticationRequired = true | ||
| actionButton.destructive = false | ||
|
|
||
| return actionButton | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,25 @@ | ||
| // | ||
| // Notes.swift | ||
| // | ||
| // | ||
| // Created by Alexei Sitalov on 3/23/16. | ||
| // | ||
| // | ||
| import Foundation | ||
| import CoreData | ||
|
|
||
|
|
||
| class Notes: NSManagedObject { | ||
|
|
||
| @NSManaged var buttonName: String? | ||
| @NSManaged var contentText: String? | ||
| @NSManaged var date: String? | ||
| @NSManaged var status: String? | ||
| @NSManaged var titleText: String? | ||
| @NSManaged var index: NSNumber? | ||
| @NSManaged var dateInDateFormat: NSDate? | ||
| @NSManaged var someTimeBefore: NSDate? | ||
| @NSManaged var searchDate: NSDate? | ||
|
|
||
| } |
| @@ -0,0 +1,13 @@ | ||
| // | ||
| // YLCheckToUnlockViewController.h | ||
| // YLSwipeLockViewDemo | ||
| // | ||
| // Created by 肖 玉龙 on 15/2/28. | ||
| // Copyright (c) 2015年 Yulong Xiao. All rights reserved. | ||
| // | ||
|
|
||
| #import <UIKit/UIKit.h> | ||
|
|
||
| @interface YLCheckToUnlockViewController : UIViewController | ||
|
|
||
| @end |
| @@ -0,0 +1,111 @@ | ||
| // | ||
| // YLCheckToUnlockViewController.m | ||
| // YLSwipeLockViewDemo | ||
| // | ||
| // Created by 肖 玉龙 on 15/2/28. | ||
| // Copyright (c) 2015年 Yulong Xiao. All rights reserved. | ||
| // | ||
|
|
||
| #import "YLCheckToUnlockViewController.h" | ||
| #import "YLSwipeLockView.h" | ||
| #import "UIKit/UIKit.h" | ||
|
|
||
|
|
||
| @interface YLCheckToUnlockViewController ()<YLSwipeLockViewDelegate> | ||
|
|
||
| @property (nonatomic, weak) YLSwipeLockView *lockView; | ||
| @property (nonatomic, weak) UILabel *titleLabel; | ||
| @property (nonatomic) NSUInteger unmatchCounter; | ||
| @property (nonatomic, weak) UILabel *counterLabel; | ||
|
|
||
|
|
||
| @end | ||
|
|
||
| @implementation YLCheckToUnlockViewController | ||
|
|
||
| - (void)viewDidLoad { | ||
| [super viewDidLoad]; | ||
|
|
||
| self.view.backgroundColor = [UIColor colorWithRed:35/255.0 green:39/255.0 blue:54/255.0 alpha:1]; | ||
|
|
||
| UILabel *titleLabel = [[UILabel alloc] init]; | ||
| titleLabel.text = @"swipe to unlock"; | ||
| titleLabel.textColor = [UIColor whiteColor]; | ||
| titleLabel.textAlignment = NSTextAlignmentCenter; | ||
| titleLabel.frame = CGRectMake(10, 60, self.view.bounds.size.width - 20, 20); | ||
| titleLabel.font = [UIFont boldSystemFontOfSize:16]; | ||
| [self.view addSubview:titleLabel]; | ||
| self.titleLabel = titleLabel; | ||
|
|
||
| UILabel *counterLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 160, self.view.bounds.size.width - 20, 20)]; | ||
| counterLabel.textColor = [UIColor redColor]; | ||
| counterLabel.textAlignment = NSTextAlignmentCenter; | ||
| counterLabel.font = [UIFont systemFontOfSize:14]; | ||
| [self.view addSubview:counterLabel]; | ||
| self.counterLabel = counterLabel; | ||
| self.counterLabel.hidden = YES; | ||
|
|
||
|
|
||
| CGFloat viewWidth = self.view.bounds.size.width - 40; | ||
| CGFloat viewHeight = viewWidth; | ||
|
|
||
| YLSwipeLockView *lockView = [[YLSwipeLockView alloc] initWithFrame:CGRectMake(20, self.view.bounds.size.height - viewHeight - 40 - 100, viewWidth, viewHeight)]; | ||
| [self.view addSubview:lockView]; | ||
|
|
||
| self.lockView = lockView; | ||
| self.lockView.delegate = self; | ||
|
|
||
| self.unmatchCounter = 5; | ||
|
|
||
| } | ||
|
|
||
| - (void)didReceiveMemoryWarning { | ||
| [super didReceiveMemoryWarning]; | ||
| } | ||
|
|
||
| -(YLSwipeLockViewState)swipeView:(YLSwipeLockView *)swipeView didEndSwipeWithPassword:(NSString *)password | ||
| { | ||
| NSString *savedPassword = [[NSUserDefaults standardUserDefaults] objectForKey:@"gesturePassword"]; | ||
| if ([savedPassword isEqualToString:password]) { | ||
| [self dismiss]; | ||
| return YLSwipeLockViewStateNormal; | ||
| }else{ | ||
| self.unmatchCounter--; | ||
| if (self.unmatchCounter == 0) { | ||
|
|
||
|
|
||
| self.counterLabel.hidden = NO; | ||
| self.unmatchCounter = 5; | ||
|
|
||
| }else { | ||
|
|
||
| self.counterLabel.text = [NSString stringWithFormat:@"Wrong password"]; | ||
| self.counterLabel.hidden = NO; | ||
| } | ||
| return YLSwipeLockViewStateWarning; | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
| - (void)dismissViewController // DISMISSING THE BLOCK SCREEN!!!!! | ||
| { | ||
| //if you are pushing your viewControler, then use below single line code | ||
| // [self.navigationController popViewControllerAnimated:YES]; | ||
| //if you are presnting ViewController modally. then use below code | ||
| //[self dismissModalViewControllerAnimated:YES]; | ||
|
|
||
| } | ||
|
|
||
| -(void)dismiss{ | ||
|
|
||
| if (self.presentingViewController) { | ||
|
|
||
| [self dismissViewControllerAnimated:YES completion:nil]; | ||
|
|
||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
| @end |
| @@ -0,0 +1,13 @@ | ||
| // | ||
| // YLInitSwipePasswordController.h | ||
| // YLSwipeLockViewDemo | ||
| // | ||
| // Created by 肖 玉龙 on 15/2/27. | ||
| // Copyright (c) 2015年 Yulong Xiao. All rights reserved. | ||
| // | ||
|
|
||
| #import <UIKit/UIKit.h> | ||
|
|
||
| @interface YLInitSwipePasswordController : UIViewController | ||
|
|
||
| @end |
| @@ -0,0 +1,97 @@ | ||
|
|
||
| // YLInitSwipePasswordController.m | ||
| // YLSwipeLockViewDemo | ||
| // | ||
| // Created by 肖 玉龙 on 15/2/27. | ||
| // Copyright (c) 2015年 Yulong Xiao. All rights reserved. | ||
| // | ||
|
|
||
| #import "YLInitSwipePasswordController.h" | ||
| #import "YLSwipeLockView.h" | ||
|
|
||
| @interface YLInitSwipePasswordController ()<YLSwipeLockViewDelegate> | ||
| @property (nonatomic, weak) YLSwipeLockView *lockView; | ||
| @property (nonatomic, weak) UILabel *titleLabel; | ||
| @property (nonatomic, strong) NSString *passwordString; | ||
| @property (nonatomic, weak) UIButton *resetButton; | ||
| @end | ||
|
|
||
| @implementation YLInitSwipePasswordController | ||
|
|
||
| - (void)viewDidLoad { | ||
| [super viewDidLoad]; | ||
| self.view.backgroundColor = [UIColor colorWithRed:35/255.0 green:39/255.0 blue:54/255.0 alpha:1]; | ||
|
|
||
| UILabel *titleLabel = [[UILabel alloc] init]; | ||
| titleLabel.text = @"set your gesture password"; | ||
| titleLabel.textColor = [UIColor whiteColor]; | ||
| titleLabel.textAlignment = NSTextAlignmentCenter; | ||
| titleLabel.frame = CGRectMake(40, 60, self.view.bounds.size.width - 80, 20); | ||
| titleLabel.font = [UIFont boldSystemFontOfSize:16]; | ||
| [self.view addSubview:titleLabel]; | ||
| self.titleLabel = titleLabel; | ||
|
|
||
| CGFloat viewWidth = self.view.bounds.size.width - 40; | ||
| CGFloat viewHeight = viewWidth; | ||
|
|
||
| YLSwipeLockView *lockView = [[YLSwipeLockView alloc] initWithFrame:CGRectMake(20, self.view.bounds.size.height - viewHeight - 40 - 100, viewWidth, viewHeight)]; | ||
| [self.view addSubview:lockView]; | ||
|
|
||
| self.lockView = lockView; | ||
| self.lockView.delegate = self; | ||
|
|
||
| UIButton *resetButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.bounds.size.width - 60, 60, 40, 20)]; | ||
| [resetButton setTitle:@"reset" forState:UIControlStateNormal]; | ||
| [resetButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; | ||
| [resetButton addTarget:self action:@selector(reset) forControlEvents:UIControlEventTouchUpInside]; | ||
| [self.view addSubview:resetButton]; | ||
| self.resetButton = resetButton; | ||
| self.resetButton.hidden = YES; | ||
| } | ||
|
|
||
| - (void)didReceiveMemoryWarning { | ||
| [super didReceiveMemoryWarning]; | ||
| } | ||
|
|
||
| -(YLSwipeLockViewState)swipeView:(YLSwipeLockView *)swipeView didEndSwipeWithPassword:(NSString *)password | ||
| { | ||
| if (self.passwordString == nil) { | ||
| self.passwordString = password; | ||
| self.titleLabel.text = @"confirm your gesture password again"; | ||
| return YLSwipeLockViewStateNormal; | ||
| }else if ([self.passwordString isEqualToString:password]){ | ||
| self.titleLabel.text = @"set succeed"; | ||
| self.passwordString = nil; | ||
|
|
||
| NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; | ||
| [userDefault setObject:password forKey:@"gesturePassword"]; | ||
|
|
||
| [self performSelector:@selector(dismiss) withObject:nil afterDelay:1]; | ||
| return YLSwipeLockViewStateSelected; | ||
| }else{ | ||
| self.titleLabel.text = @"different from last time"; | ||
| self.resetButton.hidden = NO; | ||
| return YLSwipeLockViewStateWarning; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| -(UIStatusBarStyle)preferredStatusBarStyle | ||
| { | ||
| return UIStatusBarStyleLightContent; | ||
| } | ||
|
|
||
| -(void)dismiss{ | ||
| if (self.presentingViewController) { | ||
| [self dismissViewControllerAnimated:YES completion:nil]; | ||
| } | ||
| } | ||
|
|
||
| -(void)reset | ||
| { | ||
| self.passwordString = nil; | ||
| self.titleLabel.text = @"set your gesture password"; | ||
| self.resetButton.hidden = YES; | ||
| } | ||
|
|
||
| @end |
| @@ -0,0 +1,19 @@ | ||
| // | ||
| // YLSwipeLockNodeView.h | ||
| // YLSwipeLockViewDemo | ||
| // | ||
| // Created by 肖 玉龙 on 15/2/12. | ||
| // Copyright (c) 2015年 Yulong Xiao. All rights reserved. | ||
| // | ||
|
|
||
| #import <UIKit/UIKit.h> | ||
| typedef NS_ENUM(NSUInteger, YLSwipeLockNodeViewStatus) { | ||
| YLSwipeLockNodeViewStatusNormal, | ||
| YLSwipeLockNodeViewStatusSelected, | ||
| YLSwipeLockNodeViewStatusWarning | ||
| }; | ||
|
|
||
| @interface YLSwipeLockNodeView : UIView | ||
| @property (nonatomic) YLSwipeLockNodeViewStatus nodeViewStatus; | ||
|
|
||
| @end |
| @@ -0,0 +1,119 @@ | ||
| // | ||
| // YLSwipeLockNodeView.m | ||
| // YLSwipeLockViewDemo | ||
| // | ||
| // Created by 肖 玉龙 on 15/2/12. | ||
| // Copyright (c) 2015年 Yulong Xiao. All rights reserved. | ||
| // | ||
|
|
||
| #import "YLSwipeLockNodeView.h" | ||
| #import "YLSwipeLockView.h" | ||
| @interface YLSwipeLockNodeView() | ||
| @property (nonatomic, strong)CAShapeLayer *outlineLayer; | ||
| @property (nonatomic, strong)CAShapeLayer *innerCircleLayer; | ||
| @end | ||
|
|
||
|
|
||
| @implementation YLSwipeLockNodeView | ||
| -(id)initWithFrame:(CGRect)frame | ||
| { | ||
| self = [super initWithFrame:frame]; | ||
| if (self) { | ||
| [self.layer addSublayer:self.outlineLayer]; | ||
| [self.layer addSublayer:self.innerCircleLayer]; | ||
| self.nodeViewStatus = YLSwipeLockNodeViewStatusNormal; | ||
| } | ||
| return self; | ||
| } | ||
|
|
||
| -(void)pan:(UIPanGestureRecognizer *)rec | ||
| { | ||
| // NSLog(@"what the fuck"); | ||
| // CGPoint point = [rec locationInView:self]; | ||
| // NSLog(@"location in view:%f, %f", point.x, point.y); | ||
| self.nodeViewStatus = YLSwipeLockNodeViewStatusSelected; | ||
| } | ||
|
|
||
| -(void)setNodeViewStatus:(YLSwipeLockNodeViewStatus)nodeViewStatus | ||
| { | ||
| _nodeViewStatus = nodeViewStatus; | ||
| switch (_nodeViewStatus) { | ||
| case YLSwipeLockNodeViewStatusNormal: | ||
| [self setStatusToNormal]; | ||
| break; | ||
| case YLSwipeLockNodeViewStatusSelected: | ||
| [self setStatusToSelected]; | ||
| break; | ||
| case YLSwipeLockNodeViewStatusWarning: | ||
| [self setStatusToWarning]; | ||
| break; | ||
| default: | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| -(void)setStatusToNormal | ||
| { | ||
| self.outlineLayer.strokeColor = [UIColor whiteColor].CGColor; | ||
| self.innerCircleLayer.fillColor = [UIColor clearColor].CGColor; | ||
| } | ||
|
|
||
| -(void)setStatusToSelected | ||
| { | ||
| self.outlineLayer.strokeColor = LIGHTBLUE.CGColor; | ||
| self.innerCircleLayer.fillColor = LIGHTBLUE.CGColor; | ||
| } | ||
|
|
||
| -(void)setStatusToWarning | ||
| { | ||
| self.outlineLayer.strokeColor = [UIColor redColor].CGColor; | ||
| self.innerCircleLayer.fillColor = [UIColor redColor].CGColor; | ||
|
|
||
| } | ||
|
|
||
|
|
||
| -(void)layoutSubviews | ||
| { | ||
| self.outlineLayer.frame = self.bounds; | ||
| UIBezierPath *outlinePath = [UIBezierPath bezierPathWithOvalInRect:self.bounds]; | ||
| self.outlineLayer.path = outlinePath.CGPath; | ||
|
|
||
| CGRect frame = self.bounds; | ||
| CGFloat width = frame.size.width / 3; | ||
| self.innerCircleLayer.frame = CGRectMake(width, width, width, width); | ||
| UIBezierPath *innerPath = [UIBezierPath bezierPathWithOvalInRect:self.innerCircleLayer.bounds]; | ||
| self.innerCircleLayer.path = innerPath.CGPath; | ||
|
|
||
| } | ||
|
|
||
| -(CAShapeLayer *)outlineLayer | ||
| { | ||
| if (_outlineLayer == nil) { | ||
| _outlineLayer = [[CAShapeLayer alloc] init]; | ||
| _outlineLayer.strokeColor = LIGHTBLUE.CGColor; | ||
| _outlineLayer.lineWidth = 1.0f; | ||
| _outlineLayer.fillColor = [UIColor clearColor].CGColor; | ||
| } | ||
| return _outlineLayer; | ||
| } | ||
|
|
||
| -(CAShapeLayer *)innerCircleLayer | ||
| { | ||
| if (_innerCircleLayer == nil) { | ||
| _innerCircleLayer = [[CAShapeLayer alloc] init]; | ||
| _innerCircleLayer.strokeColor = [UIColor clearColor].CGColor; | ||
| _innerCircleLayer.lineWidth = 1.0f; | ||
| _innerCircleLayer.fillColor = LIGHTBLUE.CGColor; | ||
| } | ||
| return _innerCircleLayer; | ||
| } | ||
|
|
||
| /* | ||
| // Only override drawRect: if you perform custom drawing. | ||
| // An empty implementation adversely affects performance during animation. | ||
| - (void)drawRect:(CGRect)rect { | ||
| // Drawing code | ||
| } | ||
| */ | ||
|
|
||
| @end |
| @@ -0,0 +1,27 @@ | ||
| // | ||
| // YLSwipeLockView.h | ||
| // YLSwipeLockViewDemo | ||
| // | ||
| // Created by 肖 玉龙 on 15/2/12. | ||
| // Copyright (c) 2015年 Yulong Xiao. All rights reserved. | ||
| // | ||
|
|
||
| #import <UIKit/UIKit.h> | ||
| #define LIGHTBLUE [UIColor colorWithRed:0 green:170/255.0 blue:1 alpha:1] | ||
|
|
||
| typedef NS_ENUM(NSUInteger, YLSwipeLockViewState) { | ||
| YLSwipeLockViewStateNormal, | ||
| YLSwipeLockViewStateWarning, | ||
| YLSwipeLockViewStateSelected | ||
| }; | ||
| @protocol YLSwipeLockViewDelegate; | ||
|
|
||
| @interface YLSwipeLockView : UIView | ||
| @property (nonatomic, weak) id<YLSwipeLockViewDelegate> delegate; | ||
| @end | ||
|
|
||
|
|
||
| @protocol YLSwipeLockViewDelegate<NSObject> | ||
| @optional | ||
| -(YLSwipeLockViewState)swipeView:(YLSwipeLockView *)swipeView didEndSwipeWithPassword:(NSString *)password; | ||
| @end |