Local notification won't stop sending until I opened the app - c

my app won't stop sending the notification I set for a specific time until I opened the app. It will send me like every 2 minutes or so to kind of remind me...
(void)applicationDidEnterBackground:(UIApplication *)application {
NSCalendar *calendar3 = [NSCalendar currentCalendar];
NSDateComponents *components3 = [calendar3 components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:[NSDate date]];
[components3 setHour:21];
[components3 setMinute:30];
UIApplication *app3 = [UIApplication sharedApplication];
UILocalNotification *notifyAlarm3 = [[UILocalNotification alloc] init];
if (notifyAlarm3) {
notifyAlarm3.fireDate = [calendar3 dateFromComponents:components3];
notifyAlarm3.timeZone = [NSTimeZone defaultTimeZone];
notifyAlarm3.repeatInterval = NSDayCalendarUnit;
notifyAlarm3.soundName = #"not.wav";
notifyAlarm3.alertBody = #"Hello";
[app3 scheduleLocalNotification:notifyAlarm3];
}
}
(void)applicationWillEnterForeground:(UIApplication *)application {
UIApplication *app = [UIApplication sharedApplication];
NSArray *oldNotifications = [app scheduledLocalNotifications];
if ([oldNotifications count] > 0) {
[app cancelAllLocalNotifications];
}
}
Looking forward to response!

Related

Timer with Target Day to show Alert

I have an app written here is set a fixed reference Day,after this day i want to get an Alert !
with this code I set the date and time : here Day 3 (Thuesday) and hour 11.
this works great! with an Timer in viewDidload my navigationItem.title shows Day/Hour/Minutes to the target day...
now i will set a Timer to this Day/Time, when i open my app after Thuesday (Wednesday or Thursday) the timer is 0 and the Alert shows!
with :
NSString *currentTimestamp = [NSString stringWithFormat:#"%.f", [resetTime timeIntervalSince1970]];
_epochTimeer.text = currentTimestamp;
i convert the Target time to epoch Time for my timer!
- (void) resetTimer:(id)sender {
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setLocale:[NSLocale currentLocale]];
NSDateComponents *nowComponents = [gregorian components:NSYearCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:today];
[nowComponents setWeekday:3]; //2 = Monday 3 di 4 = mi 5 = do 6 = fr 7 = sa
[nowComponents setWeek: [nowComponents week]+ 1 ]; //Next week [nowComponents week] + 1]
[nowComponents setHour:11]; //8a.m.
[nowComponents setMinute:0];
[nowComponents setSecond:0];
NSDate *resetTime = [gregorian dateFromComponents:nowComponents];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"dd-MM-YYYY HH:mm:ss"];
NSDate *date1 = today;
NSDate *date2 = resetTime;
NSTimeInterval interval = [date2 timeIntervalSinceDate:date1];
int days = (int)interval / 86400;
int hours = (interval / 3600)- (days * 24);
int minutes = ((interval / 60) - (days * 24 * 60) -(hours * 60));
int sekunden = (days * 86400) + (hours * 3600) +(minutes * 60);
NSString *timeDiff = [NSString stringWithFormat:#"%02d Tage : %02d Std : %02d Min",days, hours, minutes];
self.navigationItem.title = [NSString stringWithFormat:#"%#",timeDiff];
NSString *currentTimestamp = [NSString stringWithFormat:#"%.f", [resetTime timeIntervalSince1970]];
_epochTimeer.text = currentTimestamp;
NSLog(#"timer: %#",timeDiff);
NSLog(#"timer: %#",currentTimestamp);
}
how can I set my timer with this epoch time or the target Day/time?
i am a beginner with timer and NSDate and I do not understand how I can write the code!
or is there a completely different solution to get my Alert after the Target day when i open my APP!
Thanks Jürgen
Sorry for my bad English ..:-)
Thanks for Helping, i Add your Code and Set the localNotification.fireDate to resetTime:
- (void) resetTimer:(id)sender {
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setLocale:[NSLocale currentLocale]];
NSDateComponents *nowComponents = [gregorian components:NSYearCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:today];
[nowComponents setWeekday:7]; //2 = Monday 3 di 4 = mi 5 = do 6 = fr 7 = sa
[nowComponents setWeek: [nowComponents week]]; //Next week [nowComponents week] + 1]
[nowComponents setHour:9]; //8a.m.
[nowComponents setMinute:25];
[nowComponents setSecond:0];
NSDate *resetTime = [gregorian dateFromComponents:nowComponents];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"dd-MM-YYYY HH:mm:ss"];
NSDate *date1 = today;
NSDate *date2 = resetTime;
NSTimeInterval interval = [date2 timeIntervalSinceDate:date1];
int days = (int)interval / 86400;
int hours = (interval / 3600)- (days * 24);
int minutes = ((interval / 60) - (days * 24 * 60) -(hours * 60));
int sekunden = (days * 86400) + (hours * 3600) +(minutes * 60);
NSString *timeDiff = [NSString stringWithFormat:#"%02d Tage : %02d Std : %02d Min",days, hours, minutes];
_showTimer.text = [NSString stringWithFormat:#"%02d",sekunden];
self.navigationItem.title = [NSString stringWithFormat:#"%#",timeDiff];
NSString *currentTimestamp = [NSString stringWithFormat:#"%.f", [resetTime timeIntervalSince1970]];
destinationDate = [NSDate dateWithTimeIntervalSince1970:1425981600];
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate =resetTime;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
NSLog(#"timer: %#",timeDiff);
NSLog(#"timer: %#",currentTimestamp);
}
and this for my Alert :
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
// code to display an alert here
SCLAlertView *alert = [[SCLAlertView alloc] init];
alert.backgroundType = Blur;
UIColor *color = [UIColor colorWithRed:52/255.0 green:222/255.0 blue:192/255.0 alpha:255/255.0];
[alert showCustom:self image:[UIImage imageNamed:#"geist"] color:color title:NSLocalizedString(#"Auto Reset", nil) subTitle:NSLocalizedString(#"Automatischer Reset Aktiviert!", nil) closeButtonTitle:#"OK" duration:0.0f];
}
when the time has expired and i start my App ... the Alert is not and it does not happen..
I need to do is activate the Notification somewhere?
thanks
Ok i have added your code now in the AppDelegate.m
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIAlertView* alert= [[UIAlertView alloc]initWithTitle:#"My App"
message:#"Reset"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}}
now it works, when i start my app the Alert shows, but it Loop Blinking and i can't Klick OK!
what is this now...?
This can be done by using NSLocalNotification
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate =<target date>;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
// code to display an alert here
}

UItextView dynamiclly Height and Link reconizer iOS 6 vs ios 7

I develop an application and I need to display the content using an UITextView which must have set the height dynamically and it must recognize a link.
I used code above:
self.textView.text = [NSString stringWithFormat:#"%# \n %#", self.offersObjects.body, self.offersObjects.url];
self.textView.dataDetectorTypes = UIDataDetectorTypeLink;
if (([[[UIDevice currentDevice] systemVersion] integerValue] < 7)){
CGRect frame = self.textView.frame;
frame.size.height = self.textView.contentSize.height;contentSize.height;
self.textView.frame = frame;
}else{
[self.textView sizeToFit];
[self.textView layoutIfNeeded];
}
My problem is that it doesn't recognize the link .
try with below code :
-(IBAction)txtStustes:(id)sender
{
NSError *error = nil;
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink
| NSTextCheckingTypePhoneNumber error:&error];
NSString *string = self.textView.text;
NSArray *matches = [detector matchesInString:string options:0 range:NSMakeRange(0, [string length])];
for (NSTextCheckingResult *match in matches) {
if ([match resultType] == NSTextCheckingTypeLink) {
NSURL *url = [match URL];
[[UIApplication sharedApplication] openURL:url];
}
}
}
Also add below code in your viewDidLoad method
UITapGestureRecognizer *LblProfileNameTouch=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(txtStustes:)];
[LblProfileNameTouch setNumberOfTouchesRequired:1];
[self.textView addGestureRecognizer:LblProfileNameTouch];

Save NSMutableDictionary in iOS Keychain using iOS 6+

I am trying to save NSMutableDictionary in iOS keychain using KeychainItemWrapper classes. But I am not able to save it. I am getting error
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Couldn't add the Keychain Item.'
Here is my data to be saved
{
country = USA;
id = 3;
name = "Test User";
photo = "http://www.mydomain.com/images/user1.jpg";
result = true;
"country" = 1;
}
Here is my code
// Call to save
[self storeLoggedInUserInfoInKeychainWithDictionary:dict];
-(void)storeLoggedInUserInfoInKeychainWithDictionary:(NSMutableDictionary*)dict
{
// Save Login Credentials
KeychainItemWrapper* loginUserkeychain = [[KeychainItemWrapper alloc] initWithIdentifier:LOGIN_USER_SERVICE accessGroup:nil];
NSString *error;
[loginUserkeychain setObject:(__bridge id)(kSecAttrAccessibleWhenUnlocked) forKey:(__bridge id)(kSecAttrAccessible)];
NSData *dictionaryRep = [NSPropertyListSerialization dataFromPropertyList:dict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
[loginUserkeychain setObject:dictionaryRep forKey:(__bridge id)(kSecValueData)];
}
-(NSMutableDictionary*)fetchLoggedInUserInfoFromKeychain
{
KeychainItemWrapper* loginUserkeychain = [[KeychainItemWrapper alloc] initWithIdentifier:LOGIN_USER_SERVICE accessGroup:nil];
NSString *error;
//When the NSData object object is retrieved from the Keychain, you convert it back to NSDictionary type
NSData *dictionaryRep = [loginUserkeychain objectForKey:(__bridge id)(kSecValueData)];
NSDictionary *dictionary = [NSPropertyListSerialization propertyListFromData:dictionaryRep mutabilityOption:NSPropertyListImmutable format:nil errorDescription:&error];
if (error) {
NSLog(#"%#", error);
}
return [NSMutableDictionary dictionaryWithDictionary:dictionary];
}
-(void)resetLoggedInUserInfoFromKeychain
{
KeychainItemWrapper* loginUserkeychain = [[KeychainItemWrapper alloc] initWithIdentifier:LOGIN_USER_SERVICE accessGroup:nil];
[loginUserkeychain resetKeychainItem];
}
Can anybody tell me whats wrong in above code ?
Thanks in advance.
After few attempts & research using below code I am able to save the data in keychain. If any one is interested can have a look at below code
-(void)storeLoggedInUserInfoInKeychainWithDictionary:(NSMutableDictionary*)dict
{
// Create encoded data
NSData *encodedData= [NSKeyedArchiver archivedDataWithRootObject:dict];
// Create encoded string from data
NSString *encodedString= [encodedData base64EncodedString];
// Save Login Credentials
KeychainItemWrapper* tranxkeychain = [[KeychainItemWrapper alloc] initWithIdentifier:LOGIN_USER_KEYCHAIN accessGroup:nil];
[tranxkeychain setObject:(__bridge id)(kSecAttrAccessibleWhenUnlocked) forKey:(__bridge id)(kSecAttrAccessible)];
[tranxkeychain setObject:LOGIN_USER_SERVICE forKey: (__bridge id)kSecAttrService];
[tranxkeychain setObject:LOGIN_USER_INFO forKey:(__bridge id)(kSecAttrAccount)];
[tranxkeychain setObject:encodedString forKey:(__bridge id)(kSecValueData)];
}
-(NSDictionary*)fetchLoggedInUserInfoFromKeychain
{
KeychainItemWrapper* tranxkeychain = [[KeychainItemWrapper alloc] initWithIdentifier:LOGIN_USER_KEYCHAIN accessGroup:nil];
[tranxkeychain setObject:(__bridge id)(kSecAttrAccessibleWhenUnlocked) forKey:(__bridge id)(kSecAttrAccessible)];
[tranxkeychain setObject:LOGIN_USER_SERVICE forKey: (__bridge id)kSecAttrService];
// Get decoded string
NSString *decodedString=[tranxkeychain objectForKey:(__bridge id)(kSecValueData)];
// Get decoded data
NSData *decodedData= [NSData dataFromBase64String:decodedString];
NSDictionary *dict =[NSKeyedUnarchiver unarchiveObjectWithData:decodedData];
return dict;
}
-(void)resetLoggedInUserInfoFromKeychain
{
KeychainItemWrapper* tranxkeychain = [[KeychainItemWrapper alloc] initWithIdentifier:LOGIN_USER_KEYCHAIN accessGroup:nil];
[tranxkeychain resetKeychainItem];
}

When and how is collectionView:viewForSupplementaryElementOfKind:atIndexPath: called?

I'm trying to implement a native-Calendar-app-like timeline view with UICollectionView and custom layout. And I'm new to it.
Here is where my problem come from.
I'm using Decoration View to implement those background gridlines, and trying to use Supplementary View to make the time labels (near the gridlines), and will use Cell to make the events but not that far yet.
But before doing the events, I found when I run it all the supplementary views are not working, no matter if I have cell or not. And I found my collectionView:viewForSupplementaryElementOfKind:atIndexPath: method is not called.
So I'm wondering how and when this method is called? What could be leading to my situation that it's not called?
Actually, is it good to make those time labels with supplementary view? I'm not sure about it since I do need them to be visible even when there's no event (no cell/item in section).
Here is my code:
View Controller
- (void)viewDidLoad
{
[super viewDidLoad];
self.collectionView.backgroundColor = [UIColor whiteColor];
[self.collectionView registerClass:TodayCellKindTask.class forCellWithReuseIdentifier:CellKindTaskIdentifier];
[self.collectionView registerClass:TodayTimelineTimeHeader.class forSupplementaryViewOfKind:TimelineKindTimeHeader withReuseIdentifier:TimelineTimeHeaderIdentifier];
[self.timelineViewLayout registerClass:TodayTimelineTileWhole.class forDecorationViewOfKind:TimelineKindTileWholeHour];
[self.timelineViewLayout registerClass:TodayTimelineTileHalf.class forDecorationViewOfKind:TimelineKindTileHalfHour];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 5;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
TodayCellKindTask *cellTask = [collectionView dequeueReusableCellWithReuseIdentifier:CellKindTaskIdentifier forIndexPath:indexPath];
return cellTask;
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
NSLog(#"viewForSupplementaryElementOfKind");
TodayTimelineTimeHeader *timeHeader = [self.collectionView dequeueReusableSupplementaryViewOfKind:TimelineKindTimeHeader withReuseIdentifier:TimelineTimeHeaderIdentifier forIndexPath:indexPath];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *today = [NSDate date];
NSDateComponents *comps = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:today];
[comps setHour:indexPath.item];
timeHeader.time = [calendar dateFromComponents:comps];
return timeHeader;
}
Custom Layout
// in prepareLayout
NSMutableDictionary *timeHeaderAttributes = [NSMutableDictionary dictionary];
CGSize headerSize = [TodayTimelineTimeHeader defaultSize];
CGFloat headerOffsetY = (tileSize.height - headerSize.height) / 2;
for (NSInteger hour = 24; hour >= 0; hour--) {
NSIndexPath *timeHeaderIndexPath = [NSIndexPath indexPathForItem:hour inSection:0];
UICollectionViewLayoutAttributes *currentTimeHeaderAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:TimelineKindTimeHeader withIndexPath:timeHeaderIndexPath];
CGFloat headerPosY = hour * 2 * tileSize.height + headerOffsetY;
currentTimeHeaderAttributes.frame = CGRectMake(TimeHeaderPosX, headerPosY, headerSize.width, headerSize.height);
timeHeaderAttributes[timeHeaderIndexPath] = currentTimeHeaderAttributes;
}
self.timelineTileAttributes[TimelineKindTimeHeader] = timeHeaderAttributes;
// layoutAttributesForSupplementaryViewOfKind
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
return self.timelineTileAttributes[kind][indexPath];
}
// layoutAttributesForElementsInRect
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:self.timelineTileAttributes.count];
[self.timelineTileAttributes enumerateKeysAndObjectsUsingBlock:^(NSString *elementIdentifier,
NSDictionary *elementsInfo,
BOOL *stop) {
[elementsInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath,
UICollectionViewLayoutAttributes *attributes,
BOOL *stop) {
if (CGRectIntersectsRect(rect, attributes.frame)) {
[allAttributes addObject:attributes];
}
}];
}];
return allAttributes;
}
// collectionViewContentSize
- (CGSize)collectionViewContentSize {
CGSize tileSize = [TodayTimelineTileWhole defaultSize];
CGFloat contentHeight = tileSize.height * self.numberOfTiles;
return CGSizeMake(tileSize.width, contentHeight);
}
I tried not to post all the code here since that'd be a lot, but let me know if you need to know others.
Any tip is appreciated!
Pine
So, this problem is solved, and the reason was my stupid mistake, setting those views' position x out of the screen, and due to that the method was not called. Nothing else.
I found this reason by logging out each view's frame in prepareLayout, and found the x position was wrong. I got this position from the retina design so…
I used supplementary view and it was working without any problem.
My lesson: no worries, calm down. This can save you time from making mistake.

How to add some more marks on date tiles after loading calendar in tapku?

I am using TAPKU calendar in my iOS application. I want to add some more marks on date tile after loading complete data in tapku calendar.
I am getting some additional data from async process and I want to mark that data also on calendar.
How can i do this. Thanks in advance.
This is indeed possible, as an example for the day calendar view, modify _refreshDataPageWithAtIndex to be like this:
- (void) _refreshDataWithPageAtIndex:(NSInteger)index{
UIScrollView *sv = self.pages[index];
TKTimelineView *timeline = [self _timelineAtIndex:index];
CGRect r = CGRectInset(self.horizontalScrollView.bounds, HORIZONTAL_PAD, 0);
r.origin.x = self.horizontalScrollView.frame.size.width * index + HORIZONTAL_PAD;
sv.frame = r;
timeline.startY = VERTICAL_INSET;
for (UIView* view in sv.subviews) {
if ([view isKindOfClass:[TKCalendarDayEventView class]]){
[self.eventGraveYard addObject:view];
[view removeFromSuperview];
}
}
if(self.nowLineView.superview == sv) [self.nowLineView removeFromSuperview];
if([timeline.date isTodayWithTimeZone:self.timeZone]){
NSDate *date = [NSDate date];
NSDateComponents *comp = [date dateComponentsWithTimeZone:self.timeZone];
NSInteger hourStart = comp.hour;
CGFloat hourStartPosition = hourStart * VERTICAL_DIFF + VERTICAL_INSET;
NSInteger minuteStart = round(comp.minute / 5.0) * 5;
CGFloat minuteStartPosition = roundf((CGFloat)minuteStart / 60.0f * VERTICAL_DIFF);
CGRect eventFrame = CGRectMake(self.nowLineView.frame.origin.x, hourStartPosition + minuteStartPosition - 5, NOB_SIZE + self.frame.size.width - LEFT_INSET, NOB_SIZE);
self.nowLineView.frame = eventFrame;
[sv addSubview:self.nowLineView];
}
if(!self.dataSource) return;
timeline.events = [NSMutableArray new];
[self.dataSource calendarDayTimelineView:self eventsForDate:timeline.date andEvents:timeline.events success:^{
[timeline.events sortUsingComparator:^NSComparisonResult(TKCalendarDayEventView *obj1, TKCalendarDayEventView *obj2){
return [obj1.startDate compare:obj2.startDate];
}];
[self _realignEventsAtIndex:index];
if(self.nowLineView.superview == sv)
[sv bringSubviewToFront:self.nowLineView];
}];
}
and then change your eventsForDate function to look like this:
- (void) calendarDayTimelineView:(TKCalendarDayView*)calendarDayTimeline eventsForDate:(NSDate *)eventDate andEvents:(NSMutableArray *)events success:(void (^)())success {
[Model doSomethingAsync andSuccess:^(NSArray *classes) {
// .. Add stuff to events..
success();
}];
}
I'm assuming the pattern for the other controls is very similar. The premise is you're waiting to continue the formatting/layout flow til you get your data.

Resources