Get the viewController's "self" for this wrapped func?

Hi!

So i have wrapped an objC function a share popup, it looks like this:

void Wrapper::shareFunc()
{
    NSString *shareText = @"text to share";
    NSArray *itemsToShare = @[shareText];
    UIActivityViewController * activityVC = [[UIActivityViewController alloc] initWithActivityItems:itemsToShare applicationActivities:nil];
    activityVC.excludedActivityTypes = @[];
    [self presentViewController: activityVC animated: YES completion: nil];
   }

But it is this part that doesn’t work:

   [self presentViewController: activityVC animated: YES completion: nil];

How can i get the “self” instance in cocos2d-x? The current one.

Thanks!
I know that a lot of developers got this problem too.
I appreciate your time!

Actually instead of ‘self’ should be instance of UIVIewController.

I usually get view controller in this way:

UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController

So i have tried to use both:

    NSString *shareText = @"text to share";
    NSArray *itemsToShare = @[shareText];
    UIActivityViewController * activityVC = [[UIActivityViewController alloc] initWithActivityItems:itemsToShare applicationActivities:nil];
    activityVC.excludedActivityTypes = @[];
    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
    [vc presentViewController: activityVC animated: YES completion: nil];

and

    NSString *shareText = @"text to share";
    NSArray *itemsToShare = @[shareText];
    UIActivityViewController * activityVC = [[UIActivityViewController alloc] initWithActivityItems:itemsToShare applicationActivities:nil];
    activityVC.excludedActivityTypes = @[];
    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
    [vc.view presentViewController: activityVC animated: YES completion: nil];

and

    NSString *shareText = @"text to share";
    NSArray *itemsToShare = @[shareText];
    UIActivityViewController * activityVC = [[UIActivityViewController alloc] initWithActivityItems:itemsToShare applicationActivities:nil];
    activityVC.excludedActivityTypes = @[];
    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
    [vc.self presentViewController: activityVC animated: YES completion: nil];

but all of them made it crash ?

Thanks!

Are you testing on iPad?
In that case should be done slightly more setup before presenting activityVC:

if ([activityVC respondsToSelector:@selector(popoverPresentationController)]) {
        UIPopoverPresentationController *popover = [activityVC popoverPresentationController];
        if (popover) {
            popover.sourceView = vc.view; //but if you want popover to appear from your button - then should be used 'sourceRect' instead
        }
}

I use

UIViewController *topRootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topRootViewController.presentedViewController)
{
    topRootViewController = topRootViewController.presentedViewController;
}                                                              [topRootViewController presentViewController: activityVC animated: YES completion: nil];

Thanks so much for time guys!
BUT i have tried both of the codes but it comes with a crash:


When i use @archdanny’s example:

 UIViewController *topRootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    while (topRootViewController.presentedViewController)
    {
        topRootViewController = topRootViewController.presentedViewController;
    }                                                              [topRootViewController presentViewController: activityVC animated: YES completion: nil];

and i don’t really know how to use your newest example @MikhailSh
I have tried this:

    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
    if ([activityVC respondsToSelector:@selector(popoverPresentationController)]) {
        UIPopoverPresentationController *popover = [activityVC popoverPresentationController];
        if (popover) {
            popover.sourceView = vc.view; //but if you want popover to appear from your button - then should be used 'sourceRect' instead
        }
    }

But nothing happens?

How can i fix this?
Thanks again! I really appreciate your time!<3

void Wrapper::shareFunc()
{
    NSString *shareText = @"text to share";
    NSArray *itemsToShare = @[shareText];
    UIActivityViewController * activityVC = [[UIActivityViewController alloc] initWithActivityItems:itemsToShare applicationActivities:nil];
    activityVC.excludedActivityTypes = @[];

    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
    if ([activityVC respondsToSelector:@selector(popoverPresentationController)]) {
            UIPopoverPresentationController *popover = [activityVC popoverPresentationController];
            if (popover) {
                popover.sourceView = vc.view; //but if you want popover to appear from your button - then should be used 'sourceRect' instead
            }
    }
    [vc presentViewController: activityVC animated: YES completion: nil];
}

If that will not help, could you show the stacktrace and logs from console?

1 Like

Nice! It works! Thanks, like for real man, i appreciate this! But one more thing, can you tell me why this is working and why it doesn’t work using only the first line where you declare an instance of the uiViewController? And how can i make it spawn from the button/the bottom of the screen? I know you have said that but then i get this error:


Thanks

I’m using next code to open popover from in-game button:

1 Get bounding box of the button in world space:

cocos2d::Rect getBoundingBoxInWorldSpace(cocos2d::Node *node) {
    auto sourceRect = node->getBoundingBox();
    auto min = node->getParent()->convertToWorldSpace(Vec2(sourceRect.getMinX(), sourceRect.getMinY()));
    auto max = node->getParent()->convertToWorldSpace(Vec2(sourceRect.getMaxX(), sourceRect.getMaxY()));
    sourceRect.origin = min;
    sourceRect.size = cocos2d::Size(max.x - min.x, max.y - min.y);
    return sourceRect;
}

2 Convert bounding box from world space to UI space:

Rect convertBoundingBoxFromWorldSpaceToUISpace(const Rect &wsRect) {
        UIViewController *rootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
        const CGSize viewSize = rootVC.view.bounds.size;
        const cocos2d::Size glWinSize = cocos2d::Director::getInstance()->getWinSize();
        const float xScale = viewSize.width / glWinSize.width;
        const float yScale = viewSize.height / glWinSize.height;
        cocos2d::Rect rect;
        rect.origin.x = wsRect.origin.x * xScale;
        rect.size.width = wsRect.size.width * xScale;
        
        rect.origin.y = (glWinSize.height - wsRect.getMaxY()) * yScale;
        rect.size.height = glRect.size.height * yScale;
        return rect;
}

3 When setup popover:

 Rect rect = convertBoundingBoxFromWorldSpaceToUISpace(getBoundingBoxInWorldSpace(button)); 
 ...
 popover.sourceRect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);

WOW THANKS ! You are amazing!

I know it’s late to ask but why is the screen turning 180 degrees around from up to down every time I click the button?

Thanks!