preventing call viewDidLoad twice - ios

I have scenario which fetching json requests from API and parse it on view. But if API pushes xml link, i need to start xml parse task with AFNetworking. After parsing xml, i am passing xml as parameter(NSData) in to another class method which i am assigning child values with NSXMLParser, after parsing has finished :
-(void)parserDidEndDocument:(NSXMLParser *)parser
{
ViewController *VS = [[VC alloc] init];
[VC vastXMLReturn:vastXMLDictionary rollType:rollType];
}
After sending parameters in ViewController following method is responsible to play video;
-(void)vastXMLReturn:(NSDictionary *)xml rollType:(NSString *)roll
{
NSLog(#"XML responses = %#",xml);
//NSString *mediaDuration = [xml objectForKey:#"mediaDuration"];
NSString *mediaFilePath = [xml objectForKey:#"mediaFilePath"];
//NSArray *trackingLists = [xml objectForKey:#"trackingLinks"];
advertisementURL = [NSURL URLWithString:roll];
[self playVideo:advertisementURL initial_time:0];
}
In PlayVideo Method
-(void)playVideo:(NSURL *)videoURL initial_time:(NSTimeInterval)playerTime
{
theMoviPlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
theMoviPlayer.controlStyle = MPMovieControlStyleNone;
[self performSelector:#selector(closeButtonForVideoPlayer) withObject:nil afterDelay:5.0];
theMoviPlayer.movieSourceType = MPMovieSourceTypeFile;
theMoviPlayer.view.transform = CGAffineTransformConcat(theMoviPlayer.view.transform, CGAffineTransformMakeRotation(M_PI_2));
[self.view addSubview:theMoviPlayer.view];
//[theMoviPlayer.moviePlayer requestThumbnailImagesAtTimes:#[ #4.3f ] timeOption:MPMovieTimeOptionExact];
[theMoviPlayer setFullscreen:YES animated:YES];
}
The real problem is after [theMoviPlayer setFullscreen:YES animated:YES]; line, breakpoint jumps in viewDidLoad method which is should not happen because the process will be starting in that method again and program terminates error.
What should i have to do for preventing goes in viewDidLoad method ?
Best Regards

Related

How to wait for delegate method execution before return statement?

I have a model object that has a class method that checks if the model object already exists, and if it does it returns it, or if it doesn't it creates it and then returns it. This class makes use of the VLC framework for generating data about video files and to generate a thumbnail. This is where I'm having trouble.
The VLCThumbnailer returns the thumbnail via a delegate method once it's fetchthumbnail method is called. The problem is that the delegate method doesn't get returned until AFTER my class-creation method reaches it's return function. Here's a code example.
-(AnimuProfile*)createnewProfileforFilename:(NSString*)filename{
NSURL *fileURL = [NSURL fileURLWithPath:filename];
VLCMedia *media = [VLCMedia mediaWithURL:fileURL];
FilenameParser *parser = [[FilenameParser alloc]init];
NSArray *parsedFilename = [parser parseFilename:[filename lastPathComponent]];
NSArray *mediaArray = [media tracksInformation];
if (mediaArray.count != 0) {
NSDictionary *videoTrackinfo = [mediaArray objectAtIndex:0];
_fansubGroup = parsedFilename[0];
_seriesTitle = parsedFilename[1];
_episodeNumber = parsedFilename[2];
_filename = [filename lastPathComponent];
_filepathURL = fileURL;
_filepathString = filename;
_watched = NO;
_progress = [VLCTime timeWithInt:0];
_length = [[media length]stringValue];
NSNumber *resolution = [videoTrackinfo valueForKey:#"height"];
_resolution = [NSString stringWithFormat:#"%#p",resolution];
VLCMediaThumbnailer *thumbnailer = [VLCMediaThumbnailer thumbnailerWithMedia:media andDelegate:self];
[thumbnailer fetchThumbnail];
NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *profileName = [[_filename lastPathComponent] stringByAppendingPathExtension:#"prf"];
NSString *pathandProfileName = [libPath stringByAppendingPathComponent:profileName];
[NSKeyedArchiver archiveRootObject:self toFile:pathandProfileName];
return self;
}
And then the delegate methods:
#pragma mark VLC Thumbnailer delegate methods
- (void)mediaThumbnailerDidTimeOut:(VLCMediaThumbnailer *)mediaThumbnailerP{
NSLog(#"Thumbnailer timed out on file %#",_filename);
UIImage *filmstrip = [UIImage imageNamed:#"filmstrip"];
_thumbnail = UIImagePNGRepresentation(filmstrip);
}
- (void)mediaThumbnailer:(VLCMediaThumbnailer *)mediaThumbnailer didFinishThumbnail:(CGImageRef)thumbnail{
UIImage *image = [UIImage imageWithCGImage:thumbnail];
_thumbnail = UIImagePNGRepresentation(image);
}
I know it's a nono to lock the main thread waiting for the delegate method to be called so what should be done in this instance?
I know it's a nono to lock the main thread waiting for the delegate
method to be called so what should be done in this instance?
Those delegate methods are being called on VLC's video processing thread. They aren't the main thread and, therefore, you shouldn't be calling random UIKit API directly in the return blocks.
You need to process the results when they are available. If VLC were implemented using modern patterns, it would be using completion blocks. But it isn't, so...
- (void)mediaThumbnailer:(VLCMediaThumbnailer *)mediaThumbnailer didFinishThumbnail:(CGImageRef)thumbnail{
{
dispatch_async(dispatch_get_main_queue(), ^{ ... process thumbnail and update UI accordingly here ...});
}
That is, your createnewProfileforFilename: method should start the processing, but not expect it to be finished until sometime later. Then, when that sometime later happens, you trigger the updating of the UI with the data that was processed in the background.
And, as you state, you should never block the main queue/thread.
I was able to solve it by creating a separate class to be the delgate, make thumbnail fetch requests and then handle them.
#property NSMutableArray *queue;
#end
#implementation ThumbnailWaiter
+(id)sharedThumbnailWaiter{
static ThumbnailWaiter *singletonInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singletonInstance = [[self alloc] init];
});
return singletonInstance;
}
-(id)init{
self = [super init];
if (self) {
NSMutableArray *queue = [NSMutableArray array];
_queue = queue;
}
return self;
}
-(void)requestThumbnailForProfile:(AnimuProfile*)profile{
VLCMedia *media = [VLCMedia mediaWithURL:profile.filepathURL];
VLCMediaThumbnailer *thumbnailer = [VLCMediaThumbnailer thumbnailerWithMedia:media andDelegate:self];
[_queue addObject:profile];
[thumbnailer fetchThumbnail];
}
#pragma mark VLC Thumbnailer delegate methods
- (void)mediaThumbnailerDidTimeOut:(VLCMediaThumbnailer *)mediaThumbnailerP{
}
- (void)mediaThumbnailer:(VLCMediaThumbnailer *)mediaThumbnailer didFinishThumbnail:(CGImageRef)thumbnail{
UIImage *image = [UIImage imageWithCGImage:thumbnail];
AnimuProfile *profile = _queue.firstObject;
profile.thumbnail = UIImagePNGRepresentation(image);
[profile saveProfile];
[_queue removeObjectAtIndex:0];
}
Seems almost silly to have to do it this way but it seems to be working.

presentOpenInMenuFromRect not working DocumentHandler.h - QuickLook

I'm using documenthandler cordova plugin in where if I click the button I get the pdf in the document handler from the url which works fine, so that I can save the pdf into iBooks.
Now, instead of opening the document in the viewer and clicking the share button and then click again to save into iBooks I need to be able to trigger the share button without opening the document. I know this can be done using presentOpenInMenuFromRect instead of presentViewControllerbut it does not work for some reason, code below:
#import "DocumentHandler.h"
#implementation DocumentHandler
- (void)HandleDocumentWithURL:(CDVInvokedUrlCommand*)command;
{
CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:#""];
__weak DocumentHandler* weakSelf = self;
dispatch_queue_t asyncQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(asyncQueue, ^{
NSDictionary* dict = [command.arguments objectAtIndex:0];
NSString* urlStr = dict[#"url"];
NSURL* url = [NSURL URLWithString:urlStr];
NSData* dat = [NSData dataWithContentsOfURL:url];
NSString* fileName = [url lastPathComponent];
NSString* path = [NSTemporaryDirectory() stringByAppendingPathComponent: fileName];
NSURL* tmpFileUrl = [[NSURL alloc] initFileURLWithPath:path];
[dat writeToURL:tmpFileUrl atomically:YES];
weakSelf.fileUrl = tmpFileUrl;
dispatch_async(dispatch_get_main_queue(), ^{
QLPreviewController* cntr = [[QLPreviewController alloc] init];
cntr.delegate = weakSelf;
cntr.dataSource = weakSelf;
UIViewController* root = [[[UIApplication sharedApplication] keyWindow] rootViewController];
[root presentViewController:cntr animated:YES completion:nil];//this works fine and open the document with share button
CGRect rect = CGRectMake(0, 0, 1024, 768);
[root presentOpenInMenuFromRect:rect inView:self.view animated:YES]; // this doesn't work where
//I want to see only sharing options
//here are errors,one of them is /Property'view' not found on object of type ''DocumentHandler
});
[weakSelf.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId];
});
}
#pragma mark - QLPreviewController data source
- (NSInteger) numberOfPreviewItemsInPreviewController: (QLPreviewController *) controller
{
return 1;
}
- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index
{
return self;
}
#pragma mark - QLPreviewItem protocol
- (NSURL*)previewItemURL
{
return self.fileUrl;
}
#end
I need help please :(
EDIT: see the image what I'm trying to achieve:
presentOpenInMenuFromRect is a UIDocumentInteractionController method. I do not think you are using one in this code, unless your root view controller is a UIDocumentInteractionController, which would be very very weird.
Instead of instantiating and presenting a QLPreviewController, instantiate an UIDocumentInteractionController and present the popover from the rect corresponding to the document's icon.
To do this, check out the UIDocumentInteractionController documentation. You'll see there is an interactionControllerWithURL: method that you can use to instantiate an UIDocumentInteractionController pointed at your file. You can then call
presentOpenInMenuFromRect:inView:animated: to show the popover you want.

GPUImage - MovieWriter, nothing happens for a while after "setCompletionBlock"

Been struggling with this for a couple of days now. I'm processing a video with a filter, it saves the video just fine. However, after it's saved, it takes a long time to update the UI. I can see the video in iTunes (with iTunes file sharing), a long time before the UI is updated.
I create the view like this, and add that to my view controller. This is just so the user can preview the video and select filter.
-(GPUImageView*)playClipWithClip:(MYClip*)clip
{
_clip = clip;
_filterView = [[GPUImageView alloc] initWithFrame:CGRectMake(0, 0, 568, 320)];
_movieFile = [[GPUImageMovie alloc] initWithURL:[self urlForCurrentClip]];
_movieFile.runBenchmark = NO;
_movieFile.playAtActualSpeed = YES;
_movieFile.shouldRepeat = YES;
[self changeFilter];
return _filterView;
}
When the user wants to save the video I have this method:
-(void)saveClipWithFilter
{
[_movieFile cancelProcessing];
_movieFile.runBenchmark = YES;
_movieFile.playAtActualSpeed = NO;
_movieFile.shouldRepeat = NO;
NSString *movieName = [self fileNameForGeneratedClip];
NSString *generatedMovieNameWithPath = [NSString stringWithFormat:#"Documents/%#",movieName];
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:generatedMovieNameWithPath];
unlink([pathToMovie UTF8String]);
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
_movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(568, 320.0)];
[_filter addTarget:_movieWriter];
_movieWriter.shouldPassthroughAudio = NO;
[_movieFile enableSynchronizedEncodingUsingMovieWriter:_movieWriter];
[_movieWriter startRecording];
[_movieFile startProcessing];
__weak typeof(self) weakSelf = self;
[_movieWriter setCompletionBlock:^{
NSLog(#"**************************** DONE ****************************");
[weakSelf.filter removeTarget:weakSelf.movieWriter];
[weakSelf.movieWriter finishRecording];
[weakSelf exitVideoEditingModeAndSave];
}];
}
My method [weakSelf exitVideoEditingModeAndSave]; is called. And that method in turn calls the delegate (my view controller).
The problem is that after my delegate is called and my NSLog shows, it will take about 10 seconds for the view to update. I know that the file is ready and has been saved.
Any ideas?
This is a threading issue, in your completion block, dispatch to the main thread before you update any UI elements

Memory Leak when sending image as an attachment via Email

I have a camera application where the user can share the photos taken through email.
I am using MFMailComposerViewController to send mail. Here is the piece of code.
- (void) contactEmailRecepients:(NSArray *)emailIDs
subject:(NSString *)subject
attachment:(NSMutableDictionary *)attachmentDictionary
sender:(UIViewController *)sender
{
if ([MFMailComposeViewController canSendMail])
{
mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
[mailViewController setToRecipients:emailIDs];
[mailViewController setSubject:subject];
NSData *attachmentData = [attachmentDictionary objectForKey:#"attachmentData"];
if (nil != attachmentData)
{
[mailViewController addAttachmentData:attachmentData
mimeType:[attachmentDictionary objectForKey:#"mimeType"]
fileName:[attachmentDictionary objectForKey:#"fileName"]];
}
[sender presentViewController:mailViewController
animated:YES
completion:^{}];
attachmentData = nil;
[attachmentDictionary removeAllObjects];
attachmentDictionary = nil;
}
else
{
// display error message
}
}
My problem is every time I send a mail through my application the VM(Virtual Memory) increases by 6/7 MB. But this does not happen if I comment out following part.
if (nil != attachmentData)
{
[mailViewController addAttachmentData:attachmentData
mimeType:[attachmentDictionary objectForKey:#"mimeType"]
fileName:[attachmentDictionary objectForKey:#"fileName"]];
}
The increased VM is due to CGRasterDataand the responsible library is CoreGraphicsand responsible caller is CGDataProvideCreateWithCopyOfDatawhen I check it through Xcode 5.0.2 instruments.So somewhere a copy is getting created which is not getting released later.I am suspecting the memory allocated to display the image in Email UIActionSheetis not getting released.
Any help is appreciated.
EDIT:
Adding the piece of code where attachmentData is getting initialized.
- (void)postPhotoFromPath:(NSString *)filePath
sender:(UIViewController *)sender
{
NSData *photoData = [NSData dataWithContentsOfFile:filePath];
if (nil == photoData)
{
//display error message
}
else
{
NSString *fileName = [[filePath componentsSeparatedByString:#"/"] lastObject];
[self contactEmailRecepients:nil
subject:nil
attachment:[NSDictionary dictionaryWithObjectsAndKeys:
photoData, #"attachmentData",
#"image/jpeg", #"mimeType",
fileName, #"fileName",
nil]
sender:sender];
}
}
Also I noticed carefully that VM increases exactly when i get the UIActionSheetregarding which image size to send(whether to send the original size or downscaled size). I am attaching the screenshot for the same here.

For-Loop to quick to present View Controller

i want to add multiple passbook passes by running through a array with URLs. The problem is that the loop counts faster than the view controller can present.
Here s my code:
NSArray *passURLArray = [NSArray new];
passURLArray = response;
for (int i = 0; passURLArray.count; i++) {
NSString *passURLString = [NSString stringWithFormat:#"http://test.de%#", [passURLArray objectAtIndex:i]];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:passURLString]];
NSError *error;
PKPass *pass = [[PKPass alloc] initWithData:data error:&error];
[[UIApplication sharedApplication] openURL:[pass passURL]];
PKAddPassesViewController *passVC = [[PKAddPassesViewController alloc] initWithPass:pass];
passVC.delegate = self;
[passVC setDelegate:(id)self];
[self presentViewController:passVC animated:YES completion:nil];
}
I get this error message:
Attempt to present PKAddPassesViewController: 0xca5f7d0 on
PaymentViewController: 0x14882290 which is waiting for a delayed
presention of PKAddPassesViewController: 0xb169470 to complete
Thanks in advance.
Check if you're on the last iteration of the loop. If you are, animate the display, if not, don't animate it.
That said, it's nasty from a user standpoint. You should probably think about a nicer way of presenting, like showing a list or animating between each display when addPassesViewControllerDidFinish: is called.

Resources