https://www.youtube.com/watch?v=9wS04HLsCzo&t=1143s
It answers quite a few questions bothering me. Great video!
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
Wednesday, September 14, 2016
closure in swift
Closure is nuts!
Try run this code, and you will know what I am talking about
Try run this code, and you will know what I am talking about
typealias IntegerFunction = Int -> ()func gamCounterSample() -> Int -> Void {func increment(i: Int){print("Integer passed in: \(i)")}return increment}func gameCounter() -> IntegerFunction {var counter = 0func increment(i : Int){counter += iprint("Counter value \(counter)")}return increment}let aCounter = gameCounter()aCounteraCounter(1)aCounter(1)
Friday, September 9, 2016
tap and move collectionView
I was super pumped when found out about "installsStandardGestureForInteractiveMovement"
CollectionView is alway my go to when it comes to UI designs. Coz it makes everything more visualized, and easy to build the connection between the content and the users.
To practice "installsStandardGestureForInteractiveMovement"
First, set up a basic collection.
Then set self.installsStandardGestureForInteractiveMovement = true
and
CollectionView is alway my go to when it comes to UI designs. Coz it makes everything more visualized, and easy to build the connection between the content and the users.
To practice "installsStandardGestureForInteractiveMovement"
First, set up a basic collection.
import UIKit
private let reuseIdentifier = "Cell"
class PhotoCC: UICollectionViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView!.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 20
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath)
cell.backgroundColor = UIColor.grayColor()
return cell
}
}
Then set self.installsStandardGestureForInteractiveMovement = true
and
override func collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
//code here
}
The CollectionView will be ready to go.
The whole project is available at https://github.com/lingzt/CollectionViewTapMovePra
The whole project is available at https://github.com/lingzt/CollectionViewTapMovePra
Thursday, September 8, 2016
partially reload tableview
Practice
1. reload section
2. reload row
I can totally see myself using these functions in the future. Sometimes we just do not need to reload the whole tableview.
https://github.com/lingzt/TVRefreshSectionPra
1. reload section
2. reload row
I can totally see myself using these functions in the future. Sometimes we just do not need to reload the whole tableview.
https://github.com/lingzt/TVRefreshSectionPra
Wednesday, September 7, 2016
copy and strong + swap function
basically
Copy: pass by value
Strong: pass by reference
more details: https://github.com/lingzt/CopyAndStrong
Swap function:
is to swap values of two.
The <T> in swap function means two value has to be of the same type. <T> does not mean any type specifically but only mean certain type in general.
Swap function:
is to swap values of two.
The <T> in swap function means two value has to be of the same type. <T> does not mean any type specifically but only mean certain type in general.
Thursday, September 1, 2016
AFNETWORKING CALL
Made a successful AFNETWORKING CALL today.
Pull a whole google task list to local via OBJC. Good progress!
https://github.com/lingzt/ToDoListPraOBJC
Pull a whole google task list to local via OBJC. Good progress!
https://github.com/lingzt/ToDoListPraOBJC
Sunday, August 28, 2016
Tuesday, August 23, 2016
study note: IOS之同步请求、异步请求、GET请求、POST请求
Apple is not longer supported " NSURLConnection sendSynchronousRequest "
1、同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作,
2、异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然可以对UI进行操作,程序可以继续运行
3、GET请求,将参数直接写在访问路径上。操作简单,不过容易被外界看到,安全性不高,地址最多255字节;
4、POST请求,将参数放到body里面。POST请求操作相对复杂,需要将参数和地址分开,不过安全性高,参数放在body里面,不易被捕获。
//第一步,创建URL |
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"]; |
|
//第二步,通过URL创建网络请求 |
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; |
//NSURLRequest初始化方法第一个参数:请求访问路径,第二个参数:缓存协议,第三个参数:网络请求超时时间(秒) |
其中缓存协议是个枚举类型包含: |
NSURLRequestUseProtocolCachePolicy(基础策略) |
NSURLRequestReloadIgnoringLocalCacheData(忽略本地缓存) |
NSURLRequestReturnCacheDataElseLoad(首先使用缓存,如果没有本地缓存,才从原地址下载) |
NSURLRequestReturnCacheDataDontLoad(使用本地缓存,从不下载,如果本地没有缓存,则请求失败,此策略多用于离线操作) |
NSURLRequestReloadIgnoringLocalAndRemoteCacheData(无视任何缓存策略,无论是本地的还是远程的,总是从原地址重新下载) |
NSURLRequestReloadRevalidatingCacheData(如果本地缓存是有效的则不下载,其他任何情况都从原地址重新下载) |
//第三步,连接服务器 |
NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; |
|
NSString *str = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding]; |
|
NSLog(@"%@",str); |
//该代码片段来自于: http://www.sharejs.com/codes/objectc/5873 |
//第一步,创建URL |
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do"]; |
//第二步,创建请求 |
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; |
[request setHTTPMethod:@"POST"];//设置请求方式为POST,默认为GET |
NSString *str = @"type=focus-c";//设置参数 |
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding]; |
[request setHTTPBody:data]; |
//第三步,连接服务器 |
|
NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; |
|
NSString *str1 = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding]; |
|
NSLog(@"%@",str1); |
//该代码片段来自于: http://www.sharejs.com/codes/objectc/5873 |
//第一步,创建url |
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"]; |
//第二步,创建请求 |
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; |
//第三步,连接服务器 |
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self]; |
//该代码片段来自于: http://www.sharejs.com/codes/objectc/5873 |
//第一步,创建url |
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do"]; |
//第二步,创建请求 |
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; |
[request setHTTPMethod:@"POST"]; |
NSString *str = @"type=focus-c"; |
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding]; |
[request setHTTPBody:data]; |
//第三步,连接服务器 |
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self]; |
//该代码片段来自于: http://www.sharejs.com/codes/objectc/5873 |
//接收到服务器回应的时候调用此方法 |
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response |
{ |
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response; |
NSLog(@"%@",[res allHeaderFields]); |
self.receiveData = [NSMutableData data]; |
|
} |
//接收到服务器传输数据的时候调用,此方法根据数据大小执行若干次 |
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data |
{ |
[self.receiveData appendData:data]; |
} |
//数据传完之后调用此方法 |
-(void)connectionDidFinishLoading:(NSURLConnection *)connection |
{ |
NSString *receiveStr = [[NSString alloc]initWithData:self.receiveData encoding:NSUTF8StringEncoding]; |
NSLog(@"%@",receiveStr); |
} |
//网络请求过程中,出现任何错误(断网,连接超时等)会进入此方法 |
-(void)connection:(NSURLConnection *)connection |
didFailWithError:(NSError *)error |
{ |
NSLog(@"%@",[error localizedDescription]); |
} |
//该代码片段来自于: http://www.sharejs.com/codes/objectc/5873 |
Subscribe to:
Posts (Atom)

