最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】关于iOS/iPhone中的文件选择对话框,用于用户去选择图片等文件

iOS crifan 4577浏览 0评论

【背景】

在折腾:

给Your Second iOS App:BirdWatching添加支持用户自定义图片

的过程中,需要支持用户选择图片,所以需要找到iPhone/iOS中,如何跳出相应的文件选择对话框,然后支持用户选择图片文件。

 

【解决过程】

1.结果找了一下,看到:

open file dialog in iOS?

中说,iOS为了不让用户关心这些,故意隐藏了文件系统。

2. 后来从这里:

iphone中有没有选择本地文件的对话框

看到了相关的解释:

iPhone的程序只能访问对应程序文件夹里的资源,也即所谓“沙盒”的限制。
如果要访问系统图片库中的文件需要使用UIImagePickerController。
你要的选择效果需要自己来写,具体的文件操作请参考一下NSFileManager吧。

所以,就去找UIImagePickerController,然后就去去学习官网的解释:

UIImagePickerController Class Reference

了。

3.在写代码过程中,还遇到一个找不到类的方法的问题,后来参考别人代码才搞懂,详细折腾过程参见:

【已解决】iOS中,某个类(UIImagePickerController)的实例变量,找不到其某个方法(isSourceTypeAvailable)

4. 参考UIImagePickerController Class Reference去写代码,想要显示选择图片的对话框,写出了代码:

    self.imgPickerController = [[UIImagePickerController alloc] init];
    
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum])
    {
        NSArray *availableMediaTypeArr = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
        
        self.imgPickerController.mediaTypes = availableMediaTypeArr;
        [self presentViewController:self.imgPickerController animated:YES completion:NULL];
    }

结果运行时候出错:

2012-09-10 13:41:00.077 BirdWatching[687:11603] *** Assertion failure in -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:], /SourceCache/UIKit_Sim/UIKit-1914.84/UIWindowController.m:188
2012-09-10 13:45:42.968 BirdWatching[687:11603] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempting to begin a modal transition from <UINavigationController: 0x6ddd150> to <UIImagePickerController: 0x6df0b70> while a transition is already in progress. Wait for viewDidAppear/viewDidDisappear to know the current transition has completed'
*** First throw call stack:
(0x14b2022 0x1024cd6 0x145aa48 0xb1e2cb 0x46d648 0x255857 0x2559bc 0x5062 0x24ea1e 0x24dfec 0x274f1d 0x25f1cb 0x275df1 0x275ea9 0x46f508 0x22c401 0x22d08b 0x46ed6c 0x255857 0x2559bc 0x2559fc 0x5bdf4a 0x5b24d0 0x14b3e99 0x18a14e 0x3c8a0e 0x14b3e99 0x18a14e 0x18a0e6 0x230ade 0x230fa7 0x230266 0x1af3c0 0x1af5e6 0x195dc4 0x189634 0x16c9ef5 0x1486195 0x13eaff2 0x13e98da 0x13e8d84 0x13e8c9b 0x16c87d8 0x16c888a 0x187626 0x273d 0x26a5 0x1)
terminate called throwing an exception(lldb) 

看来是显示界面的切换transition过程中,出错了。

5.后来想了想,其实此处需要实现的是,对于图片,点击对应的图片的话,然后再弹出对应的选择图片的对话框。

所以,首先是要响应点击对应的点击Image View的事件才可以。

不过,官网UIImageView Class Reference中的解释,只说到需要把userInteractionEnabled设置为True,对此,我已经在storyboard中选中了 User Interaction Enabled:

Image View select User Interaction Enabled

但是接下来,到底如何获得点击图片的事件,却还是不懂。

6.然后去搜了搜,然后找到:

click any UIImage and open an UIImageView in objective-c

怎么让一个UIImageView响应点击事件呢?

大概看懂了,是通过获得鼠标点击的手势来实现的。

7.但是问题来了,我之前通过之前拖放一个UIImageView到UITableViewCell中,但是由于image和highlightedImage没有设置,是空的,所以不显示。

而之所以没有设置图片的原因是,对于iOS模拟器来说,不知道从哪里找到图片。

8。现在的想法是,把某个图片当做默认的BirdImage显示的图片,其他的,提供选择自定义。

所以,希望把某个图片集成到iOS程序内部中,这样可以直接引用了。

关于如何集成图片到iOS项目中,并显示,折腾过程参考:

【已解决】给iOS项目中添加图片,并通过UIImageView引用和显示该UIImage图片

9.经过折腾,终于实现了添加图片到iOS模拟器中,详情参考:

【已解决】如何添加图片到iOS模拟器(iOS Simulator)中的Photos(即Album)

这样,后续代码去调用窗口,才能有图片供显示,供用户选择。

10.下面接着去添加代码支持,点击图片,然后可以跳出(图片选择)对话框,选择图片。

然后先去学习了:UITapGestureRecognizer Class Reference,然后写了代码,结果运行出错,解决过程参考:

【已解决】iOS程序出错:[AddSightingViewController handleImageTap]: unrecognized selector sent to instance 0x6d97d20

最后的可以运行的代码是:

- (void)viewDidLoad
{
...
    self.imgPickerController = [[UIImagePickerController alloc] init];
    

    
    UITapGestureRecognizer *imgTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleImageTap:)];
    imgTap.numberOfTapsRequired = 1;
    imgTap.numberOfTouchesRequired = 1;
    
    [self.birdImageView addGestureRecognizer:imgTap];
}

//handle the tap to image
-(void)handleImageTap:(UITapGestureRecognizer *)sender{
    
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum])
    {
        NSArray *availableMediaTypeArr = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
        
        self.imgPickerController.mediaTypes = availableMediaTypeArr;
        [self presentViewController:self.imgPickerController animated:YES completion:NULL];
    }
}

11.但是,此时,也只是可以运行到handleImageTap函数里面而已,具体如何打开图片选择框,还是没有实现。

所以,继续去学习如何切换界面,打开图片选择框。

结果发现,上述代码,其实是已经可以正常工作了,可以跳转到对应的Album界面,可以浏览对应图片了:

can choose but not custom it

只是暂时由于没有实现函数,所以选择了图片后,又调回原有界面而已。

12.现在去添加代码实现将选中的图片,保存为对应的Bird的图片。

关于如何获得选择的图片,参考官网的:

UIImagePickerController Class Reference

中的解释,是需要实现对应的delegate的:UIImagePickerControllerDelegate Protocol Reference.

所以就去添加代码实现对应的delegate。

然后参考:

OverlayViewController.m

添加了.h中的delegate声明后,.m中去实现代码:

#pragma -
#pragma UIImagePickerControllerDelegate
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    //set selectd img to bird img
    
    //get selected image
    UIImage *selectedImg = [info valueForKey:UIImagePickerControllerOriginalImage];
    self.birdImageView.image = selectedImg;
}

但是却是,选中一个图片后,代码却没有执行到此函数。

然后又是才想起来,忘了设置delegate了。。。。

13.然后设置delegate时又出现错误,最后也解决了,折腾过程参考:

【已解决】iOS程序中,设置delegate时候,出现警告:Assigning to ‘id<UINavigationControllerDelegate,UIImagePickerControllerDelegate>’ from incompatible type ‘AddSightingViewController *const __strong’

14.可以正常设置delegate后,就可以正常执行handleImageTap,然后跳转到对应的选择图片的界面,最后选择图片后,可以执行

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

去设置所选图片给对应的变量了,但是还存在一个问题,所选图片后,Album界面没有消失,需要手动点击Cancel,才能回到原先界面:

pic can show selected

15.现在继续去折腾,希望点击选择一个图片后,对应的页面也跳转回来到原先界面。

即,点击选择一个图片后,当前Album界面消失,界面回到原先的UITableView界面。

然后搜到:

iphone 怎么使用图片选取器 UIImagePickerController

然后看到有个函数dismissModalViewControllerAnimated,就去搜了下,找到– dismissModalViewControllerAnimated:

dismissModalViewControllerAnimated:

Dismisses the view controller that was presented by the receiver. (Deprecated. Use dismissViewControllerAnimated:completion: instead.)

。。。

所以,再去看– dismissViewControllerAnimated:completion:

dismissViewControllerAnimated:completion:

Dismisses the view controller that was presented by the receiver.

– (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion

Parameters
flag

Pass YES to animate the transition.

completion

A block called after the view controller has been dismissed.

Discussion

The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, it automatically forwards the message to the presenting view controller.

If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.

If you want to retain a reference to the receiver’s presented view controller, get the value in the presentedViewController property before calling this method.

The completion handler is called after the viewDidDisappear: method is called on the presented view controller.

Availability
  • Available in iOS 5.0 and later.
Declared In

UIViewController.h

所以,意思很明显,就是让当前显示的画面消失。

然后就去添加dismissModalViewControllerAnimated的代码,变成:

#pragma -
#pragma UIImagePickerControllerDelegate
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    //set selectd img to bird img
    
    //get selected image
    UIImage *selectedImg = [info valueForKey:UIImagePickerControllerOriginalImage];
    self.birdImageView.image = selectedImg;
    [self dismissModalViewControllerAnimated:YES];
}

然后运行结果就是达到效果了,点击一个图片后,可以自动消失掉Album的界面,回到原先界面:

can dismiss old ui

 

至此,算是终于搞定了用户自定义选择图片的问题。

 

【总结】

想要实现用户自定义选择图片的问题。

此处的总的逻辑是:

1.对于已经显示的某个图片,点击该图片

2. 通过UITapGestureRecognizer实现了能检测到Tap单击的动作,然后调用对应的自定义的函数

3. 在函数中,使用UIImagePickerController去打开iOS(模拟器中的)相册Album

4. 然后用户可以选择自己需要的某张图片,单击图片会触发对应的事件

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

5. 然后在该函数中,可以获得所选图片,进行你所需要的相应的处理,然后调用dismissModalViewControllerAnimated将显示窗口切换回原来的界面,即可。

转载请注明:在路上 » 【已解决】关于iOS/iPhone中的文件选择对话框,用于用户去选择图片等文件

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
83 queries in 0.167 seconds, using 22.12MB memory