https://www.youtube.com/watch?v=9wS04HLsCzo&t=1143s
It answers quite a few questions bothering me. Great video!
Ling's IOS Adventure
Monday, May 29, 2017
Tuesday, February 21, 2017
在程序被送入后台时,向 iOS 借点时间,来完成一个长期任务
was fixing a 0x000000008badf00d "crash" and found this to read.
转载自 http://www.cnblogs.com/lyanet/archive/2013/03/26/2983079.html by _安静ゝ
转载自 http://www.cnblogs.com/lyanet/archive/2013/03/26/2983079.html by _安静ゝ
12.2.2. 方案
使用UIApplication的beginBackgroundTaskWithExpirationHandler: 实例方法。在你完成任务后,调用UIApplication的endBackgroundTask:方法。
12.2.3. 讨论
当一个iOS应用被送到后台,它的主线程会被暂停。你用NSThread的detachNewThreadSelector:toTar get:withObject:类方法创建的线程也被挂起了。如果你想在后台完成一个长期任务,就必须调用UIApplication的beginBackgroundTaskWithExpirationHandler:实例方法,来向iOS借点时间。UIApplication的backgroundTimeRemaining属性包含了程序完成他的任务可以使用的秒数。如果在这个期限内,长期任务没有被完成,iOS将终止程序。每个对beginBackgroundTaskWithExpirationHandler:方法的调用,必须要相应的调用endBackgroundTask:方法(UIApplication的另一个实例方法)。也就是说,如果你向iOS要更多时间来完成一个任务,你必须告诉iOS你什么时候能完成那个任务,那时,你的程序将iOS 5 Programming Cookbook www.devdiv.com 翻译整理
DevDiv 翻译:kyelup cloudhsu 耐心摩卡 wangli2003j3 xiebaochun dymx101 jimmylianf BeyondVincent 20 DevDiv 校对:laigb kyelup DevDiv 编辑:BeyondVincent 版本 1.0 | 2012 年 07 月 30 日
和其所有被暂停的线程被放入后台。
当你的程序在前台时,UIApplication的backgroundTimeRemaining属性等于DBL_MAX常量,这是double类型可表示的最大值(和这个值相当的integer通常等于-1)。在iOS被要求在程序被完全挂起之前给于更多的执行时间,这个属性指明了在完成任务前程序拥有多少秒。
在程序中你可以多次调用beginBackgroundTaskWithExpirationHandler:方法。要记住的重点是,当iOS为你的程序返回一个token或者任务标识(task identifier)时,你都必须调用endBackgroundTask:方法,在运行的任务结束时,用来标志任务结束。如果你不这么做的话,iOS会终止你的程序。
在后台时,程序不应该执行完全的功能,也不应该处理大量数据。事实上,他们只应该完成一个长期任务。
比如,一个程序正在调用一个web service API,并且还没有从服务器上的那个API接收到响应。在此期间,如果程序被送入后台,它可以请求更多的时间,直到它从服务器收到响应。一旦响应被接收,程序必须保存其状态,并调用UIApplication的endBackgroundTask:实例方法将任务标记为完成。
让我们看一个例子。我将从在应用程序委托中定义一个UIBackgroundTaskIdentifier类型的属性开始。同时,让我们定义一个NSTimer,当程序被送到后台时,我们将用它每隔1秒向控制台窗口输出一条消息:
#import <UIKit/UIKit.h>
@interface Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, unsafe_unretained) UIBackgroundTaskIdentifier backgroundTaskIdentifier;
@property (nonatomic, strong) NSTimer *myTimer;
@end
接下来我们继续同步属性:
#import "Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate.h" @implementation Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate
@synthesize window = _window;
@synthesize backgroundTaskIdentifier; @synthesize myTimer;
现在,让我们创建定时器,并在程序被送到后台时启动它:
- (BOOL) isMultitaskingSupported{
BOOL result = NO;
if ([[UIDevice currentDevice]
respondsToSelector:@selector(isMultitaskingSupported)]){ result = [[UIDevice currentDevice] isMultitaskingSupported];
}
return result;
}
- (void) timerMethod:(NSTimer *)paramSender{
NSTimeInterval backgroundTimeRemaining =
[[UIApplication sharedApplication] backgroundTimeRemaining];
if (backgroundTimeRemaining == DBL_MAX){ NSLog(@"Background Time Remaining = Undetermined");
} else { iOS 5 Programming Cookbook www.devdiv.com 翻译整理
DevDiv 翻译:kyelup cloudhsu 耐心摩卡 wangli2003j3 xiebaochun dymx101 jimmylianf BeyondVincent 21 DevDiv 校对:laigb kyelup DevDiv 编辑:BeyondVincent 版本 1.0 | 2012 年 07 月 30 日
NSLog(@"Background Time Remaining = %.02f Seconds",
backgroundTimeRemaining);
} }
- (void)applicationDidEnterBackground:(UIApplication *)application{
if ([self isMultitaskingSupported] == NO){
return; }
self.myTimer =
[NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:@selector(timerMethod:) userInfo:nil
repeats:YES];
self.backgroundTaskIdentifier =
[application beginBackgroundTaskWithExpirationHandler:^(void) { [self endBackgroundTask];
}]; }
你可以看到,在后台任务的完成处理者(completion handler)中,我们调用了应用程序委托的endBackgroundTask方法。这是一个我们编写的方法,如下:
- (void) endBackgroundTask{
dispatch_queue_t mainQueue = dispatch_get_main_queue();
__weak Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate *weakSelf = self;
dispatch_async(mainQueue, ^(void) {
Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate *strongSelf = weakSelf;
if (strongSelf != nil){
[strongSelf.myTimer invalidate];
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
strongSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid; }
}); }
在长期任务结束后,我们需要做一些事情进行清理:
1. 结束所有的线程和定时器,不管他们是基础定时器还是GCD中创建的。
2.调用UIApplication的endBackgroundTask:方法来结束后台任务。
3.将任务标识设置为UIBackgroundTaskInvalid,标志我们的任务结束。
最后,当我们的应用回到前台,如果我们的后台任务还在执行中,我们需要确保我们在干掉它:
- (void)applicationWillEnterForeground:(UIApplication *)application{
if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid){
[self endBackgroundTask]; }
}
在我们的例子中,不论何时程序被送到后台,我们都会要求更多时间以完成一个长期任务(例如,在这里是我们计时器的代码)。在我们的时间里,我们不断的读取UIApplication实例中backgroundTimeRemaining属性的值,将它打印到控制台。在UIApplication的beginBackgroundTask WithExpirationHandler: 实例方法中,在程序的额外时间内完成一个长期任务之前,我们提供的代码将被执行(一版大概在任务过期前5到10秒)。在此,我们只要调用UIApplication的endBackgroundTask:实例方法来结束任务。
Wednesday, November 9, 2016
How to use barrier
Example:
https://github.com/lingzt/BarrierPra
By using the barrier, I can make sure every time getter starting after the previous setter finished.
https://github.com/lingzt/BarrierPra
By using the barrier, I can make sure every time getter starting after the previous setter finished.
#import "ViewController.h" NSString *_name; @interface ViewController () @property (nonatomic, strong, readwrite) NSString *name;@property (nonnull, strong, nonatomic) dispatch_queue_t syncQueue;@end @implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; //并行队列 set up on global queue _syncQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); for(int i=0; i<1000; i++){ NSString *tempName = [NSString stringWithFormat:@"%d",i]; [self name]; [self setName:tempName]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.} //用同步 sync with global queue- (NSString *)name{ __block NSString *localName; dispatch_sync(_syncQueue, ^{ localName =_name; NSLog(@"getter"); NSLog(localName); }); return localName;} //利用异步栅栏块 async with global que, with barrier- (void)setName:(NSString *)name{ dispatch_barrier_async(_syncQueue, ^{ _name = name; NSLog(@"settter"); NSLog(_name); });} @end
Monday, November 7, 2016
difference bw category & extension
Category:
1. The category .h file is optional. When it is deleted the .m file have to import the main .h file
2. To expose the method, it has to be declared in the .h file.
3. Can't declare any new property in the category.
Extension:
1. Kinda like category, but anonymous, what is even better, it can declare the new property!
2. Can be used to expose read-only properties.
for example:
in main .m file, declare the internal method
then implement the method
in other class's .m file, set extension interface to expose the method to the current class.
later in this class, we will be able to call the private method.
1. The category .h file is optional. When it is deleted the .m file have to import the main .h file
2. To expose the method, it has to be declared in the .h file.
3. Can't declare any new property in the category.
Extension:
1. Kinda like category, but anonymous, what is even better, it can declare the new property!
2. Can be used to expose read-only properties.
for example:
in main .m file, declare the internal method
@interface Account () @property (nonatomic, readonly) NSString* randomStuff; + (void)setCurrentAccount:(Account*)account;
then implement the method
+ (void)setCurrentAccount:(Account*)account { currentAccount = account;}
in other class's .m file, set extension interface to expose the method to the current class.
@interface Account () + (void)setCurrentAccount:(Account*)account;@end
later in this class, we will be able to call the private method.
- (void)cleanCurrentUser{ [Account setCurrentAccount:nil]; }
Sunday, November 6, 2016
ReactiveCocoa
I have found some senior people heavily using ReactiveCocoa in the project I am currently working on. So, knowing ReactiveCocoa https://github.com/ReactiveCocoa/ReactiveCocoa is my homework of this Sunday.
Study note:
It is 1:30am and I really got to go to bed. That way I will have enough energy for pairing with others tomorrow.
It was not as productive as I expected, so so far I found RAC has something to do with MVVM, which is super cool.
More reading to come: https://www.objc.io/issues/13-architecture/mvvm/
Following are some material I am following today:
Study note:
It is 1:30am and I really got to go to bed. That way I will have enough energy for pairing with others tomorrow.
It was not as productive as I expected, so so far I found RAC has something to do with MVVM, which is super cool.
More reading to come: https://www.objc.io/issues/13-architecture/mvvm/
Monday, September 26, 2016
UIPageViewController
https://spin.atomicobject.com/2015/12/23/swift-uipageviewcontroller-tutorial/
Found a very good tutorial online for UIPageViewController.
Practice project please see following
https://github.com/lingzt/UIPageViewControllerPra/commits/master
Found a very good tutorial online for UIPageViewController.
Practice project please see following
https://github.com/lingzt/UIPageViewControllerPra/commits/master
Subscribe to:
Posts (Atom)