iOS 8 iPad에서 UIAactivityView 컨트롤러 충돌
저는 현재 Xcode 6(베타 6)으로 앱을 테스트하고 있습니다.UIAactivityViewController는 iPhone 장치 및 시뮬레이터와 잘 작동하지만 iPad 시뮬레이터 및 장치(iOS 8)와 충돌하고 다음 로그가 표시됩니다.
Terminating app due to uncaught exception 'NSGenericException',
reason: 'UIPopoverPresentationController
(<_UIAlertControllerActionSheetRegularPresentationController: 0x7fc7a874bd90>)
should have a non-nil sourceView or barButtonItem set before the presentation occurs.
iOS 7과 iOS 8 모두에서 아이폰과 아이패드에 대해 다음 코드를 사용하고 있습니다.
NSData *myData = [NSData dataWithContentsOfFile:_filename];
NSArray *activityItems = [NSArray arrayWithObjects:myData, nil];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:nil applicationActivities:nil];
activityViewController.excludedActivityTypes = @[UIActivityTypeCopyToPasteboard];
[self presentViewController:activityViewController animated:YES completion:nil];
다른 앱에서도 비슷한 충돌이 발생하고 있습니다.iOS 8의 UIActivityViewController에서 변경된 사항이 있습니까?제가 확인해봤지만 이것에 대해 아무것도 발견하지 못했습니다.
iPad에서 활동 보기 컨트롤러는 새로운 UIPopover Presentation Controller를 사용하여 팝업으로 표시되며, 다음 세 가지 속성 중 하나를 사용하여 팝업 프레젠테이션의 앵커 포인트를 지정해야 합니다.
앵커 포인트를 지정하려면 UIActivityController의 UIPopoverPresentationController에 대한 참조를 가져와 다음과 같이 속성 중 하나를 설정해야 합니다.
if ( [activityViewController respondsToSelector:@selector(popoverPresentationController)] ) {
// iOS8
activityViewController.popoverPresentationController.sourceView =
parentView;
}
에도 같은 했고, 는 이 .UIActivityViewController
는 아이패드를 사용해야 .UIPopoverController
iPhone과 iPad 모두에서 사용할 수 있는 코드는 다음과 같습니다.
//to attach the image and text with sharing
UIImage *image=[UIImage imageNamed:@"giraffe.png"];
NSString *str=@"Image form My app";
NSArray *postItems=@[str,image];
UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:postItems applicationActivities:nil];
//if iPhone
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
[self presentViewController:controller animated:YES completion:nil];
}
//if iPad
else {
// Change Rect to position Popover
UIPopoverController *popup = [[UIPopoverController alloc] initWithContentViewController:controller];
[popup presentPopoverFromRect:CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/4, 0, 0)inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
swift 4.2 / swift 5인 경우
func openShareDilog() {
let text = "share text will goes here"
// set up activity view controller
let textToShare = [text]
let activityViewController = UIActivityViewController(activityItems: textToShare, applicationActivities: nil)
activityViewController.excludedActivityTypes = [.airDrop]
if let popoverController = activityViewController.popoverPresentationController {
popoverController.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0)
popoverController.sourceView = self.view
popoverController.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)
}
self.present(activityViewController, animated: true, completion: nil)
}
2이. Swift 2.0의 문제입니다.UIActivityViewController
iPhone에서는 잘 작동했지만 iPad를 시뮬레이션할 때 충돌이 발생했습니다.
여기에 답변을 덧붙이고 싶습니다. 적어도 Swift 2.0에서는 if 문이 필요 없습니다.당신은 그냥 만들 수 있습니다.popoverPresentationController
선택적.
간단히 말하자면 sourceView, sourceRect 또는 barButtonItem만 사용할 수 있다는 답변이 받아들여지는 것처럼 보이지만, UIPopoverPresentationController에 대한 Apple의 문서에 따르면 다음 중 하나가 필요합니다.
- 막대 단추 항목
- sourceView 및 sourceRect
제가 연구하고 있던 특정한 예는 아래와 같습니다. 여기서 저는 다음을 포함하는 함수를 만들고 있습니다.UIView
및) 및 (sourceView 및 sourceRect의 경우) »String
(UIActivityView 컨트롤러의 유일한 활동 항목).
func presentActivityViewController(sourceView: UIView, activityItem: String ) {
let activityViewController = UIActivityViewController(activityItems: [activityItem], applicationActivities: [])
activityViewController.popoverPresentationController?.sourceView = sourceView
activityViewController.popoverPresentationController?.sourceRect = sourceView.bounds
self.presentViewController(activityViewController, animated: true, completion: nil)
}
에서 합니다. 가 iPhone, iPad(tvOS)를 말입니다. 장치가 지원하지 않는 경우popoverPresentationController
그것을 언급하는 두 줄의 코드는 근본적으로 무시됩니다.
iPad에서 작동하기 위해 필요한 것은 코드 두 줄을 추가하거나 barButtonItem을 사용하는 경우 한 줄만 추가하면 된다는 것입니다!
스위프트 코드를 사용하면서 아이폰/아이패드 등을 열심히 코딩하는 사람들을 많이 봅니다.
이것은 필요하지 않습니다. 언어 기능을 사용해야 합니다.다음 코드는 사용자가 UIBarButtonItem을 사용하고 iPhone과 iPad 모두에서 작동한다고 가정합니다.
@IBAction func share(sender: AnyObject) {
let vc = UIActivityViewController(activityItems: ["hello"], applicationActivities: nil)
vc.popoverPresentationController?.barButtonItem = sender as? UIBarButtonItem
self.presentViewController(vc, animated: true, completion: nil)
}
If 진술이나 다른 미친 것들이 어떻게 없는지 주목하세요.옵션 iPhone 은 0이 .vc.popoverPresentationController?
iPhone에서는 아무것도 하지 않습니다.
Xamarin.i를 사용한 솔루션OS.
이 예에서는 화면 캡처를 수행하고 이미지를 생성하며 사용자가 이미지를 공유할 수 있도록 합니다.iPad의 팝업은 화면 중앙에 위치합니다.
var activityItems = new NSObject[] { image };
var excludedActivityTypes = new NSString[] {
UIActivityType.PostToWeibo,
UIActivityType.CopyToPasteboard,
UIActivityType.AddToReadingList,
UIActivityType.AssignToContact,
UIActivityType.Print,
};
var activityViewController = new UIActivityViewController(activityItems, null);
//set subject line if email is used
var subject = new NSString("subject");
activityViewController.SetValueForKey(NSObject.FromObject("Goal Length"), subject);
activityViewController.ExcludedActivityTypes = excludedActivityTypes;
//configure for iPad, note if you do not your app will not pass app store review
if(null != activityViewController.PopoverPresentationController)
{
activityViewController.PopoverPresentationController.SourceView = this.View;
var frame = UIScreen.MainScreen.Bounds;
frame.Height /= 2;
activityViewController.PopoverPresentationController.SourceRect = frame;
}
this.PresentViewController(activityViewController, true, null);
Swift, iOS 9/10(UIPopover 컨트롤러가 더 이상 사용되지 않는 경우)
let activityViewController = UIActivityViewController(activityItems: sharingItems, applicationActivities: nil)
if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
if activityViewController.respondsToSelector(Selector("popoverPresentationController")) {
activityViewController.popoverPresentationController?.sourceView = self.view
}
}
self.presentViewController(activityViewController, animated: true, completion: nil)
스위프트 UI 버전
func presentActivityView(items: [Any]){
let activityController = UIActivityViewController(activityItems: items, applicationActivities: nil)
if UIDevice.current.userInterfaceIdiom == .pad{
activityController.popoverPresentationController?.sourceView = UIApplication.shared.windows.first
activityController.popoverPresentationController?.sourceRect = CGRect(x: UIScreen.main.bounds.width / 3, y: UIScreen.main.bounds.height / 1.5, width: 400, height: 400)
}
UIApplication.shared.windows.first?.rootViewController?.present(activityController, animated: true, completion: nil)
}
,면▁if▁▁show여.UIActivityViewController
를 UIBarButtonItem
다음 코드를 사용합니다.
activityViewController.popoverPresentationController?.barButtonItem = sender
그렇지 않은 경우, 예를 들어 다른 컨트롤을 사용하는 경우UIButton
다음 코드를 사용합니다.
activityViewController.popoverPresentationController?.sourceView = sender
activityViewController.popoverPresentationController?.sourceRect = sender.bounds
에서 설서에다까지UIPopoverPresentationController
:
var barButtonItem: UIBarButtonItem? { get set }
이 속성에 값을 할당하여 지정된 막대 단추 항목에 팝업을 고정합니다.표시되면 팝업의 화살표가 지정된 항목을 가리킵니다.또는 sourceView 및 sourceRect 속성을 사용하여 팝업에 대한 앵커 위치를 지정할 수 있습니다.
Swift에서 iPad용으로 이 문제를 해결하는 가장 좋은 방법은 제가 찾은 것처럼 하는 것입니다.
let things = ["Things to share"]
let avc = UIActivityViewController(activityItems:things, applicationActivities:nil)
avc.setValue("Subject title", forKey: "subject")
avc.completionWithItemsHandler = {
(s: String!, ok: Bool, items: [AnyObject]!, err:NSError!) -> Void in
}
self.presentViewController(avc, animated:true, completion:nil)
if let pop = avc.popoverPresentationController {
let v = sender as! UIView // sender would be the button view tapped, but could be any view
pop.sourceView = v
pop.sourceRect = v.bounds
}
스위프트 3:
class func openShareActions(image: UIImage, vc: UIViewController) {
let activityVC = UIActivityViewController(activityItems: [image], applicationActivities: nil)
if UIDevice.current.userInterfaceIdiom == .pad {
if activityVC.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
activityVC.popoverPresentationController?.sourceView = vc.view
}
}
vc.present(activityVC, animated: true, completion: nil)
}
목표-C 및 UIPopover 프레젠테이션 컨트롤러 사용을 위한 솔루션
UIActivityViewController *controller = /*Init your Controller*/;
//if iPhone
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
[self presentViewController:controller animated:YES completion:nil];
}
//if iPad
else {
UIPopoverPresentationController* popOver = controller.popoverPresentationController
if(popOver){
popOver.sourceView = controller.view;
popOver.sourceRect = CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/4, 0, 0);
[self presentViewController:controller animated:YES completion:nil];
}
}
Swift용 수정 프로그램 2.0
if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Phone {
self.presentViewController(activityVC, animated: true, completion: nil)
}
else {
let popup: UIPopoverController = UIPopoverController(contentViewController: activityVC)
popup.presentPopoverFromRect(CGRectMake(self.view.frame.size.width / 2, self.view.frame.size.height / 4, 0, 0), inView: self.view, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
}
참고로.
저는 다음 코드를 공유합니다. 이 코드는 Swift 5.0을 사용합니다.또한 사용되지 않는 창을 방지합니다.
UIA 응용 프로그램.shared.windows.먼저?rootViewController!present(activityController, 애니메이션: true, 완료: nil)
코드 조각은 다음과 같습니다.
let activityController = UIActivityViewController(activityItems: [activityItem], applicationActivities: nil)
let scenes = UIApplication.shared.connectedScenes
let windowScene = scenes.first as? UIWindowScene
let window = windowScene?.windows.first
if UIDevice.current.userInterfaceIdiom == .pad{
activityController.popoverPresentationController?.sourceView = window
activityController.popoverPresentationController?.sourceRect = CGRect(x: UIScreen.main.bounds.width / 3, y: UIScreen.main.bounds.height / 1.5, width: 400, height: 400)
}
window?.rootViewController!.present(activityController, animated: true)
그것은 아이폰과 아이패드에서 테스트되었습니다.
누군가에게 도움이 되길 바랍니다.
건배!
스위프트:
let activityViewController = UIActivityViewController(activityItems: sharingItems, applicationActivities: nil)
//if iPhone
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Phone) {
self.presentViewController(activityViewController, animated: true, completion: nil)
} else { //if iPad
// Change Rect to position Popover
var popoverCntlr = UIPopoverController(contentViewController: activityViewController)
popoverCntlr.presentPopoverFromRect(CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/4, 0, 0), inView: self.view, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
}
iphone과 ipad에서 작동하는 swift 4 후속 코드입니다.설명서에 따름
주어진 장치 관용구에 적합한 방법을 사용하여 뷰 컨트롤러를 표시하고 해제하는 것은 사용자의 책임입니다.iPad에서는 뷰 컨트롤러를 팝업으로 표시해야 합니다.다른 장치에서는 형식적으로 표시해야 합니다.
let activityViewController = UIActivityViewController(activityItems: activityitems, applicationActivities: nil)
if UIDevice.current.userInterfaceIdiom == .pad {
if activityViewController.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
activityViewController.popoverPresentationController?.sourceView = self.view
}
}
self.present(activityViewController, animated: true, completion: nil)
다음 코드를 시도해봤는데 작동합니다.
먼저 막대 단추 항목을 View 컨트롤러에 넣은 다음 IBOutlet을 만듭니다.
@property(weak,nonatomic)IBOutlet UIBarButtonItem *barButtonItem;
.m 파일의 다음:yourUIActivityViewController.popoverPresentationController.barButtonItem = self.barButtonItem;
swift = ios7 / ios8
let activityViewController = UIActivityViewController(activityItems: sharingItems, applicationActivities: nil)
//if iPhone
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Phone) {
// go on..
} else {
//if iPad
if activityViewController.respondsToSelector(Selector("popoverPresentationController")) {
// on iOS8
activityViewController.popoverPresentationController!.barButtonItem = self.shareButtonItem;
}
}
self.presentViewController(activityViewController, animated: true, completion: nil)
스위프트 5를 사용하고 있습니다.iPad의 앱에서 "공유 버튼"을 클릭했을 때도 충돌하는 문제가 있었습니다.이 해결책을 찾았습니다.1단계: Main.storyboard에 "view" 객체(객체 라이브러리에서 "UIview" 검색)를 추가합니다.2단계: ViewController.swift에서 @IBOutlet을 생성하고 원하는 이름(예: view1)을 할당합니다.
3단계: 위의 이름(예: view1)을 sourceView로 추가합니다.공유 단추 작업입니다.
@IBAction func Share(_ sender: Any) {
let activityVC = UIActivityViewController(activityItems: ["www.google.com"], applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = view1
self.present(activityVC, animated: true, completion: nil)
}
저는 swift에 매우 익숙하지 않아서 일주일 동안 이것에 갇혀 있었습니다.이것이 누군가에게 도움이 되기를 바랍니다.그래서 이 솔루션을 공유합니다.
이 솔루션을 찾았습니다. 먼저 팝업을 표시하는 뷰 컨트롤러는 다음을 구현해야 합니다.<UIPopoverPresentationControllerDelegate>
의전
다음으로, 다음을 설정해야 합니다.popoverPresentationController
의 대리인.
다음 기능을 추가합니다.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Assuming you've hooked this all up in a Storyboard with a popover presentation style
if ([segue.identifier isEqualToString:@"showPopover"]) {
UINavigationController *destNav = segue.destinationViewController;
PopoverContentsViewController *vc = destNav.viewControllers.firstObject;
// This is the important part
UIPopoverPresentationController *popPC = destNav.popoverPresentationController;
popPC.delegate = self;
}
}
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController: (UIPresentationController *)controller {
return UIModalPresentationNone;
}
스위프트 2.0의 경우.iPad의 공유 버튼에 팝업을 고정하려는 경우 이 기능이 작동한다는 것을 알게 되었습니다.이것은 도구 모음에 공유 버튼에 대한 배출구를 만들었다고 가정합니다.
func share(sender: AnyObject) {
let firstActivityItem = "test"
let activityViewController = UIActivityViewController(activityItems: [firstActivityItem], applicationActivities: nil)
if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Phone {
self.presentViewController(activityViewController, animated: true, completion: nil)
}
else {
if activityViewController.respondsToSelector("popoverPresentationController") {
activityViewController.popoverPresentationController!.barButtonItem = sender as? UIBarButtonItem
self.presentViewController(activityViewController, animated: true, completion: nil)
}
}
}
swift를 사용하여 iPad용으로 개발하는 경우 디버그에서는 잘 작동하지만 릴리스에서는 충돌할 수 있으므로 주의하십시오.testFlight 및 AppStore와 함께 작동하도록 하려면 다음을 사용하여 신속하게 최적화할 수 없습니다.-none
개봉용의
언급URL : https://stackoverflow.com/questions/25644054/uiactivityviewcontroller-crashing-on-ios-8-ipads
'programing' 카테고리의 다른 글
리눅스 셸에서 변수로 나눗셈을 어떻게 할 수 있습니까? (0) | 2023.05.21 |
---|---|
도커가 postgresql이 실행될 때까지 기다립니다. (0) | 2023.05.21 |
분기 기준 변경 (0) | 2023.05.21 |
각도 2 - 모델 변경 후 뷰가 업데이트되지 않음 (0) | 2023.05.21 |
기본 변경 기본 iOS 시뮬레이터 장치 대응 (0) | 2023.05.21 |