QLPreviewController only shows a single file - objective-c

I am using a QLPreviewController to display a set of files. However, it only shows the first one and I can't seem to swipe or do anything to show the second. What am I doing wrong? Do I have to set it manually? If so - how would I go about doing that?
This is from my AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// normal viewcontroller init here
[self showPreview] ;
return YES;
}
NSArray* documents ;
QLPreviewController* preview ;
- (void) showPreview
{
documents = [[NSArray alloc] initWithObjects: #"photo" , #"photo2" , nil ] ;
preview = [[QLPreviewController alloc] init];
preview.dataSource = self;
preview.delegate = self;
preview.view.frame = [[UIScreen mainScreen] bounds];
//save a reference to the preview controller in an ivar
// self.previewController = preview;
//refresh the preview controller
[preview reloadData];
[[preview view] setNeedsLayout];
[[preview view] setNeedsDisplay];
[preview refreshCurrentPreviewItem];
preview.view.userInteractionEnabled = YES;
//add it
[self.viewController.view addSubview:preview.view];
}
I also declared the two callback functions in the same AppDelegate.m file:
- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index
{
NSString* filename = [documents objectAtIndex:index] ; // #"photo" ;
NSURL* returnURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource: filename ofType:#"jpg" ]] ;
return returnURL ;
}
- (NSInteger) numberOfPreviewItemsInPreviewController: (QLPreviewController *) controller
{
return [documents count];
}

You are displaying it wrong.
QLPreviewController is a UIViewController, which means you basically have 2 ways of displaying it:
Push it into your UINavigationController.
Display it modally (this can be done with or without a UINavigationController - depends if you want a navigation bar).
If you choose option 2 you get "free" navigation arrows to switch between items.
For option 1 you need to create the arrows yourself.
This following is taken from the QLPreviewController documentation:
If there is more than one item in the list, a modally-presented (that
is, full-screen) controller displays navigation arrows to let the user
switch among the items. For a Quick Look preview controller pushed
using a navigation controller, you can provide buttons in the
navigation bar for moving through the navigation list.

Related

iOS10 SFSafariViewController not working when alpha is set to 0

I'm using SFSafariViewController to grab user's cookie in my app. Here's is my code:
SFSafariViewController *safari = [[SFSafariViewController alloc]initWithURL:[NSURL URLWithString:referrerUrl] entersReaderIfAvailable:NO];
safari.delegate = self;
safari.modalPresentationStyle = UIModalPresentationOverCurrentContext;
safari.view.alpha = 0.0;
safari.view.hidden = true;
[self dismissViewControllerAnimated:false completion:nil];
NSLog(#"[referrerService - StoreViewController] presenting safari VC");
[self presentViewController:safari animated:false completion:nil];
This works well on iOS 9. but on iOS 10 it seems that the SF controller doesn't work (it also block my current context - which happens to be another UIWebView).
Anyone can suggest of an alternative way to hide a SFSafariViewController?
Updated answer:
Apple prohibits this kind of SafariViewController usage in last version of review guidelines:
SafariViewContoller must be used to visibly present information to users; the controller may not be hidden or obscured by other views or layers. Additionally, an app may not use SafariViewController to track users without their knowledge and consent.
Old answer:
In iOS 10 there are some additional requirements for presented SFSafariViewController:
1) Your view should not be hidden, so hidden should be set to NO
2) The minimum value for alpha is 0.05
3) You need to add controller manually with addChildViewController: / didMoveToParentViewController: (callback's doesn't called otherwise).
4) UIApplication.keyWindow.frame and SFSafariViewController.view.frame should have non-empty intersection (in appropriate coordinate space), that means:
safari view size should be greater than CGSizeZero
you can't place safari view off the screen
but you can hide safari view under your own view
Code example:
self.safariVC = [[SFSafariViewController alloc] initWithURL:referrerUrl];
self.safariVC.delegate = self;
self.safariVC.view.alpha = 0.05;
[self addChildViewController:self.safariVC];
self.safariVC.view.frame = CGRectMake(0.0, 0.0, 0.5, 0.5);
[self.view insertSubview:self.safariVC.view atIndex:0];
[self.safariVC didMoveToParentViewController:self];
Also, don't forget to remove safariVC properly after the end of the usage:
[self.safariVC willMoveToParentViewController:nil];
[self.safariVC.view removeFromSuperview];
[self.safariVC removeFromParentViewController];
New info: Don't do this.
The revised App Store guidelines prohibit this practice.
https://developer.apple.com/app-store/review/guidelines/
I'll leave this below for posterity:
I call the following code from my app delegate's didFinishLaunchingWithOptions.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self checkCookie];
}
- (void)checkCookie
{
NSURL *url = [NSURL URLWithString:#"http://domainToCheck.com"];
SFSafariViewController *vc = [[SFSafariViewController alloc] initWithURL:url];
vc.delegate = self;
UIViewController *windowRootController = [[UIViewController alloc] init];
self.secondWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.secondWindow.rootViewController = windowRootController;
[self.secondWindow makeKeyAndVisible];
[self.secondWindow setAlpha:0.1];
[windowRootController presentViewController:vc animated:NO completion:nil];
self.window.windowLevel = 10;
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(nonnull NSDictionary<NSString *,id> *)options
{
[self.secondWindow.rootViewController dismissViewControllerAnimated:NO completion:nil];
self.secondWindow = nil;
self.window.windowLevel = 0;
return YES;
}
I was able to achieve this affect using invisible child view controller:
_safariViewController = [[SFSafariViewController alloc] initWithURL:_requestURL];
_safariViewController.delegate = self;
_safariViewController.view.userInteractionEnabled = NO;
_safariViewController.view.alpha = 0.0;
[_containerViewController addChildViewController:_safariViewController];
[_containerViewController.view addSubview:_safariViewController.view];
[_safariViewController didMoveToParentViewController:_containerViewController];
_safariViewController.view.frame = CGRectZero;
its possible to use this on swift 3 for xcode 8.3.2 becausa i get all i delegate anduse correctly , but i have this error
[12:05]
2017-04-25 12:05:03.680 pruebaslibrary[7476:136239] Warning: Attempt to present on whose view is not in the window hierarchy!

Pop up UIViewController with an IBAction UIViewController

Is it possible to pop up an UIViewController (xib file) like UIPopOverControl in iPad ?
I have a separate NIB file which is linked to an UIViewController. I want to popup that NIB file along with the button pressed with a customised size (200,200).
Is this possible?
I am trying to get something like this on the iPhone - http://www.freeimagehosting.net/c219p
You can also use one of these custom made clases to show a popup:
https://github.com/sonsongithub/PopupView
https://github.com/werner77/WEPopover
https://github.com/50pixels/FPPopover
Example with FPPopover:
//the view controller you want to present as popover
YourViewController *controller = [[YourViewController alloc] init];
//our popover
FPPopoverController *popover = [[FPPopoverController alloc] initWithViewController:controller];
//the popover will be presented from the okButton view
[popover presentPopoverFromView:okButton];
//release if you arent using ARC
[controller release];
yes it is. load Your pOpOver controller lazily at the point when it is needed. add its view as a subview (you could animate the addition). make its frame size what You need and add the image You have shown as a background subview of the pOpOver controller along with other controls You want in the pop up.
good luck
UPDATE:
alright, ii will show You how ii do this in my app Lucid Reality Check (deployment target iOS4.3).
one can use a UIPopoverController to present another controllers view. what ii do first is to make sure ii always know the current orientation of the device, so ii can reposition the popup on rotation (maybe this works by itself on iOS6?). so in my base controller (from where ii want to show a popup) ii have an instance variable like this:
UIInterfaceOrientation toOrientation;
and also:
UIPopoverController *popover;
UIButton *popover_from_button;
BOOL representPopover;
popover will be reused for all popups, and popover_from_button will hold the button from which the popup is initiated.
then the next code comes into the base controller:
- (void)popoverWillRotate {
if ([popover isPopoverVisible]) {
[self dismissPopover];
representPopover = YES;
}
}
- (void)popoverDidRotate {
if (popover && representPopover) {
representPopover = NO;
[self representPopover];
}
}
these two methods have to be called every time the device is rotated, like this:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
//DLOG(#"willRotateTo %i", toInterfaceOrientation);
toOrientation = toInterfaceOrientation;
if ([Kriya isPad ]) {
[self popoverWillRotate];
}
}
as one can see, first the orientation is captured then popoverWillRotate is called. this would hide the popover during the orientation animation. and after rotating, the popover must be redisplayed like this:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
//DLOG(#"didRotateFrom %i", fromInterfaceOrientation);
//[self layout:toOrientation]; //do some layout if You need
if ([Kriya isPad]) {
[self popoverDidRotate];
}
}
- (void)layout:(UIInterfaceOrientation)toInterfaceOrientation {
//one can do view layout here, and call other controllers to do their layout too
}
now that the orientation changes are worked out, the code for presenting the popover arrives here:
#pragma mark Popovers
- (void)presentPopoverWith:(id)controller fromButton:(UIButton*)button {
if (popover)
[popover release];
if (popover_from_button)
[popover_from_button release];
popover_from_button = [button retain];
popover = [[UIPopoverController alloc] initWithContentViewController:controller];
[popover setDelegate:self];
[self representPopover];
}
- (void)representPopover{
if (popover) {
UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirectionAny;
UIViewController *vc = (UIViewController*)[popover contentViewController];
CGSize contentSize = [vc contentSizeForViewInPopover];
if (contentSize.width > 0 && contentSize.height > 0) {
[popover setPopoverContentSize:contentSize animated:NO];
}
//DLOG(#"representPopover rect:%#", [Kriya printRect:popover_from_button.frame]);
[popover presentPopoverFromRect:CGRectOffset(popover_from_button.frame, 0, popover_from_button.frame.size.height + 7.0) inView:self.view permittedArrowDirections:arrowDirection animated:YES];
}
}
- (void)dismissPopover {
if (popover) {
[popover dismissPopoverAnimated:YES];
}
}
finally, if one wants to be notified when the popover is dismissed, the base controller must implement a delegate method:
#pragma mark UIPopoverControllerDelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
//do something important here like drink some water
}
and don't forget to make the base controller a UIPopoverControllerDelegate in its header.
a use case for this way of doing popups would then look like this:
- (void)takeImage {
UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
[picker setDelegate:self];
[picker setAllowsEditing:NO];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[picker setSourceType:UIImagePickerControllerSourceTypeCamera];
if ([Kriya isPad]) {
[self presentPopoverWith:picker fromButton:backgroundImageButton];
} else {
//modals on iPhone/iPod
//DLOG(#"takeImage addSubview picker");
[self presentModalViewController:picker animated:YES];
}
} else {
//DLOG(#"no camera");
}
}
this would use an image picker as the content for the popup, but one can use any controller with a valid view. so just do this:
[self presentPopoverWith:popupsContentController fromButton:tappedButton];
one should not have any missing information, :), the method [Kriya isPad] is just this:
+ (BOOL)isPad {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
// iPad capable OS
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
//this is an iPad
return YES;
}else {
//this is an iPod/iPhone
return NO;
}
#else
//can not pissible be iPad
return NO;
#endif
}
ENJOY!

Xcode Page Based Application Interface Rotation Issue

Start a new page based application project in Xcode
Run the project and turn some pages
Rotate the simulator or device
=> The page view conroller switches back to the first page (january)
How can I prevent step 4. ?
EDIT:
This happens only the first time you rotate after the app started in simulator/device.
I use most recent Xcode 4.5 with iOS 6.0 Simulator and iOS 6 on my testing device.
The same thing happens when I download some other sample code from blogs / etc. Maybe an iOS 6 bug?
EDIT2:
I found out that the first page view that is passed to the UIPageViewController is not dealloced until first rotation. This really looks like a bug to me.
(UPDATE FROM 2014: This seems to have been fixed in iOS7, if you start again from a new Page View application template.)
I've experienced this bug as well. It seems to kick in any time after the main view reappears. My app has several full-screen modals in it, and after those go away the same behaviour occurs.
This happens in XCode 4.5.1 and iOS6 - I 'fixed' this by re-downloading XCode 4.4 and reverting my app back to iOS5.1. Obviously not a great long-term solution. I filed this in Radar and got a note back that it was already logged.
FWIW I noticed that iBooks had this same bug in it right after iOS6 came out, but they seem to have fixed it in a recent update.
Here's how I managed to fix this problem in my app. I'm afraid it's kind of a hacky solution, but it's a quirky bug.
Context: My app is a diary (it's called Remembary) and each page is a different day's diary entry. I have a singleton class called "AppContext" that keeps track of various app-level values, such as the currently showing diary entry object, the current date, and the like. Each day's dataViewController also keeps track of its own diary entry.
The trickiest part was finding a context where I could catch that the app was showing the wrong page. It turns out that this is in [RootViewController viewDidLayoutSubviews], so I added the following to that method:
// get the currently displaying page
DataViewController *currentPage = self.pageViewController.viewControllers[0];
// check if we're showing the wrong page
if ([currentPage myEntry] != [AppContext getCurrentEntry]) {
// jump to the proper page (the delay is needed to ensure that the rotation has fully completed)
[self performSelector:#selector(forceJumpToDate:)
withObject:[AppContext getCurrentEntryDate]
afterDelay:0.5];
}
Here's the forceJumpToDate function, which basically gets a new page based on the current date and tells the pageViewController to jump to it without animating:
- (void) forceJumpToDate:(NSDate *)targetDate {
DataViewController *targetPage = [self.modelController viewControllerForDate:targetDate
storyboard:self.storyboard];
NSArray *viewControllers = [NSArray arrayWithObject:targetPage];
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:NULL];
}
The user might notice a brief hiccup on the screen as the new page is forced into place, but this only happens if they would otherwise be getting the wrong page, so it's still an improvement.
This was seriously interfering with my ability to upgrade my app to iOS6, so I'm glad I finally figured it out.
Here is my solution:
// RootViewController.m
#import "RootViewController.h"
#import "ModelController.h"
#import "DataViewController.h"
#interface RootViewController ()
#property (readonly, strong, nonatomic) ModelController *modelController;
//added
#property (strong, nonatomic) DataViewController *currentViewController;
#end
#implementation RootViewController
#synthesize modelController = _modelController;
//added
#synthesize currentViewController = _currentViewController;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Configure the page view controller and add it as a child view controller.
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageViewController.delegate = self;
DataViewController *startingViewController = [self.modelController viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
self.pageViewController.dataSource = self.modelController;
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
// Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
CGRect pageViewRect = self.view.bounds;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
pageViewRect = CGRectInset(pageViewRect, 40.0, 40.0);
}
self.pageViewController.view.frame = pageViewRect;
[self.pageViewController didMoveToParentViewController:self];
// Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
//added
self.currentViewController = self.pageViewController.viewControllers[0];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (ModelController *)modelController
{
// Return the model controller object, creating it if necessary.
// In more complex implementations, the model controller may be passed to the view controller.
if (!_modelController) {
_modelController = [[ModelController alloc] init];
}
return _modelController;
}
#pragma mark - UIPageViewController delegate methods
/*
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
}
*/
//added
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
self.currentViewController = self.pageViewController.viewControllers[0];
}
- (DataViewController *)currentViewController
{
if (!_currentViewController) _currentViewController = [[DataViewController alloc] init];
return _currentViewController;
}
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
if (UIInterfaceOrientationIsPortrait(orientation) || ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)) {
// In portrait orientation or on iPhone: Set the spine position to "min" and the page view controller's view controllers array to contain just one view controller. Setting the spine position to 'UIPageViewControllerSpineLocationMid' in landscape orientation sets the doubleSided property to YES, so set it to NO here.
//deleted: UIViewController *currentViewController = self.pageViewController.viewControllers[0];
//changed to self.currentViewController
NSArray *viewControllers = #[self.currentViewController];
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:NULL];
self.pageViewController.doubleSided = NO;
return UIPageViewControllerSpineLocationMin;
}
// In landscape orientation: Set set the spine location to "mid" and the page view controller's view controllers array to contain two view controllers. If the current page is even, set it to contain the current and next view controllers; if it is odd, set the array to contain the previous and current view controllers.
// deleted: DataViewController *currentViewController = self.pageViewController.viewControllers[0];
//deleted: NSArray *viewControllers = nil;
//added
NSArray *viewControllers = #[self.currentViewController];
//changed currentViewController to self.currentViewController
NSUInteger indexOfCurrentViewController = [self.modelController indexOfViewController:self.currentViewController];
if (indexOfCurrentViewController == 0 || indexOfCurrentViewController % 2 == 0) {
UIViewController *nextViewController = [self.modelController pageViewController:self.pageViewController viewControllerAfterViewController:self.currentViewController];
viewControllers = #[self.currentViewController, nextViewController];
} else {
UIViewController *previousViewController = [self.modelController pageViewController:self.pageViewController viewControllerBeforeViewController:self.currentViewController];
viewControllers = #[previousViewController, self.currentViewController];
}
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
return UIPageViewControllerSpineLocationMid;
}
#end
What is it you want to prevent? Do you want to prevent rotation? If that is what you want, modify the shouldAutorotateToInterfaceOrientation return value in the RootViewController.m implementation file.
When I did this, the App was able to keep the same page (month) even after rotating the device. I used the simulator and tried on both iPhone and iPad. On the iPad, in landscape mode, it showed two months at a time, but then when rotated back to portrait, still kept the first of the two months that was displayed. This was when I incremented to June. I used the default project without changing a line of code.
Today I found out that in my app I could just use the following to remove the bug (but I have no clue why).
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
...
self.pageViewController.view.hidden = YES;
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
self.pageViewController.view.hidden = NO;
}

Application unit testing in IOS

I am testing an application in IOS5 using OCUnit. Before posting my problem I read all the relevant posts here as much I could. It really helped. I am now facing the problem below ,which I tried to narrate as clearly as possible.
My application has a login screen which is nothing but a view controller say: initialController. The root controller of my app delegate is the Navigation controller. The property initWithRootViewController of the Navigation controller is set with this initialController.
Now after logging in , the application loads another controller and I want to do unit testing in that controller without having to go through this login process.
Post login, another controller say PostloginController gets loaded, this controller's Navigation item is customized with 2 button's say: button1 and button2.
These buttons are added as the subviews of UIBarButtonItem and this UIBarButtonItem is set as the rightBarButtonItem of the PostloginController.navigationItem.rightBarButtonItem.(pseudo code)
finally PostLoginController is pushed in the Navigation controller
navigationcontroller pushviewcontroller:postLoginController.(pseudo code)
I have to write unit test code which on button1's UIControlEventTouchUpInside should launch another controller say :Newcontroller.
Loading this new controller on button1's event complete one test case.
My problem is that I don't get the subview of UIBarButtonItem which should be 2 buttons. The log show me there is one controller in the Navigation Controller and only one subview. My code is as follows:
- (void)setUp
{
[super setUp];
// Set-up code here.
self.appDelegate = (MYAppDelegate*)[[UIApplication sharedApplication] delegate ];
self.navigationController = (UINavigationController *)self.appDelegate.window.rootViewController;
}
- (void)testAppDelegate
{
STAssertNotNil(self.appDelegate, #"Cannot find the application delegate");
NSArray *tempArray = [self.navigationController viewControllers];
NSLog(#"Number of controllers in navigationController = %i", [tempArray count]);
}
- (void) testButton1
{
//self.myController = (PostLoginController*)self.navigationController.topViewController;
UIBarButtonItem *barButtonItem = self.navigationController.topViewController.navigationItem.rightBarButtonItem;
UIView *customView = barButtonItem.customView;
NSArray *subviews1 = customView.subviews;
NSLog (# "Got subviews");
NSLog(#"Number of subviews = %i", [subviews1 count]);
if ([subviews1 count] == 0)
{
NSLog (# "no subviews");
}
for (UIView* view in subviews1)
{
NSLog(#"%#", view);
if([view isKindOfClass:[UIButton class]])
{
UIButton *btn = (UIButton*)view;
NSLog (# " UIButton parsed");
// Check if Button1 clicked.
NSData *data1=UIImagePNGRepresentation([btn backgroundImageForState:UIControlStateNormal]);
NSData *data2=UIImagePNGRepresentation([UIImage imageNamed:#"BUTTON1.png"]);
if([data1 isEqualToData:data2]) // CHECKING IF BUTTON1 OR BUTTON2 PRESSED BY IMAGE SINCE THEY DONT HAVE ANY TAGS SET.
{
[btn sendActionsForControlEvents:(UIControlEventTouchUpInside)];
STAssertTrue([self.navigationController.visibleViewController isMemberOfClass: [NewController class]], #" NewController failed to load!"); //BUTTON1 CLICK SHOULD LAUNCH NEWCONTROLLER - COMPLETES ONE TEST CASE.
}
}
}
}

Reading touch events in a QLPreviewController

I've got a QuickLook view that I view some of my app's documents in. It works fine, but I'm having my share of trouble closing the view again. How do I create a touch event / gesture recognizer for which I can detect when the user wants to close the view?
I tried the following, but no events seem to trigger when I test it.
/------------------------ [ TouchPreviewController.h ]---------------------------
#import <Quicklook/Quicklook.h>
#interface TouchPreviewController : QLPreviewController
#end
//------------------------ [ TouchPreviewController.m ]---------------------------
#import "TouchPreviewController.h"
#implementation TouchPreviewController
- (id)init:(CGRect)aRect {
if (self = [super init]) {
// We set it here directly for convenience
// As by default for a UIImageView it is set to NO
UITapGestureRecognizer *singleFingerDTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSingleDoubleTap:)];
singleFingerDTap.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:singleFingerDTap];
[self.view setUserInteractionEnabled:YES];
[self.view setMultipleTouchEnabled:YES];
//[singleFingerDTap release];
}
return self;
}
- (IBAction)handleSingleDoubleTap:(UIGestureRecognizer *) sender {
CGPoint tapPoint = [sender locationInView:sender.view.superview];
[UIView beginAnimations:nil context:NULL];
sender.view.center = tapPoint;
[UIView commitAnimations];
NSLog(#"TouchPreviewController tap!" ) ;
}
// I also tried adding this
- (BOOL)gestureRecognizer:(UIGestureRecognizer *) gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*) otherGestureRecognizer {
return YES;
}
#end
Edit: For clarification, this is how I instantiate the controller:
documents = [[NSArray alloc] initWithObjects: filename , nil ] ;
preview = [[TouchPreviewController alloc] init];
preview.dataSource = self;
preview.delegate = self;
//set the frame from the parent view
CGFloat w= backgroundViewHolder.frame.size.width;
CGFloat h= backgroundViewHolder.frame.size.height;
preview.view.frame = CGRectMake(0, 0,w, h);
//refresh the preview controller
[preview reloadData];
[[preview view] setNeedsLayout];
[[preview view] setNeedsDisplay];
[preview refreshCurrentPreviewItem];
//add it
[quickLookView addSubview:preview.view];
Also, I've defined the callback methods as this:
- (NSInteger) numberOfPreviewItemsInPreviewController: (QLPreviewController *) controller
{
return [documents count];
}
- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index
{
return [NSURL fileURLWithPath:[documents objectAtIndex:index]];
}
Edit2: One thing i noticed. If I try making swiping gestures, I get the following message. This could shed some light on what is wrong/missing?
Ignoring call to [UIPanGestureRecognizer setTranslation:inView:] since
gesture recognizer is not active.
I think your example code is incomplete. It isn't clear how you are instantiating the TouchPreviewController (storyboard, nib file or loadView.)
I have never used the class so I could be way out in left field.
If you've already instantiated a UITapGestureRecognizer in the parent viewController, it is absorbing the tap events and they aren't passed on to your TouchPreviewController.
I would implement the view hierarchy differently by attaching the UITapGestureRecognizer to the parent viewController and handle presentation and unloading of the QLPreviewController there.
I think you might not have to subclass QLPreviewController by instantiating the viewController from a nib file.
When your parent viewController's UITapGestureRecognizer got an event you would either push the QLPreviewController on the navigation stack or pop it off the navigation stack when done.
Hope this is of some help.