How do you present a view controller in a SKScene? - swift

I am trying to figure out how to use a share sheet for my SpriteKit game and when I try to present the view controller from my scene, it gives me an error.
if self.nodeAtPoint(location) == self.shareButton {
var tempMessage = "I just got \(score) on [insert app]"
let activityVC:UIActivityViewController = UIActivityViewController(activityItems: [tempMessage], applicationActivities: nil)
self.presentViewController(activityVC, animated: true, completion: nil)
}
This is in my GameOverScene. How exactly do you go about managing viewcontrollers in Swift because the answers I have seen were in OBJ-C.
Thanks!

Ok so I did some digging and found a solution that works.
Basically, I used NSNoticationCenter and set up the view controller in my GameViewController file as such.
override func viewDidLoad() {
.
.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showSocialNetworks", name: "showSocialNetworksID", object: nil)
}
and made the function to be called
func showSocialNetworks(){
var tempMessage = "Insert your message to be shared on social network"
let activityVC:UIActivityViewController = UIActivityViewController(activityItems: [tempMessage], applicationActivities: nil)
self.presentViewController(activityVC, animated: true, completion: nil)
}
Now jump back to my GameOverScene, I set it up so when the user taps the Share Button, it performs the following code
if self.nodeAtPoint(location) == self.shareButton {
NSNotificationCenter.defaultCenter().postNotificationName("showSocialNetworksID", object: nil)
}
This may not be the cleanest way to do it, but it works for me. Hope this helps!

Related

UIActivityViewController becomes blank on iOS 15

I have an iOS App similar to Photos App from Apple, which also has a ‘Share’ button for sharing photo, which worked well before. The code is as follows (for simplicity, I changed the sharing content to a string):
#objc func shareButtonTapped()
{
let vc = UIActivityViewController(activityItems: ["www.apple.com"], applicationActivities: nil);
if let pop = vc.popoverPresentationController
{
pop.sourceView = someView;
pop.sourceRect = shareButton.frame;
}
self.present(vc, animated: true, completion: nil);
}
But when my iPhone was upgraded to iOS 15, the UIActivityViewController that is showed up was invisible. I attach an operation video:
enter link description here
Observe carefully, in fact, UIActivityViewController has a pop-up, but it has become almost transparent.
Then, I added a statement to deliberately set the background color of its view:
#objc func shareButtonTapped()
{
let vc = UIActivityViewController(activityItems: ["www.apple.com"], applicationActivities: nil);
vc.view.backgroundColor = UIColor.systemBackground;
if let pop = vc.popoverPresentationController
{
pop.sourceView = someView;
pop.sourceRect = shareButton.frame;
}
self.present(vc, animated: true, completion: nil);
}
The operation video is as follows:
enter link description here
This code is very simple and very standard. I don't know why this happens?
Hope someone can help. Thanks in advance!
In fact, I define the shareButton within a class derived from UICollectionViewCell:
class AssetPreviewCell: UICollectionViewCell, UIScrollViewDelegate, PHLiveViewDelegate, UINavigationControllerDelegate
{
//....
}
And the complete code is:
#objc func shareButtonTapped()
{
guard let svc = self.findViewController() else { return }
let vc = UIActivityViewController(activityItems: ["www.apple.com"], applicationActivities: nil);
if let pop = vc.popoverPresentationController
{
pop.sourceView = someView;
pop.sourceRect = shareButton.frame;
}
svc.present(vc, animated: true, completion: nil);
}
The func findViewController() is the method from enter link description here
Edit:
And I have an 'Albums' button next to the 'Share' button. When the 'Albums' button is tapped, I present another view controller for add current photo to albums or remove current photo from albums according user select or deselect. This view controller is presented quiet normally. The operation video is on enter link description here . So I think the problem is just from UIActivityViewController or something else.
I find the answer. The problem is caused because I overrided the viewDidLoad function of UIActivityViewController for some reason:
override open func viewDidLoad()
{
super.viewDidLoad();
a_var += 1;
}
This cause problem on iOS15 while works well on iOS14 or iOS13.
Now I override the viewDidAppear(_) instead and the problem dissappears:
override open func viewDidAppear(_ animated: Bool)
{
super.viewDidAppear(animated);
a_var += 1;
}
ps: #mczmma is another account of mine. This account is restricted to ask question. I don't know the reason.
What worked for me in my use case was just to change the sourceView from
let shareAll = [textView.text]
let activityViewController = UIActivityViewController(activityItems: shareAll, applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
self.present(activityViewController, animated: true, completion: nil)
to
let shareAll = [textView.text]
let activityViewController = UIActivityViewController(activityItems: shareAll, applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = textView
self.present(activityViewController, animated: true, completion: nil)
So that on iPad the share shows above the textView, and it just works normally on iPhone.

Blank UIActivityViewController swift 5

I want to share a PDF file that i created with PDFKIT. This pdf file is stored in myVariables struct. Here is the code that i use to display the ActivityView when a button is pressed.
#IBAction func shareButton(_ sender: Any) {
let shareContent = [myVariables.pdfInView]
let activityController = UIActivityViewController(activityItems: shareContent,
applicationActivities: nil)
self.present(activityController, animated: true, completion: nil)
}
However, when i run my code, i just get completely blank UIActivityViewController with nothing.
You get completely blank UIActivityViewController with nothing just because your shareContent is nil.Please check that for example use below code:
let shareContent = ["Example"]
Hope it will help you.Thank you.

Go to next Page in UIPageViewController

I have a button and I just want to go to the next page.
I have read in other threads people saying to just used this,
setViewControllers([UIVIewController], direction: .forward, animated: false, completion: nil)
I have tried this in the button on a child view. I see that the PageControl (the little dots) has the functionality I want but I can't seem to find how apple implemented this. I have been reading a lot of posts on stackOverflow but I am not quite grasping it.
I have a rootViewController that implements the dataSource and delegate.
First get the current view controller and next view controller and then pass the next view controller in setViewControllers function
func moveToNextPage() {
guard let currentViewController = self.viewControllers?.first else { return print("Failed to get current view controller") }
guard let nextViewController = self.dataSource?.pageViewController( self, viewControllerAfter: currentViewController) else { return }
setViewControllers([nextViewController], direction: .forward, animated: false, completion: nil)
}
I hope this helps you.

IOS 8 iPad App Crashes When UIActivityViewController Is Called

When a UIActivityViewController is called on the iPhone in this app, it works perfectly, but when called on a iPad, the app crashes. Below is the code I used:
func shareButtonPress() {
//when the share button is pressed, default share phrase is added, cropped image of highscore is added
var sharingItems = [AnyObject]()
var shareButtonHighscore = NSUserDefaults.standardUserDefaults().objectForKey("highscore") as Int!
sharingItems.append("Just hit \(shareButtonHighscore)! Beat it! #Swath")
UIGraphicsBeginImageContextWithOptions(UIScreen.mainScreen().bounds.size, false, 0);
self.view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
sharingItems.append(image)
let activityViewController = UIActivityViewController(activityItems: sharingItems, applicationActivities: nil)
var barButtonItem: UIBarButtonItem! = UIBarButtonItem()
activityViewController.excludedActivityTypes = [UIActivityTypeCopyToPasteboard,UIActivityTypeAirDrop,UIActivityTypeAddToReadingList,UIActivityTypeAssignToContact,UIActivityTypePostToTencentWeibo,UIActivityTypePostToVimeo,UIActivityTypePrint,UIActivityTypeSaveToCameraRoll,UIActivityTypePostToWeibo]
self.presentViewController(activityViewController, animated: true, completion: nil)
}
As you can see, I'm programming in Swift, in the SpriteKit Framework, and I don't understand why the app is crashing.
I'm receiving this error:
Terminating app due to uncaught exception 'NSGenericException', reason: 'UIPopoverPresentationController (<_UIAlertControllerActionSheetRegularPresentationController: 0x7fc7a874bd90>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.'
What can I do to fix this problem?
Before presenting the UIActivityViewController, add in this line of code:
activityViewController.popoverPresentationController?.sourceView = self.view
This way, the view controller knows in which frame of the GameViewController to appear in.
If you read the error it says how to fix it, you need to set the barButtonItem or sourceView from which to present the popover from, in your case:
func shareButtonPress(pressedButton: UIBarButtonItem) {
...
activityViewController.popoverPresentationController.barButtonItem = pressedButton
self.presentViewController(activityViewController, animated: true, completion: nil)
}
Swift 5:
Check if the device is iPhone or iPad and based on that add a sourceView and present the activityController
let activity = UIActivityViewController(activityItems: [self], applicationActivities: nil)
if UIDevice.current.userInterfaceIdiom == .phone {
UIApplication.topViewController?.present(activity, animated: true, completion: nil)
} else {
activity.popoverPresentationController?.sourceView = UIApplication.topViewController!.view
UIApplication.topViewController?.present(activity, animated: true, completion: nil)
}
There are two option, the action came from a UIBarButtonitem or UIButton that is a UIView.
func shareButtonPress() {
...
if let actv = activityViewController.popoverPresentationController {
actv.barButtonItem = someBarButton // if it is a UIBarButtonItem
// Or if it is a view you can get the view rect
actv.sourceView = someView
// actv.sourceRect = someView.frame // you can also specify the CGRect
}
self.presentViewController(activityViewController, animated: true, completion: nil)
}
You may have to add a sender to your function like func shareButtonPress(sender: UIBarButtonItem) or func shareButtonPress(sender: UIButton)
I added for Swift 3:
activityViewController.popoverPresentationController?.sourceView = self.view
fixed my issue.

UIActivityViewController in GameScene

I want to use this function in my GameScene:
func shareButton(){
var myShare = "test"
let activityVC:UIActivityViewController = UIActivityViewController(activityItems: [myShare], applicationActivities: nil)
self.presentViewController(activityVC, animated: true, completion:nil)
}
Because I am using a spritenode and when the spritenode is pushed, I want the sharebutton function to run. but as far as I know an UIActivitycontroller can not be in GameScene, only in GameViewController.
What is the proper way to do this?
Just use it in the GameViewController, no other way around.