set uipageviewcontroller in ePub reader - iphone

I want to use UIPageViewController to implement the ebook reader.
The demo I am sing is AePubReader.
How to use UIPsgeViewController to implement real page turn effect.
How to add set page index while turn pages....
Here next page and previous page Methods:
- (void) gotoNextPage {
if(!paginating){
if(currentPageInSpineIndex+1<pagesInCurrentSpineCount){
[self gotoPageInCurrentSpine:++currentPageInSpineIndex];
} else {
[self gotoNextSpine];
}
}
}
- (void) gotoPrevPage {
if (!paginating) {
if(currentPageInSpineIndex-1>=0){
[self gotoPageInCurrentSpine:--currentPageInSpineIndex];
} else {
if(currentSpineIndex!=0){
int targetPage = [[loadedEpub.spineArray objectAtIndex:(currentSpineIndex-1)] pageCount];
[self loadSpine:--currentSpineIndex atPageIndex:targetPage-1];
}
}
}
}
Thanks....

You can find number of pages in a spine only after rendering the html to webview .I did as follows
- (void) setPagination:(UIWebView *) webView
{
NSString *varMySheet = #"var mySheet = document.styleSheets[0];";
NSString *addCSSRule = #"function addCSSRule(selector, newRule) {"
"ruleIndex = mySheet.cssRules.length;"
"mySheet.insertRule(selector + '{' + newRule + ';}', ruleIndex);" // For Firefox, Chrome, etc.
"}";
NSString *insertRule1 = [NSString stringWithFormat:#"addCSSRule('html', 'height: %fpx; -webkit-column-gap: 0px; -webkit-column-width: %fpx;')", webView.frame.size.height, webView.frame.size.width];
NSString *insertRule2 = [NSString stringWithFormat:#"addCSSRule('p', 'text-align: justify;')"];
//NSString *setTextSizeRule = [NSString stringWithFormat:#"addCSSRule('body', '-webkit-text-size-adjust: %d%%;')", currentTextSize];
[webView stringByEvaluatingJavaScriptFromString:varMySheet];
[webView stringByEvaluatingJavaScriptFromString:addCSSRule];
[webView stringByEvaluatingJavaScriptFromString:insertRule1];
[webView stringByEvaluatingJavaScriptFromString:insertRule2];
CGSize contentSize = CGSizeMake([[webView stringByEvaluatingJavaScriptFromString:#"document.body.scrollWidth;"] floatValue],
[[webView stringByEvaluatingJavaScriptFromString:#"document.body.scrollHeight;"] floatValue]);
self.pageVO.chapterVO.pageCountInChapter = contentSize.width/webView.frame.size.width;
// NSLog(#"content width : %f ,frame width : %f ,my page count : %f",contentSize.width,webView.frame.size.width,contentSize.width/webView.frame.size.width);
CGPoint point = CGPointMake(0, 0);
if([self checkIsPageIndexOutOfRange])
{
//after decreasing font size page will be left blank
[self.pageVO setIndexOfPage:self.pageVO.chapterVO.pageCountInChapter-1];
[_myDelegate myWebViewOnPageOutOfRange];
}
else
{
if([self.pageVO getIndexOfPage] ==PAGE_INDEX_GREATER_THAN_PAGE_COUNT)
{
//load last page of chapter
[self.pageVO setIndexOfPage:self.pageVO.chapterVO.pageCountInChapter-1];
}
if([self.pageVO getIndexOfPage] !=GET_PAGE_INDEX_USING_WORD_ID)
{
point = CGPointMake([self.pageVO getIndexOfPage]*webView.frame.size.width, 0);
self.scrollView.contentOffset = point;
}
}
[_myDelegate myWebViewDidLoadFinish];
}

Related

Flutter image_picker choose video

I am successfully using the Flutter Plugin Image_picker to choose images so that I can use them for upload, display, etc... I wondered if anyone had any guidance on how to modify this plugin to also see videos and allow them to be chosen and use for upload, etc...
Looking for iOS and Android modifications if anyone has guidance on how to proceed or example code. I have made some progress but still need to get the camera to save video and be able to present. I will post the code changes so far. I have it selecting a video, but it will not present back to the app.
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import UIKit;
#import <MobileCoreServices/MobileCoreServices.h>
#import "ImagePickerPlugin.h"
#interface ImagePickerPlugin ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
#end
static const int SOURCE_ASK_USER = 0;
static const int SOURCE_CAMERA = 1;
static const int SOURCE_GALLERY = 2;
#implementation ImagePickerPlugin {
FlutterResult _result;
NSDictionary *_arguments;
UIImagePickerController *_imagePickerController;
UIViewController *_viewController;
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FlutterMethodChannel *channel =
[FlutterMethodChannel methodChannelWithName:#"image_picker"
binaryMessenger:[registrar messenger]];
UIViewController *viewController =
[UIApplication sharedApplication].delegate.window.rootViewController;
ImagePickerPlugin *instance = [[ImagePickerPlugin alloc] initWithViewController:viewController];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (instancetype)initWithViewController:(UIViewController *)viewController {
self = [super init];
if (self) {
_viewController = viewController;
_imagePickerController = [[UIImagePickerController alloc] init];
}
return self;
}
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
if (_result) {
_result([FlutterError errorWithCode:#"multiple_request"
message:#"Cancelled by a second request"
details:nil]);
_result = nil;
}
if ([#"pickImage" isEqualToString:call.method]) {
_imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
_imagePickerController.delegate = self;
_result = result;
_arguments = call.arguments;
int imageSource = [[_arguments objectForKey:#"source"] intValue];
switch (imageSource) {
case SOURCE_ASK_USER:
[self showImageSourceSelector];
break;
case SOURCE_CAMERA:
[self showCamera];
break;
case SOURCE_GALLERY:
[self showPhotoLibrary];
break;
default:
result([FlutterError errorWithCode:#"invalid_source"
message:#"Invalid image source."
details:nil]);
break;
}
} else {
result(FlutterMethodNotImplemented);
}
}
- (void)showImageSourceSelector {
UIAlertControllerStyle style = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
? UIAlertControllerStyleAlert
: UIAlertControllerStyleActionSheet;
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:style];
UIAlertAction *camera = [UIAlertAction actionWithTitle:#"Take Photo"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self showCamera];
}];
UIAlertAction *library = [UIAlertAction actionWithTitle:#"Choose Photo"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self showPhotoLibrary];
}];
UIAlertAction *cancel =
[UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:camera];
[alert addAction:library];
[alert addAction:cancel];
[_viewController presentViewController:alert animated:YES completion:nil];
}
- (void)showCamera {
// Camera is not available on simulators
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
_imagePickerController.sourceType = UIImagePickerControllerCameraCaptureModeVideo;
[_viewController presentViewController:_imagePickerController animated:YES completion:nil];
} else {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:#"Camera not available."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
}
}
- (void)showPhotoLibrary {
// No need to check if SourceType is available. It always is.
//_imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
_imagePickerController.mediaTypes =[UIImagePickerController availableMediaTypesForSourceType:_imagePickerController.sourceType];
[_viewController presentViewController:_imagePickerController animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info {
[_imagePickerController dismissViewControllerAnimated:YES completion:nil];
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
if (image == nil) {
image = [info objectForKey:UIImagePickerControllerOriginalImage];
} else {
image = [self normalizedImage:image];
}
if (videoURL == nil) {
} else {
//image = videoURL;
}
NSNumber *maxWidth = [_arguments objectForKey:#"maxWidth"];
NSNumber *maxHeight = [_arguments objectForKey:#"maxHeight"];
if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) {
image = [self scaledImage:image maxWidth:maxWidth maxHeight:maxHeight];
}
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSString *tmpDirectory = NSTemporaryDirectory();
NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString];
// TODO(jackson): Using the cache directory might be better than temporary
// directory.
NSString *tmpFile = [NSString stringWithFormat:#"image_picker_%#.jpg", guid];
NSString *tmpPath = [tmpDirectory stringByAppendingPathComponent:tmpFile];
if ([[NSFileManager defaultManager] createFileAtPath:tmpPath contents:data attributes:nil]) {
_result(tmpPath);
} else {
_result([FlutterError errorWithCode:#"create_error"
message:#"Temporary file could not be created"
details:nil]);
}
_result = nil;
_arguments = nil;
}
// The way we save images to the tmp dir currently throws away all EXIF data
// (including the orientation of the image). That means, pics taken in portrait
// will not be orientated correctly as is. To avoid that, we rotate the actual
// image data.
// TODO(goderbauer): investigate how to preserve EXIF data.
- (UIImage *)normalizedImage:(UIImage *)image {
if (image.imageOrientation == UIImageOrientationUp) return image;
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
[image drawInRect:(CGRect){0, 0, image.size}];
UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return normalizedImage;
}
- (UIImage *)scaledImage:(UIImage *)image
maxWidth:(NSNumber *)maxWidth
maxHeight:(NSNumber *)maxHeight {
double originalWidth = image.size.width;
double originalHeight = image.size.height;
bool hasMaxWidth = maxWidth != (id)[NSNull null];
bool hasMaxHeight = maxHeight != (id)[NSNull null];
double width = hasMaxWidth ? MIN([maxWidth doubleValue], originalWidth) : originalWidth;
double height = hasMaxHeight ? MIN([maxHeight doubleValue], originalHeight) : originalHeight;
bool shouldDownscaleWidth = hasMaxWidth && [maxWidth doubleValue] < originalWidth;
bool shouldDownscaleHeight = hasMaxHeight && [maxHeight doubleValue] < originalHeight;
bool shouldDownscale = shouldDownscaleWidth || shouldDownscaleHeight;
if (shouldDownscale) {
double downscaledWidth = (height / originalHeight) * originalWidth;
double downscaledHeight = (width / originalWidth) * originalHeight;
if (width < height) {
if (!hasMaxWidth) {
width = downscaledWidth;
} else {
height = downscaledHeight;
}
} else if (height < width) {
if (!hasMaxHeight) {
height = downscaledHeight;
} else {
width = downscaledWidth;
}
} else {
if (originalWidth < originalHeight) {
width = downscaledWidth;
} else if (originalHeight < originalWidth) {
height = downscaledHeight;
}
}
}
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 1.0);
[image drawInRect:CGRectMake(0, 0, width, height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
#end
Thanks
Here is the IOS code that I have completed, I am still working on the Android if anyone wants to assist, I will post where I am at so far. This code replaces what is in the .m file of the IOS folder, no other changes are needed for this to work to pick and capture video along with images. You must figure out how to display the selected video/image in your app, but that's however you want to handle it. Again let me know if you want to assist with finishing he Android side.
#import UIKit;
#import <MobileCoreServices/MobileCoreServices.h>
#import "MediaPickerPlugin.h"
#interface MediaPickerPlugin ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
#end
static const int SOURCE_ASK_USER = 0;
//static const int SOURCE_CAMERA = 0;
//static const int SOURCE_GALLERY = 0;
#implementation MediaPickerPlugin {
FlutterResult _result;
NSDictionary *_arguments;
UIImagePickerController *_imagePickerController;
UIViewController *_viewController;
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FlutterMethodChannel *channel =
[FlutterMethodChannel methodChannelWithName:#"media_picker"
binaryMessenger:[registrar messenger]];
UIViewController *viewController =
[UIApplication sharedApplication].delegate.window.rootViewController;
MediaPickerPlugin *instance =
[[MediaPickerPlugin alloc] initWithViewController:viewController];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (instancetype)initWithViewController:(UIViewController *)viewController {
self = [super init];
if (self) {
_viewController = viewController;
_imagePickerController = [[UIImagePickerController alloc] init];
}
return self;
}
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
if (_result) {
_result([FlutterError errorWithCode:#"multiple_request"
message:#"Cancelled by a second request"
details:nil]);
_result = nil;
_arguments = nil;
}
if ([#"pickImage" isEqualToString:call.method]) {
_imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
_imagePickerController.delegate = self;
_result = result;
_arguments = call.arguments;
int imageSource = [[_arguments objectForKey:#"source"] intValue];
switch (imageSource) {
case SOURCE_ASK_USER:
[self showImageSourceSelector];
break;
default:
result([FlutterError errorWithCode:#"invalid_source"
message:#"Invalid image source."
details:nil]);
break;
}
} else {
result(FlutterMethodNotImplemented);
}
}
- (void)showImageSourceSelector {
UIAlertControllerStyle style = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
? UIAlertControllerStyleAlert
: UIAlertControllerStyleActionSheet;
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:style];
UIAlertAction *camera = [UIAlertAction actionWithTitle:#"Camera"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self showCamera];
}];
UIAlertAction *library = [UIAlertAction actionWithTitle:#"Gallery"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self showPhotoLibrary];
}];
UIAlertAction *cancel =
[UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:camera];
[alert addAction:library];
[alert addAction:cancel];
[_viewController presentViewController:alert animated:YES completion:nil];
}
- (void)showCamera {
// Camera is not available on simulators
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
_imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
_imagePickerController.mediaTypes = [NSArray arrayWithObjects:#"public.movie", #"public.image", nil];
_imagePickerController.delegate = self;
_imagePickerController.restoresFocusAfterTransition = false;
_imagePickerController.allowsEditing = NO;
_imagePickerController.videoQuality = UIImagePickerControllerQualityTypeLow;
_imagePickerController.videoMaximumDuration = 30.0f; // 30 seconds
[_viewController presentViewController:_imagePickerController animated:YES completion:nil];
} else {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:#"Camera not available."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
}
}
- (void)showPhotoLibrary {
// No need to check if SourceType is available. It always is.
_imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
_imagePickerController.mediaTypes = [NSArray arrayWithObjects:#"public.movie", #"public.image", nil];
//_imagePickerController.mediaTypes =[UIImagePickerController availableMediaTypesForSourceType:_imagePickerController.sourceType];
[_viewController presentViewController:_imagePickerController animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info {
[_imagePickerController dismissViewControllerAnimated:YES completion:nil];
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:#"public.movie"]) {
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSString *videoString = [videoURL absoluteString];
NSLog(#"Video File:%#", videoString);
_result(videoString);
} else {
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
if (image == nil) {
image = [info objectForKey:UIImagePickerControllerOriginalImage];
}
image = [self normalizedImage:image];
NSNumber *maxWidth = [_arguments objectForKey:#"maxWidth"];
NSNumber *maxHeight = [_arguments objectForKey:#"maxHeight"];
if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) {
image = [self scaledImage:image maxWidth:maxWidth maxHeight:maxHeight];
}
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSString *tmpDirectory = NSTemporaryDirectory();
NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString];
// TODO(jackson): Using the cache directory might be better than temporary
// directory.
NSString *tmpFile = [NSString stringWithFormat:#"image_picker_%#.jpg", guid];
NSString *tmpPath = [tmpDirectory stringByAppendingPathComponent:tmpFile];
NSLog(#"Image File:%#", tmpPath);
if ([[NSFileManager defaultManager] createFileAtPath:tmpPath contents:data attributes:nil]) {
_result(tmpPath);
} else {
_result([FlutterError errorWithCode:#"create_error"
message:#"Temporary file could not be created"
details:nil]);
}
_result = nil;
_arguments = nil;
}
_result = nil;
_arguments = nil;
}
// The way we save images to the tmp dir currently throws away all EXIF data
// (including the orientation of the image). That means, pics taken in portrait
// will not be orientated correctly as is. To avoid that, we rotate the actual
// image data.
// TODO(goderbauer): investigate how to preserve EXIF data.
- (UIImage *)normalizedImage:(UIImage *)image {
if (image.imageOrientation == UIImageOrientationUp) return image;
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
[image drawInRect:(CGRect){0, 0, image.size}];
UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return normalizedImage;
}
//- (NSString *)normalVideo:(NSURL *)videoURL {
// NSString *normalVideo = UIImagePickerControllerMediaURL;
// return normalVideo;
//}
- (UIImage *)scaledImage:(UIImage *)image
maxWidth:(NSNumber *)maxWidth
maxHeight:(NSNumber *)maxHeight {
double originalWidth = image.size.width;
double originalHeight = image.size.height;
bool hasMaxWidth = maxWidth != (id)[NSNull null];
bool hasMaxHeight = maxHeight != (id)[NSNull null];
double width = hasMaxWidth ? MIN([maxWidth doubleValue], originalWidth) : originalWidth;
double height = hasMaxHeight ? MIN([maxHeight doubleValue], originalHeight) : originalHeight;
bool shouldDownscaleWidth = hasMaxWidth && [maxWidth doubleValue] < originalWidth;
bool shouldDownscaleHeight = hasMaxHeight && [maxHeight doubleValue] < originalHeight;
bool shouldDownscale = shouldDownscaleWidth || shouldDownscaleHeight;
if (shouldDownscale) {
double downscaledWidth = (height / originalHeight) * originalWidth;
double downscaledHeight = (width / originalWidth) * originalHeight;
if (width < height) {
if (!hasMaxWidth) {
width = downscaledWidth;
} else {
height = downscaledHeight;
}
} else if (height < width) {
if (!hasMaxHeight) {
height = downscaledHeight;
} else {
width = downscaledWidth;
}
} else {
if (originalWidth < originalHeight) {
width = downscaledWidth;
} else if (originalHeight < originalWidth) {
height = downscaledHeight;
}
}
}
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 1.0);
[image drawInRect:CGRectMake(0, 0, width, height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
#end
I would probably add another method pickVideo to image_picker.dart, and then add the corresponding Android and iOS implementations of that in imagePickerPlugin.m and ImagePickerPlugin.java.
Inside the latter two, I would use the iOS and Android APIs for videos, e.g. something like this on iOS:
Objective c - ios : How to pick video from Camera Roll?
as of version 0.4.2, the plugin allows video to be selected
Added support for picking videos. Updated example app to show video
preview.
You can do that now using pickVideo available in image_picker
final _picker = ImagePicker();
PickedFile video = await _picker.getVideo(...)
...
Ref - https://pub.dev/packages/image_picker
you can use the image picker for recording video, and chewie library to show a video via video controller.
for more reference use this video link -
https://www.youtube.com/watch?time_continue=17&v=XSn5EwWBG-4&feature=emb_logo

Playing Youtube Video in iframe in UIWebView

Hello I'm parsing html string into web view and here is how I check for youtube videos and add them to iframe:
- (NSString *)extendYouTubeSupportInHtml:(NSString *)html {
static dispatch_once_t onceToken;
static NSRegularExpression *youtubeEmbedRegex;
dispatch_once(&onceToken, ^{
youtubeEmbedRegex = [[NSRegularExpression alloc] initWithPattern:#"<object.*src.*/v/(.*?)['|\"].*object\\s*>" options:NSRegularExpressionCaseInsensitive error:nil];
});
NSArray *matchs;
if (html != nil) {
matchs = [youtubeEmbedRegex matchesInString:html options:0 range:NSMakeRange(0, html.length)];
}else{
matchs = nil;
}
NSInteger rangeOffset = 0;
for (NSTextCheckingResult *match in matchs) {
NSRange objectRange = NSMakeRange([match rangeAtIndex:0].location + rangeOffset, [match rangeAtIndex:0].length);
NSRange idRange = NSMakeRange([match rangeAtIndex:1].location + rangeOffset, [match rangeAtIndex:1].length);
NSString* youtubrId = [html substringWithRange:idRange];
// Add uniq id to img tag
NSString* iframe = [NSString stringWithFormat:#"<iframe src=\"http://www.youtube.com/embed/%#\" frameborder=\"0\" allowfullscreen></iframe>", youtubrId];
html = [html stringByReplacingCharactersInRange:objectRange withString:iframe];
rangeOffset += iframe.length - objectRange.length;
}
return html;
}
And here is how I'm displaying the web view:
- (id)initWithFrame:(CGRect)frame dict:(NSDictionary *)dict {
self = [super initWithFrame:frame];
if (self) {
self.webView = [[[UIWebView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)] autorelease];
self.webView.backgroundColor = [UIColor clearColor];
self.webView.opaque = NO;
self.webView.delegate = self;
self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.webView.scalesPageToFit = NO;
self.webView.allowsInlineMediaPlayback = YES;
self.webView.mediaPlaybackRequiresUserAction = NO;
[self removeBackgroundFromWebView:self.webView];
[self addSubview:self.webView];
self.dictionary = dict;
}
return self;
}
My issue is that when I start playing video - memory usage is going up to 30MB, video starts to stutter, audio/video doesn't match, and when i close it - the memory usage is still the same.
I have a couple of leaks in AudioToolbox, also.
I'm using iOS 6 SDK, and iOS 6.
iOS 6 sdk broke the code - now it's not displaying anything in iOS 5.
This is my way of play a youtube video inside a app.
I am using iFrame to load youtube video inside my app.
follow this steps and you will too.
create a uiwebview and connect it to your .h file. Mine is _webView.
Add this method to your .m file.
-(void)embedYouTube{
NSString *embedHTML = #"<iframe width=\"300\" height=\"250\" src=\"http://www.youtube.com/embed/rOPI5LDo7mg\" frameborder=\"0\" allowfullscreen></iframe>";
NSString *html = [NSString stringWithFormat:embedHTML];
[_webView loadHTMLString:html baseURL:nil];
[self.view addSubview:_webView];
}
I am using the embedded code in youtube video. (I hope you know what it is)
call this method inside your viewdidload
[self embedYouTube];
Run the app and you will see the video in your view. This way is perfectly working for me and i think this will help for your too.

Not firing self.viewcontroller.webview.delegate = self+PhoneGap+secondtime

I have to reload the mainviewcontroller webview second time and reload the webview.
APPDELGATE:
- (void) webViewDidFinishLoad:(UIWebView*) theWebView
{
// only valid if FooBar.plist specifies a protocol to handle
if (self.invokeString)
{
// this is passed before the deviceready event is fired, so you can access it in js when you receive deviceready
NSString* jsString = [NSString stringWithFormat:#"var invokeString = \"%#\";", self.invokeString];
[theWebView stringByEvaluatingJavaScriptFromString:jsString];
}else {
if([loginComplete isEqualToString:#"1"] ){
NSString *page = #"intro.html";
NSString* jsString = [NSString stringWithFormat:#"loadParams('%#','%#','%#');", at,userfbid,page];
[theWebView stringByEvaluatingJavaScriptFromString:jsString];
}
else {
NSString *page = #"friends.html";
NSString* jsString = [NSString stringWithFormat:#"loadParams('%#','%#','%#');", at,userfbid,page];
[theWebView stringByEvaluatingJavaScriptFromString:jsString];
}
// Black base color for background matches the native apps
theWebView.backgroundColor = [UIColor grayColor];
return [self.viewController webViewDidFinishLoad:theWebView];
}
-(void)insert{
self.viewcontroller.webview.delegate=self;
}
Webdelegate is not firing in insert.
Thanks
Try this:
return [self webViewDidFinishLoad:theWebView];
instead of:
return [self.viewController webViewDidFinishLoad:theWebView];
Because your AppDelegate is the delegate for webView's webViewDidFinishLoaded, not webView itself.

How to run, restart and kill thread in Objective C?

I have a function which update pagination i.e. calculate total number of pages.
- (void) updatePagination{
if(!paginating){
NSLog(#"Pagination Started!");
paginating = YES;
totalPagesCount=0;
for (UIGestureRecognizer *gr in self.pageViewController.gestureRecognizers) {
[gr setEnabled:NO];
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[self loadSpine:currentSpineIndex atPageIndex:currentPageInSpineIndex];
[[loadedEpub.spineArray objectAtIndex:0] setDelegate:self];
//This Line calls method of another class
[[loadedEpub.spineArray objectAtIndex:0] loadChapterWithWindowSize:webView.bounds fontPercentSize:currentTextSize];
[currentPageLabel setText:#"?/?"];
}
}
}
This is the method it calls
- (void) loadChapterWithWindowSize:(CGRect)theWindowSize fontPercentSize:(int) theFontPercentSize{
fontPercentSize = theFontPercentSize;
windowSize = theWindowSize;
UIWebView* webView = [[UIWebView alloc] initWithFrame:windowSize];
[webView setDelegate:self];
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:spinePath]];
[webView loadRequest:urlRequest];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
[webView dealloc];
}
- (void) webViewDidFinishLoad:(UIWebView*)webView{
NSString *varMySheet = #"var mySheet = document.styleSheets[0];";
NSString *addCSSRule = #"function addCSSRule(selector, newRule) {"
"if (mySheet.addRule) {"
"mySheet.addRule(selector, newRule);" // For Internet Explorer
"} else {"
"ruleIndex = mySheet.cssRules.length;"
"mySheet.insertRule(selector + '{' + newRule + ';}', ruleIndex);" // For Firefox, Chrome, etc.
"}"
"}";
NSString *insertRule1 = [NSString stringWithFormat:#"addCSSRule('html', 'padding: 0px; height: %fpx; -webkit-column-gap: 0px; -webkit-column-width: %fpx;')", webView.frame.size.height, webView.frame.size.width];
NSString *insertRule2 = [NSString stringWithFormat:#"addCSSRule('p', 'text-align: justify;')"];
NSString *setTextSizeRule = [NSString stringWithFormat:#"addCSSRule('body', '-webkit-text-size-adjust: %d%%;')",fontPercentSize];
[webView stringByEvaluatingJavaScriptFromString:varMySheet];
[webView stringByEvaluatingJavaScriptFromString:addCSSRule];
[webView stringByEvaluatingJavaScriptFromString:insertRule1];
[webView stringByEvaluatingJavaScriptFromString:insertRule2];
[webView stringByEvaluatingJavaScriptFromString:setTextSizeRule];
int totalWidth = [[webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.scrollWidth"] intValue];
pageCount = (int)((float)totalWidth/webView.bounds.size.width);
[webView dealloc];
[delegate chapterDidFinishLoad:self];
}
Because of this my UI not get struck but when user dismiss or pop the view app get crashed. Also another button to increase and decrease the size of the text also called same method so if already it is running and user clicks on resize the font it struck or sometime get crashed.
My Questions are:
Is it possible to run it in background and if user dismiss the modal
then instead of crash it should stop.
If user clicks on resizing of font size then it should stop old and run new.
can I utilize the totalpages calculated even if its processing still going on.
I used
[self performSelectorOnMainThread:#selector(LoadChapters) withObject:nil waitUntilDone:NO]; (works but sometime give error for webview)
and NSOperation (not works)
to call that single line of function call.

UIImage problem

I am loading the images of size 450KB in UIImage view and then adding it to UIscrollview. while am scrolling the 30 images continously,its getting crashed.. what may be the reason..is this memory leak issue...or image size is the problem...? thanks in advance..
here is my code ..
#try{
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
//NSArray *array = [global_ContentString componentsSeparatedByString:#"###"];
NSArray *array1 = [catalogURL componentsSeparatedByString:#"&"];
//**NSLog(#"array1****** = %#",array1);
NSLog(#"loading catalog image(method: loadCatalogImage).......%#%#",baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:0]);
//NSLog(#"baseURL = %#",baseURL);
NSLog(#"loading catalog image.......%#%#",baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:0]);
zoomedImageURL = [NSString stringWithFormat:#"%#%#", baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:1]];
[zoomedImageURL retain];
NSLog(#"aaaaaaaaaaaaaa = %#",zoomedImageURL);
//UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#",baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:0]]]]];
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",zoomedImageURL]]]];
imgView.contentMode = UIViewContentModeScaleAspectFit;
imgView.image = img;//[GPSTripTracking generatePhotoThumbnail:img:109];
[pool release];
[global_imgProgress stopAnimating];
}
#catch (NSException *e) {
[global_imgProgress stopAnimating];
NSLog(#"Exception....");
}
#finally {
}
am releasing my imgView in dealloc method..
i imlemented the following code in "scrollviewdidscroll"
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
// which a scroll event generated from the user hitting the page control triggers updates from
// the delegate method. We use a boolean to disable the delegate logic when the page control is used.
if (pageControlUsed) {
// do nothing - the scroll was initiated from the page control, not the user dragging
//pageText.text = [NSString stringWithFormat:#"%d/%d", (pageControl.currentPage +1), pageControl.numberOfPages];
pageText.text = [NSString stringWithFormat:#"%d/%d", (pageControl.currentPage ), pageControl.numberOfPages];
//NSLog(#"not scrollling page....");
return;
}
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
// load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
//NSLog(#"scrolling page....%d", page);
// A possible optimization would be to unload the views+controllers which are no longer visible
}
and my code for " loadScrollViewWithPage" is
- (void)loadScrollViewWithPage:(int)page
{
//page--;
if (page < 0) return;
if (page >= numberOfPages) return;
if(!isViewCatalog && searchId == 1)
{
//NSLog(#"curre page = %d",pageControl.currentPage);
NSArray *array1 = [global_ContentString componentsSeparatedByString:#"###"];
if(searchInCatalogFlag == 1)
{
pageControl.currentPage=0;
NSArray *urlArray = [[array1 objectAtIndex:pageControl.currentPage] componentsSeparatedByString:#"##"];
//NSLog(#"url array** = %#",urlArray);
headerText.text = [NSString stringWithString:[urlArray objectAtIndex:0]];
pageText.text = [NSString stringWithFormat:#"%d/%d", pageControl.currentPage, (pageControl.numberOfPages - 1)];
}
else
{
NSArray *urlArray = [[array1 objectAtIndex:pageControl.currentPage] componentsSeparatedByString:#"##"];
//NSLog(#"url array** = %#",urlArray);
headerText.text = [NSString stringWithString:[urlArray objectAtIndex:0]];
pageText.text = [NSString stringWithFormat:#"%d/%d", pageControl.currentPage, (pageControl.numberOfPages - 1)];
}
if(page == selectedPage && ![global_imgProgress isAnimating])
[global_imgProgress startAnimating];
}
else
{
headerText.text = [NSString stringWithString:global_SelectedCatalogName];
pageText.text = [NSString stringWithFormat:#"%d/%d", (pageControl.currentPage + 1), (pageControl.numberOfPages - 1)];
if(page == selectedPage + 1 && ![global_imgProgress isAnimating] )
[global_imgProgress startAnimating];
// NSLog(#"header text = %#", headerText.text);
//headerText.text = [NSString stringWithString:[urlArray objectAtIndex:0]];
}
FullPageView *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null] ) {
//NSLog(#"Loading page =========== %d, %d", page, selectedPage);
//voucherPageNo = page;
//[voucherImage retain];
if(universalApp==2)
{
controller = [[FullPageView alloc] initWithNibName:#"FullPageView_iphone" bundle:nil];//:page];
[controller.view setFrame:CGRectMake(0, 0, 320,332)];
}
else
{
controller = [[FullPageView alloc] initWithNibName:#"FullPageView" bundle:nil];//:page];
[controller.view setFrame:CGRectMake(0, 192, 768, 691)];
}
//[controller.view setFrame:CGRectMake(0, 0, 320,480)];
//[controller.view setFrame:CGRectMake(0, 192, 768, 691)];
if((!isViewCatalog && searchId < 2 && searchInCatalogFlag == 0))// || searchInCatalogFlag == 1)
{
// NSLog(#">>>>>>>>>>>>>>>>>> LOADING IMAGE >>>>>>>>>>>>>>>>>>>>");
[controller setPageNo:page];
// if(page >= selectedPage - 1)
[NSThread detachNewThreadSelector:#selector(loadImage) toTarget:controller withObject:nil];
}
else //if((page >= (selectedPage - 1) && page <= (selectedPage + 1)) || !isFirstTimeLoading)
{
NSLog(#"Loading CATALOG IMAGE = %d, %d, %#", page, selectedPage, (isFirstTimeLoading ?#"YES" : #"NO"));
[controller setCatalogURL:[NSString stringWithFormat:#"%#", [catalogArray objectAtIndex:page+(searchId< 2 && !isViewCatalog && searchInCatalogFlag == 0?0:1)]]];
NSLog(#"loading image ipad= %#", [catalogArray objectAtIndex:page+(searchId< 2 && !isViewCatalog && searchInCatalogFlag == 0?0:1)]);
// if(page >= selectedPage - 1)
[NSThread detachNewThreadSelector:#selector(loadCatalogImage) toTarget:controller withObject:nil];
// if(page == (selectedPage + 1))
//isFirstTimeLoading = NO;
}
[viewControllers replaceObjectAtIndex:page withObject:controller];
[controller release];
}
// add the controller's view to the scroll view
if (nil == controller.view.superview)
{
// NSLog(#"Voucher view addead at page..... %d", page);
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
// NSLog(#">>>>>>>>> %f, %f", frame.size.width, frame.origin.x);
[scrollView addSubview:controller.view];
}
//if(page == pageControl.currentPage)
//[imgProgress startAnimating];
//else
//pageControlUsed = YES;
}
where wil be the problem..?
450KB is the compressed image size. When an image is loaded into memory, it is uncompressed.
A rule of thumb for working out how much memory an uncompressed image will occupy is:
width * height * 4
With 30 images it is very likely that you're running out of memory.
You should write your code to only keep images in memory if they are visible on screen.
It very likely that your program gets terminated by iOS because it consumes too much memory. Start it from XCode and look at the console - it will probably print that it receives memory warnings.
You will have to load the images on demand, i.e. only when the user gets close to seeing them, and you will have to release the ones that move out of view again. To that end, implement the
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
delegate method, look at the scroll view's content offset and load/release the appropriate images. Alternatively, you can choose to not release them there but instead wait for a memory warning to do so. To do so, implement the
- (void)didReceiveMemoryWarning
method in your view controller.
This might be the issue of memory leaks.
Try to replace this line
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",zoomedImageURL]]]]
and use this
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",zoomedImageURL]]]];
<<<<<YOUR CODE>>>>
[img release];
I hope this helps