iOS, UIImagePickerController, is there a way to de

2019-09-09 14:10发布

Xcode 7.3, iOS 9.3.1

I want to use two custom overlay views for when the user is about to take a picture and after while editing the picture. To change the overlay I would like to know if there is a callback method from the UIImagePickerControllerDelegate that will let me know when the user starts editing the picture, or when the user has tapped the take picture button.

The only methods I know of are:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

I have looked here: UIImagePickerController with cameraOverlayView focusses when button in overlay is tapped, How to know I tap "taking photo button" with UIImagePicker and iOS - Taking A Picture After Button Tap in UIImagePickerController CustomOverlayView.

Or perhaps there is a way to get the tap event from the standard button by adding an observer.

Please help! Thanks in advance.

3条回答
不美不萌又怎样
2楼-- · 2019-09-09 14:31

UIImagePickerControllerDelegate is quite poor but you can handle it by adding an observer:

Swift 3:

NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidCaptureItem"), object:nil, queue:nil, using: { note in
    //Do something
})

Objective-C:

[[NSNotificationCenter defaultCenter] addObserverForName:@"_UIImagePickerControllerUserDidCaptureItem" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
    //Do something
}];
查看更多
够拽才男人
3楼-- · 2019-09-09 14:32

Xcode 8.2.1, iOS10.2.1

Before implementing please read the solution for earlier version to understand the basics. Thanks! The problem was that some of the names for various subviews have changed from iOS 9.3.1 to iOS 10.2.1.

Here is the complete code (see below where to insert), that replaces "//Code goes here" below:

for (UIView *subviewImagePickerControllerView in self.imagePickerController.view.subviews)
{
    if ([subviewImagePickerControllerView.class.description isEqualToString:@"UINavigationTransitionView"])
    {
        for (UIView *subviewUINavigationTransitionView in subviewImagePickerControllerView.subviews)
        {
            if ([subviewUINavigationTransitionView.class.description isEqualToString:@"UIViewControllerWrapperView"])
            {
                for (UIView *subviewUIViewControllerWrapperView in subviewUINavigationTransitionView.subviews)
                {
                    if ([subviewUIViewControllerWrapperView.class.description isEqualToString:@"CAMCameraViewControllerContainerView"])
                    {
                        for (UIView *subviewCAMCameraViewControllerContainerView in subviewUIViewControllerWrapperView.subviews)
                        {
                            if ([subviewCAMCameraViewControllerContainerView.class.description isEqualToString:@"CAMViewfinderView"])
                            {
                                for (UIView *subviewCAMViewfinderView in subviewCAMCameraViewControllerContainerView.subviews)
                                {
                                    if ([subviewCAMViewfinderView.class.description isEqualToString:@"CAMBottomBar"])
                                    {
                                        for (UIView *subviewCAMBottomBar in subviewCAMViewfinderView.subviews)
                                        {
                                            if ([subviewCAMBottomBar.class.description isEqualToString:@"CUShutterButton"] && [subviewCAMBottomBar.class isSubclassOfClass:[UIButton class]])
                                            {
                                                UIButton *shutterButton = (UIButton *)subviewCAMBottomBar;

                                                [shutterButton addTarget:self action:@selector(touchUpInsideCMKShutterButton) forControlEvents:UIControlEventTouchUpInside];
                                            }
                                            else
                                            {
                                                nil;
                                            }
                                        }
                                    }
                                }

                            }
                            else if ([subviewCAMCameraViewControllerContainerView.class.description isEqualToString:@"PLCropOverlay"])
                            {
                                for (UIView *subviewPLCropOverlay in subviewCAMCameraViewControllerContainerView.subviews)
                                {
                                    if ([subviewPLCropOverlay.class.description isEqualToString:@"PLCropOverlayBottomBar"])
                                    {
                                        for (UIView *subviewPLCropOverlayBottomBar in subviewPLCropOverlay.subviews)
                                        {
                                            if ([subviewPLCropOverlayBottomBar.class.description isEqualToString:@"PLCropOverlayPreviewBottomBar"])
                                            {
                                                for (UIView *itemPLCropOverlayPreviewBottomBar in subviewPLCropOverlayBottomBar.subviews)
                                                {
                                                    if ([itemPLCropOverlayPreviewBottomBar.class isSubclassOfClass:[UIButton class]])
                                                    {
                                                        UIButton *buttonPLCropOverlay = (UIButton *)itemPLCropOverlayPreviewBottomBar;

                                                        if ([buttonPLCropOverlay.titleLabel.text isEqualToString:@"Retake"])
                                                        {
                                                            UIButton *retakeButton = buttonPLCropOverlay;

                                                            [retakeButton addTarget:self action:@selector(touchUpInsideButtonRetake) forControlEvents:UIControlEventTouchUpInside];
                                                        }
                                                        else
                                                        {
                                                            nil;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        nil;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                nil;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        nil;
                                    }
                                }
                            }
                            else
                            {
                                nil;
                            }
                        }
                    }
                    else
                    {
                        nil;
                    }
                }
            }
            else
            {
                nil;
            }
        }
    }
    else
    {
        nil;
    }
}

Xcode 7.3, iOS9.3.1

I had to get this working, so I spent a lot of time figuring this out.

The gist of it is, I drill down the view hierarchy after the UIImagePickerController was presented, looking for CMKShutterButton and the retake button with a title of "Retake", then I attach a selector to the buttons' action, like so...

[shutterButton addTarget:self action:@selector(touchUpInsideCMKShutterButton) forControlEvents:UIControlEventTouchUpInside];

[retakeButton addTarget:self action:@selector(touchUpInsideButtonRetake) forControlEvents:UIControlEventTouchUpInside];

Drop the code below into the completion block that is called after your image picker is presented:

[self presentViewController:self.imagePickerController animated:true completion:^(void){

     //Code goes here

}

Here is the complete code, that replaces "//Code goes here" above:

for (UIView *subviewImagePickerControllerView in self.imagePickerController.view.subviews)
{
    if ([subviewImagePickerControllerView.class.description isEqualToString:@"UINavigationTransitionView"])
    {
        for (UIView *subviewUINavigationTransitionView in subviewImagePickerControllerView.subviews)
        {
            if ([subviewUINavigationTransitionView.class.description isEqualToString:@"UIViewControllerWrapperView"])
            {
                for (UIView *subviewUIViewControllerWrapperView in subviewUINavigationTransitionView.subviews)
                {
                    if ([subviewUIViewControllerWrapperView.class.description isEqualToString:@"PLImagePickerCameraView"])
                    {
                        for (UIView *subviewPLImagePickerCameraView in subviewUIViewControllerWrapperView.subviews)
                        {
                            if ([subviewPLImagePickerCameraView.class.description isEqualToString:@"CMKBottomBar"])
                            {
                                for (UIView *itemCMKBottomBar in subviewPLImagePickerCameraView.subviews)
                                {
                                    if ([itemCMKBottomBar.class.description isEqualToString:@"CMKShutterButton"] && [itemCMKBottomBar.class isSubclassOfClass:[UIButton class]])
                                    {
                                        UIButton *shutterButton = (UIButton *)itemCMKBottomBar;

                                        [shutterButton addTarget:self action:@selector(touchUpInsideCMKShutterButton) forControlEvents:UIControlEventTouchUpInside];
                                    }
                                    else
                                    {
                                        nil;
                                    }
                                }
                            }
                            else if ([subviewPLImagePickerCameraView.class.description isEqualToString:@"PLCropOverlay"])
                            {
                                for (UIView *subviewPLCropOverlay in subviewPLImagePickerCameraView.subviews)
                                {
                                    if ([subviewPLCropOverlay.class.description isEqualToString:@"PLCropOverlayBottomBar"])
                                    {
                                        for (UIView *subviewPLCropOverlayBottomBar in subviewPLCropOverlay.subviews)
                                        {
                                            if ([subviewPLCropOverlayBottomBar.class.description isEqualToString:@"PLCropOverlayPreviewBottomBar"])
                                            {
                                                for (UIView *itemPLCropOverlayPreviewBottomBar in subviewPLCropOverlayBottomBar.subviews)
                                                {
                                                    if ([itemPLCropOverlayPreviewBottomBar.class isSubclassOfClass:[UIButton class]])
                                                    {
                                                        UIButton *buttonPLCropOverlay = (UIButton *)itemPLCropOverlayPreviewBottomBar;

                                                        if ([buttonPLCropOverlay.titleLabel.text isEqualToString:@"Retake"])
                                                        {
                                                            UIButton *retakeButton = buttonPLCropOverlay;

                                                            [retakeButton addTarget:self action:@selector(touchUpInsideButtonRetake) forControlEvents:UIControlEventTouchUpInside];
                                                        }
                                                        else
                                                        {
                                                            nil;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        nil;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                nil;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        nil;
                                    }
                                }
                            }
                            else
                            {
                                nil;
                            }
                        }
                    }
                    else
                    {
                        nil;
                    }
                }
            }
            else
            {
                nil;
            }
        }
    }
    else
    {
        nil;
    }
} 

And here is the method I am attaching, which goes in the view controller that is presenting the image picker controller:

- (void)touchUpInsideCMKShutterButton
{
    NSLog(@"Take");
}

- (void)touchUpInsideButtonRetake
{
    NSLog(@"Re-take");
}

Hope this helps someone! Thanks.

查看更多
ら.Afraid
4楼-- · 2019-09-09 14:40

you could use the UINavigationControllerDelegate that you also have to implement when using UIImagePickerController. implementing the delegate method [...]didShowViewController[...] like this

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    NSLog(@"%@", [viewController class]);
}

produces the following output (using the simulator, choosing UIImagePickerControllerSourceTypePhotoLibrary as the sourceType and navigating like this: photo albums overview > specific album > editing specific photo):

2016-04-08 00:19:36.882 ImagePicker[44578:4705834] PUUIAlbumListViewController
2016-04-08 00:19:41.341 ImagePicker[44578:4705834] PUUIMomentsGridViewController
2016-04-08 00:19:47.929 ImagePicker[44578:4705834] PUUIImageViewController

hope that helps!

查看更多
登录 后发表回答