QLPreviewController editing mode not working? - ios

Are you able to edit images with QLPreviewController?
For example, preview an image and crop it? If not, what is the editing property on QLPreviewController for? It doesn't seem to change anything. (Previewing files is working fine)
Here is an example:
QLPreviewController *previewController=[[QLPreviewController alloc]init];
previewController.delegate=self;
previewController.dataSource=self;
[previewController setCurrentPreviewItemIndex:selectedIndex];
[previewController setEditing:YES animated:YES];
[self presentModalViewController:previewController animated:YES];
Delegate methods:
- (id <QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
{
file = [folder.files objectAtIndex:index];
controller.title = file.name;
CustomQLPreviewItem *customQLPreviewItem = [[CustomQLPreviewItem alloc] init];
customQLPreviewItem.previewItemURL = [NSURL fileURLWithPath:file.uri];
customQLPreviewItem.previewItemTitle = file.name;
return customQLPreviewItem;
}
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller
{
return folder.file.count;
}

QLPreviewController does not support editing in the way you are thinking.
the editing property is actually inherited from UIViewController and from here:
UIViewController Class Reference
editing A Boolean value indicating whether the view controller
currently allows the user to edit the view contents.
#property(nonatomic, getter=isEditing) BOOL editing Discussion If YES,
the view controller currently allows editing; otherwise, NO.
If the view is editable and the associated navigation controller
contains an edit-done button, then a Done button is displayed;
otherwise, an Edit button is displayed. Clicking either button toggles
the state of this property. Add an edit-done button by setting the
custom left or right view of the navigation item to the value returned
by the editButtonItem method. Set the editing property to the initial
state of your view. Use the setEditing:animated: method as an action
method to animate the transition of this state if the view is already
displayed.
Availability Available in iOS 2.0 and later. See Also –
setEditing:animated: – editButtonItem Related Sample Code BonjourWeb
iPhoneCoreDataRecipes Declared In UIViewController.h

Related

setting rightbarbuttonitem in navigation item to nil doesn't disappear

I have an object with the class FSDDropdownPicker (a dropdown menu) and I want to edit one of the entries in my dropdown menu. Upon doing so I change the object to nil, and the right bar button item to nil yet the old dropdown menu remains even after instantiating the new dropdown and adding it to the right bar button item.
if(_picker){
// _picker.tableView.delegate = nil;
// _picker.tableView.dataSource = nil;
// _picker.delegate = nil;
self.navigationItem.rightBarButtonItem = nil;
// [_picker removeFromSuperview];
// _picker.view
}
_picker = [self.navigationItem addDropdownPickerWithOptions:[arr copy]];
_picker.delegate = self;
I also have functionality such that if the menu becomes empty then I erase the dropdown completely and just do
if([api.myGroups count]==0){
self.navigationItem.rightBarButtonItem = nil;
return;
}
However my rightBarButtonItem remains unchanged. Added Notes: I'm also using AMSlideMenu if that makes a difference but it really shouldn't.
Even after re-adding new picker, the FSDDropdownPicker keeps the old tableView still in the view hierarchy, so try calling [_picker removeFromSuperview]; before adding a new one.
Also there's no need to call [self.view setNeedsDisplay]; and nil the delegates and data source. Seems you just have to assign it again.
Additionally, the line self.navigationItem.rightBarButtonItem = _picker; is redundant as the category method addDropdownPickerWithOptions: on navigationItem already assigns the newly created picker to navigationItem.
EDIT: My bad, you need to call this code before creating new picker:
for (UIView *view in self.navigationController.navigationBar.superview.subviews) {
if ([view isKindOfClass:[UITableView class]]) {
[view removeFromSuperview];
}
}
Unfortunately the library doesn't take care of this by itself, so you either do it this way or create a pull request with a fix for the FSDDropdownPicker library.
EDIT EDIT:
If you're not using CocoaPods, you could try to put the table view and options definition in the header file - not a nice solution, but probably the easiest for you now. Move this
#property (strong, nonatomic) UITableView *tableView; and this #property (strong, nonatomic) NSArray *options; line to FSDDropdownPicker.h and you won't have to create new picker instance every time you want to add/delete an item. Just add/delete an item to options and reload the table view.

Where and how to set protocol delegate when slide out menu implemented in navigation controller?

Imagine you have the following storyboard scheme:
Slide out menu UITableView and feed UITableView embedded in Nav controllers
You want to filter out your feed based on the content of the cell that is tapped in the slide out menu.
As you can see on the storyboard scheme I shared above, you want to do this dynamically using only one segue whose identifier is:
#"Filter_MenuItem"
You declared the following protocol in the slide out menu view controller:
// SlideOutMenuTableViewController.h
#import <UIKit/UIKit.h>
#import "SlideOutMenuItems.h"
#import "SlideOutMenuCellTableViewCell.h"
#protocol filterFeed <NSObject>
-(void)filterFeedFromSlideOutItemTapped:(NSString *)slideOutItemStringData; //String to pass slideOut menu item string back to feed
#end
#interface SlideOutMenuTableViewController : UITableViewController
#property(nonatomic,assign)id<filterFeed> stringDelegate;
#end
And you implement the protocol method filterFeedFromSlideOutItemTapped:in your feed view controller:
#pragma mark - Filter feed based on slideout menu item tapped
-(void)filterFeedFromSlideOutItemTapped:(NSString *)slideOutItemStringData
{
NSLog(#"filterFeedFromSlideOutItemTapped just started");
if (!(slideOutItemStringData == (nil)))
{//Pass self.feed.flames + filtering string ==> filtered flames
NSMutableArray* allFlames = [[NSMutableArray alloc] initWithArray:self.feed.flames];
NSString *flameRelationFilter = slideOutItemStringData;
NSPredicate* sortFlames = [NSPredicate predicateWithFormat:#"(kFlameRelation like %#)", flameRelationFilter];
NSArray* filteredFlames = [allFlames filteredArrayUsingPredicate:sortFlames];
NSLog(#"The filter flames are %#", filteredFlames);
NSMutableArray *mutableFilteredFlames = [filteredFlames mutableCopy];
self.filteredFeed.flames = mutableFilteredFlames;
[self.tableView reloadData];
}
}
You make sure to synthesize your delegate in the implementation of your slide out menu view controller: #synthesize stringDelegate;
And before you call your protocol method in the implementation of your slide out menu view controller:
[stringDelegate filterFeedFromSlideOutItemTapped:[self.slideOutMenuItems menuItemAtIndex:indexPath.row]];
you know that, first, you need to initialize your protocol delegate:
instanceOfSlideOutMenuTableViewController.stringDelegate=self;
Generally, you do that successfully in a "prepareForSegue" method. But this time it's more complicated since you implemented a slide out menu (you actually didn't reinvent the wheel, you picked your implementation here).
Where and how should you initialize your protocol delegate?
Since you use SWRevealViewController which adds other controllers as child controllers, you can directly access feed controller from menu using parentViewController.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// get reveal controller
SWRevealViewController *revealController = (SWRevealViewController *)self.navigationController.parentViewController;
// get content controller
UINavigationController *feedNavController = (UINavigationController *)revealController.frontViewController;
// rename "FeedController" to whatever class you use for front controller
FeedController *feedController = (FeedController *)feedNavController.topViewController;
// get menu item
NSString *menuItem = [self.slideOutMenuItems menuItemAtIndex:indexPath.row];
// pass selected item to feed controller
[feedController filterFeedFromSlideOutItemTapped:menuItem];
}
as i seen your storyboard you used SWRevealViewController to add the slider in your main bundle . you added a tableview to show the list of menu . so use "tableviewdidSelect" method to add your view controller to SwWRevealMain view that added your main view on the main Screen.

how to get the a property value when dismissing uipopover

I am using a uipopover to present a mini number pad to the user when they enter a textfield on my main view controller.
when they enter numbers using the number pad, i save the entry into a nsstring property that I've named keypadvalue.
there is an unwind segue wired to a done button on the popover which fires the following code.
- (IBAction)doneWithKeyboard:(UIStoryboardSegue *)segue
{
NSLog(#"unwind");
if ([segue.sourceViewController isKindOfClass:[KeyPopupViewController class]])
{
KeyPopupViewController *popOver2 = segue.sourceViewController;
activeField.text =popOver2.keypadValue;
}
}
the activetextfield on my main view controller then gets updated to the kepadvalue, and this all works fine.
my problem now is that i want the activetextfield to update the same way if the user presses outside the uipopover, and it dismisses without firing the unwind segue.
i thought i might use the following to perform the update when the popover dismisses
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
activeField.text = controller.keypadValue;
return YES;
}
unfortunately despite multiple attempts i can't get the property to return a value it is always null even though the method fires as expected.
how should i recover the property value from the popover using this or another method?
i am obviously doing something wrong
can anyone advise
thanks
It should help:
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
[self.view endEditing:YES];
activeField.text = controller.keypadValue;
return YES;
}

iOS - Prompt When Navigating From View

I have a UINavigationController inside a UITabBarController. The navigationcontroller has a UITableView and a form for editing items. The problem is that if a tab is tapped during editing, the form is just cleared and the user is dumped back to the UITableView.
Is there a way I can add a prompt to confirm navigation away from the edit view?
First, declare a BOOL in your .h to store the editing state. Also declare a temporary variable we will use later for storing the selected row.
BOOL isEditing;
NSUInteger selectedRow;
In your viewDidLoad, initialize the boolean to NO
- (void)viewDidLoad {
// initialization
isEditing = NO;
[super viewDidLoad];
}
You can then conform your view controller to UITextFieldDelegate and UIAlertViewDelegate. The text field delegate allows the controller to receive callbacks when editing ends and begins for the text fields and the alert view delegate allow it to receive callbacks when an alert view is dismissed.
#interface MyController : UIViewController <UITextFieldDelegate, UIAlertViewDelegate>
You then also need to set all the text field's delegates to be assigned to the controller. So in your cellForRowAtIndexPath when you add the text fields, just add this:
textField.delegate = self;
Once you have this, you are all set up to receive callbacks from the text field - so now implement the following two methods like so:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
isEditing = YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
isEditing = NO;
}
Now the key here is to make a separate method for pushing the next view, so just do something like this (like you would normally when the table view row is selected):
- (void)showNextView {
// in this method create the child view controller and push it
// like you would normally when a cell is selected
// to get the selected row, use the `selectedRow` variable
// we declared earlier.
}
You now need to implement the table view callback when the user selects a row - in this method we test if they are editing and show them a prompt if they are. If they aren't, we go to the next view.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedRow = [indexPath row];
if (isEditing) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Continue Editing?"
message:#"Continue Editing or discard edits"
delegate:self
cancelButtonTitle:#"Discard"
otherButtonTitles:#"Continue"];
[alert show];
[alert release];
return;
}
[self showNextView];
}
Finally, we need to implement the alert view delegate callback for when the alert view is dismissed:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex != [alertView cancelButtonIndex]) return; // stay editing
[self showNextView];
}
Hope that all makes sense and is helpful to you!
Since you are using a UINavigationController, if you are pushing this "form" onto the stack you could set
#property(nonatomic) BOOL hidesBottomBarWhenPushed
That way the tab bar would be hidden until they are done with the form.
I solved this eventually by using a custom UIBarButtonItem which looks like a back arrow.

UISearchDisplayController Without Dimming?

I am writing a SplitView iPad app. Inside the DetailViewController, there's a little view that contains a UITableView and a UISearchBar and its controller. This view does not represent the whole screen space reserved for the DetailViewController. Actually, it uses just half of it. There's an UIImageView on the other half.
And this is where trouble comes in: every time I use the search bar, the displaycontroller (I assume) dims everything present inside the DetailViewController, including the image view. That is not consistent with what someone would expect when running the app. Is there any way to set the frame to be dimmed? Or at least disable dimming for good?
Thanks in advance.
You are correct that it is the UISearchDisplayController that is managing the "dimming" effect that you're seeing.
What the UISearchDisplayController is doing is adding a UIControl as a subview to the view of the searchContentsController (a property of UISearchDisplayController), which is likely your detail-view controller. This UIControl is just an alpha'd view with a gray background. It seems to have a touch-up-inside event handler that ends searching when tapped.
To constrain the dimming effect to your sub-view of the detail-view, you need to do three things. (I'm assuming your detail-view-controller is defined via a xib. If not, these steps can be done in code too.)
1) add a new UIViewController to your detail-view-controller xib. Attach this new view-controller to an IBOutlet of your detail-view-controller. In my example I call this "_searchAreaViewController". This is important, even if you wont ever access the view controller (but remember, you'll have to release it at some point)
#interface DetailViewController : UIViewController <UIPopoverControllerDelegate, UISplitViewControllerDelegate, UITableViewDelegate, UITableViewDataSource> {
UIPopoverController *popoverController;
UIToolbar *toolbar;
id detailItem;
UILabel *detailDescriptionLabel;
IBOutlet UIViewController* _searchAreaViewController;
}
2) make the containing view for your search area the view of this new view-controller. To do this, use Interface Builder to set a new referencing outlet for this view by dragging the outlet to the searchAreaViewController and selecting the "view" outlet. You must have a containing view - it should be a subview of your detail-view, and it should contain the UISearchBar and likely your UITableView.
3) make the searchContentsController property of the UISearchDisplayController refer to this new view controller instead of the detail-view-controller. This can only be done via Interface Builder as the property is read-only (IB has some magic to make this work?) If you need to do this step via code you'll have to subclass the UISearchDisplayController and return the correct value from a property override of "searchContentsController".
I made a sample app to demonstrate this and the only line of code I had to add to the SplitView template was the one listed in step 1 above. Everything else was just adding the views/controllers and connecting them properly in IB.
good luck!
iOS 8+
[[UIView appearanceWhenContainedInInstancesOfClasses:#[NSClassFromString(#"UISearchDisplayControllerContainerView")]] setHidden:YES];
iOS 7
[View appearanceWhenContainedIn:NSClassFromString(#"UISearchDisplayControllerContainerView"), nil] setHidden:YES];
I know, that UISearchDisplayController is deprecated for now, but if you still need to use it, you can solve your issue with one line of code perfectly. Add it to viewDidLoad method.
Could you clarify what you mean by "use the search bar" and "dims everything present"? I interpret what you wrote in such a way that the keyboard pops up when you are about to enter text in the text field of the search bar. And that at this point the detail view is dimmed out, preventing user interaction.
The cause is that the search bar implements a modal dialog which prevents user interaction with the view as long as the keyboard is shown. Unfortunately, there doesn't seem to be any way to configure the search bar to prevent this behavior. On the other hand I am not sure that the user won't expect this behavior since search bars are modal consistently and behave like this in general under iOS.
I have tried two work-arounds:
1.) There is a property of the UIViewController called modalPresentationStyle which produces exactly the behavior you describe if it has the value UIModalPresentationFormSheet ("All uncovered areas are dimmed to prevent the user from interacting with them.", see the Apple documentation). But setting this property to a different values does not change the result (at least for me it didn't work).
2.) You would need to write your own non-modal search bar replacement since a standard UITextField is non-modal and thus does not dim out any other UI elements. This approach works, but you might need a little more work to make it look like a "regular" search bar. But, again, since this search bar behaves differently from the modal normal search bars in iOS this might not really be what the users expect.
I know I am late and this is a horrible idea here, but 'setHidden:No' did not work for me.
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
BOOL hasBeenremoved = NO;
hasBeenremoved = [[[[NSThread mainThread] threadDictionary] objectForKey:#"hasBeenremoved"] boolValue];
if (hasBeenremoved)
{
UIView* dimmingView = nil;
dimmingView = [[[NSThread mainThread] threadDictionary] objectForKey:#"dimmingView"];
UIView* dimmingViewSuperView = nil;
dimmingViewSuperView = [[[NSThread mainThread] threadDictionary] objectForKey:#"dimmingViewSuperView"];
[dimmingViewSuperView addSubview:dimmingView];
[[[NSThread mainThread] threadDictionary] setObject:#NO forKey:#"hasBeenremoved"];
}
if ([searchText length] == 0 || [searchText isEqualToString:#""] )
{
[searchBar becomeFirstResponder];
[[[self primarySearchDisplayController] searchResultsTableView] reloadData];
[[[self primarySearchDisplayController] searchResultsTableView] setHidden:NO];
for( UIView *subview in self.view.subviews )
{
if([subview isMemberOfClass:[UIControl class]] ||
([[[subview class] description] isEqualToString:#"UISearchDisplayControllerContainerView"]))
{
for(UIView *subView2 in subview.subviews)
{
for(UIView *subView3 in subView2.subviews)
{
if (subView3.alpha < 1)
{
if ([[[subView3 class] description] isEqualToString:#"_UISearchDisplayControllerDimmingView"])
{
[[[NSThread mainThread] threadDictionary] setObject:subView3 forKey:#"dimmingView"];
[[[NSThread mainThread] threadDictionary] setObject:subView3.superview forKey:#"dimmingViewSuperView"];
[[[NSThread mainThread] threadDictionary] setObject:#YES forKey:#"hasBeenremoved"];
[subView3 removeFromSuperview];
}
}
}
}
}
}
}
}

Resources