programing

iOS 8 iPad에서 UIAactivityView 컨트롤러 충돌

linuxpc 2023. 5. 21. 11:01
반응형

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의 문제입니다.UIActivityViewControlleriPhone에서는 잘 작동했지만 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여.UIActivityViewControllerUIBarButtonItem다음 코드를 사용합니다.

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

반응형