How to stop or cancel sending block execution

I want to execute several sending blocks at once. Therefore, when any sending block is executed at the same time as I start the second sending block, I want to stop the execution of the previous sending block.

I am using this code below:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [NSData dataWithContentsOfURL:item.URL];
        dispatch_async(dispatch_get_main_queue(), ^(void){
         NSError *error = nil;
         self.player =[[AVAudioPlayer alloc] initWithData:data fileTypeHint:AVFileTypeMPEGLayer3 error:&error];
            NSLog(@"%@",error);
        });
    });

And I also tried this code below. but if I used this code below, you can undo the previous block, but my application will hang

//Use NSOperationQueue 
    myQueue = [NSOperationQueue mainQueue];
    [myQueue addOperationWithBlock:^{

        // Background work
        NSData *data = [NSData dataWithContentsOfURL:item.URL];
       [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            // Main thread work (UI usually)
            NSError *error = nil;
           self.player =[[AVAudioPlayer alloc] initWithData:data fileTypeHint:AVFileTypeMPEGLayer3 error:&error];
            NSLog(@"%@",error);
        }];
    }];

Thanks in advance,

+4
source share
1 answer

This does not require sending queues or operation queues.

NSURLSession, , AVAudioPlayer. , cancel, stop .

:

@class Song;

@protocol SongDelegate <NSObject>

- (void)song:(Song *)song didFinishPlayingSuccessfully:(BOOL)flag;
- (void)song:(Song *)song didFinishDownloadWithError:(NSError *)error;

@end

@interface Song: NSObject <AVAudioPlayerDelegate>
@property (nonatomic, strong) NSURL *url;
@property (nonatomic, weak)   NSURLSessionTask *downloadTask;
@property (nonatomic, strong) NSURL *localURL;
@property (nonatomic, strong) AVAudioPlayer *player;
@property (nonatomic, weak)   id<SongDelegate> delegate;
@end

@implementation Song

+ (instancetype)songWithURL:(NSURL *)url delegate:(id<SongDelegate>)delegate {
    Song *song = [[Song alloc] init];
    song.url = url;
    song.delegate = delegate;
    return song;
}

- (void)downloadAndPlay {
    self.downloadTask = [[NSURLSession sharedSession] downloadTaskWithURL:self.url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.delegate song:self didFinishDownloadWithError:error];
        });
        NSURL *documentsURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:false error:&error];
        NSAssert(documentsURL, @"URLForDirectory failed: %@", error);
        NSURL *fileURL = [documentsURL URLByAppendingPathComponent:self.url.lastPathComponent];
        NSError *moveError;
        BOOL success = [[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:&moveError];
        NSAssert(success, moveError.localizedDescription);

        // note, the only reason we dispatch the following is that this completion handler runs on background queue and we want to update properties and start the player from the main queue

        dispatch_async(dispatch_get_main_queue(), ^{
            self.localURL = fileURL;
            NSError *playError;
            self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&playError];
            self.player.delegate = self;
            [self.player play];
            NSAssert(playError == nil, playError.localizedDescription);
        });
    }];
    [self.downloadTask resume];
}

- (void)cancel {
    [self.downloadTask cancel];  // if download still in progress, stop it
    [self.player stop];          // if playing, stop it
}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    self.player = nil;
    [self.delegate song:self didFinishPlayingSuccessfully:flag];
}

@end

, , downloadAndPlay , , . cancel , , , .

:

@interface ViewController () <SongDelegate>

@property (nonatomic, strong) Song *song;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.song = [Song songWithURL:[NSURL URLWithString:@"http://dl.last.fm/static/1464677535/131211148/70b3b5a9d048c7939d5bb9ec87a2c5d58d6ee528828f5c6a5b7b1eddd69f4553/Death+Grips+-+Get+Got.mp3"] delegate:self];

    // Do any additional setup after loading the view, typically from a nib.
}

- (IBAction)didTapPlayButton:(id)sender {
    [self.song downloadAndPlay];
}

- (IBAction)didTapStopButton:(id)sender {
    [self.song cancel];
}

- (void)song:(Song *)song didFinishPlayingSuccessfully:(BOOL)flag {
    NSLog(@"did finish playing %@", flag ? @"successfully" : @"unsuccessfully");
}

- (void)song:(Song *)song didFinishDownloadWithError:(NSError *)error {
    NSLog(@"did finish download with error %@", error.localizedDescription);
}
@end

, , ( NSAssert, - , , , , Song, , 2 1 ..), , , , . , , .

, NSURLSession -https- - , , info.plist ( , " " - " " ), - :

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>dl.last.fm</key>
        <dict>
            <!--Include to allow subdomains-->
            <key>NSIncludesSubdomains</key>
            <true/>
            <!--Include to allow HTTP requests-->
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <!--Include to specify minimum TLS version-->
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.1</string>
        </dict>
    </dict>
</dict>
+2

All Articles