高性能iOS应用开发 笔记07

Timer循环引用

- (IBAction)onClickCloseVC:(id)sender
{
    [self dismissViewControllerAnimated:NO completion:nil];
}

- (IBAction)onClickBtn:(id)sender
{
    self.timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(updateFeed:) userInfo:nil repeats:YES];
}

- (void)updateFeed:(id)sender
{
    NSLog(@"updateFeed");
}

- (void)dealloc
{
    [self.timer invalidate];
    NSLog(@"Page4VC dealloc");
}

对象持有定时器
定时器持有对象
运行循环也持有定时器
因为循环引用 dealloc 永远不会被调用

改进1

- (IBAction)onClickCloseVC:(id)sender
{
    [self cleanUp];
    
    [self dismissViewControllerAnimated:NO completion:nil];
}

- (IBAction)onClickBtn:(id)sender
{
    self.timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(updateFeed:) userInfo:nil repeats:YES];
}

- (void)updateFeed:(id)sender
{
    NSLog(@"updateFeed");
}

- (void)dealloc
{
    NSLog(@"Page4VC dealloc");
}

//- (void)didMoveToParentViewController:(UIViewController *)parent
//{
//    if(parent == nil)
//    {
//        [self cleanUp];
//    }
//}

- (void)cleanUp
{
    [self.timer invalidate];
}

改进2

@interface Page4VC ()

@property (nonatomic, strong) FeedUpdateTask *updateTask;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.updateTask = [[FeedUpdateTask alloc] initWithTimeInterval:10 target:self selector:@selector(updateFeed:)];
}
- (IBAction)onClickCloseVC:(id)sender
{
    [self dismissViewControllerAnimated:NO completion:nil];
}

- (IBAction)onClickBtn:(id)sender
{
}

- (void)updateFeed:(id)sender
{
    NSLog(@"updateFeed");
    
    UIImage *image = (UIImage *)sender;
    
    self.imageView.image = image;
}

- (void)dealloc
{
    NSLog(@"Page4VC dealloc");
    
    [self.updateTask shutDown];
}

@interface FeedUpdateTask : NSObject

@property (nonatomic, weak) id target;
@property (nonatomic, assign) SEL selector;

- (instancetype)initWithTimeInterval:(NSTimeInterval)interval target:(id)target selector:(SEL)selector;

- (void)shutDown;

@end

@interface FeedUpdateTask ()

@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, strong) NSURLSessionTask *downloadTask;

@end


@implementation FeedUpdateTask

- (instancetype)initWithTimeInterval:(NSTimeInterval)interval target:(id)target selector:(SEL)selector
{
    self = [super init];
    
    if(self)
    {
        self.target = target;
        self.selector = selector;
        
        self.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(fetchAndUpdate:) userInfo:nil repeats:YES];
    }
    
    return self;
}

- (void)fetchAndUpdate:(NSTimer *)timer
{
    __weak typeof(self) weakSelf = self;
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        __strong typeof(weakSelf) sself = weakSelf;
        
        NSURL *imgURL = [[NSURL alloc] initWithString:@"http://macdown.uranusjr.com/static/images/logo-160.png"];
        
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:imgURL];
        
        NSURLSession *session = [NSURLSession sharedSession];
        
        sself.downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse *response, NSError *error) {
            UIImage *image = [[UIImage alloc] initWithData:data];
            dispatch_async(dispatch_get_main_queue(), ^{
                if(!sself)
                {
                    return;
                }
                
                if(sself.target == nil)
                {
                    return;
                }
                
                id target = sself.target;
                SEL selector = sself.selector;
                
                if([target respondsToSelector:selector])
                {
                    [target performSelector:selector withObject:image];
                }
            });
        }];
        
        [sself.downloadTask resume];
    });
}

- (void)shutDown
{
    [self.downloadTask cancel];
    
    [self.timer invalidate];
    self.timer = nil;
}

- (void)dealloc
{
    NSLog(@"FeedUpdateTask dealloc");
}

@end

改进3

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.updateTask = [[FeedUpdateTask alloc] initWithTimeInterval:10];
    self.updateTask.delegate = self;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (IBAction)onClickCloseVC:(id)sender
{
    [self dismissViewControllerAnimated:NO completion:nil];
}

- (IBAction)onClickBtn:(id)sender
{
    [self.updateTask start];
}

- (void)updateFeed:(id)sender
{
    NSLog(@"updateFeed");
    
    UIImage *image = (UIImage *)sender;
    
    self.imageView.image = image;
}

- (void)dealloc
{
    NSLog(@"Page4VC dealloc");
    
    if(self.updateTask != nil)
    {
        [self.updateTask shutDown];
    }
}
@protocol FeedUpdateTaskDelegate 

- (void)updateFeed:(id)sender;

@end

@interface FeedUpdateTask : NSObject

- (instancetype)initWithTimeInterval:(NSTimeInterval)interval;

@property (nonatomic, weak) id delegate;

- (void)start;
- (void)shutDown;

@end
- (void)start
{
    self.timer = [NSTimer scheduledTimerWithTimeInterval:self.interval target:self selector:@selector(fetchAndUpdate:) userInfo:nil repeats:YES];
}

- (void)fetchAndUpdate:(NSTimer *)timer
{
    __weak typeof(self) weakSelf = self;
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        __strong typeof(weakSelf) sself = weakSelf;
        
        NSURL *imgURL = [[NSURL alloc] initWithString:@"http://macdown.uranusjr.com/static/images/logo-160.png"];
        
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:imgURL];
        
        NSURLSession *session = [NSURLSession sharedSession];
        
        sself.downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse *response, NSError *error) {
            UIImage *image = [[UIImage alloc] initWithData:data];
            dispatch_async(dispatch_get_main_queue(), ^{
                if(!sself)
                {
                    return;
                }
                
                id delegate = sself.delegate;
                
                if(!delegate)
                {
                }
                else
                {
                    [delegate updateFeed:image];
                }
            });
        }];
        
        [sself.downloadTask resume];
    });
}

- (void)shutDown
{
    [self.downloadTask cancel];
    
    [self.timer invalidate];
    self.timer = nil;
    
    self.delegate = nil;
}

- (void)dealloc
{
    NSLog(@"FeedUpdateTask dealloc");
}

你可能感兴趣的:(高性能iOS应用开发 笔记07)