ios11 game center find player fails - ios

I am developing a multi player game. I want to use "standard" GKMatchmakerViewController for finding players like this:
let matchrequest = GKMatchRequest()
matchrequest.minPlayers = 2
matchrequest.maxPlayers = 2
matchrequest.defaultNumberOfPlayers = 2
matchrequest.inviteMessage = "Hello, do you want to play with me ?"
let mmVC = GKMatchmakerViewController(matchRequest: matchrequest)
mmVC?.matchmakerDelegate = self
self.present(mmVC!, animated: true)
If I invoke the GKMatchmakerViewController on both devices and press "Play now" they find each other and everything ist fine.
However when I press "Invite Friends", press the "+" on the right to add a recipient and go then to the tab "Nearby" NO players show up.
Q1: Why don't I see the player in "Nearby" but can connect to it by pressing "Play now"
Q2: If I send an invitation to my other player via iMessage the message is received on the other device and when I click it the app gets launched. But it remains at its Main Screen and doesn't take any action to respond to the invitation. What Protocol or Callback needs to be implemented in order to react to app launches caused by "game invitations" ?
Please refer to the latest API. The GC APIs have changed dramatically and most SO answers refer to the deprecated API.
Thanks
Chris

For Q2. you need to implement GKLocalPlayerListener to answer calls.
How were you able to send invites? I'm trying to figure out how to get a GKPlayer from a string. Like If I want to send an invite to my friend "Blazing420" how do I know his GKPlayer ID or how do I find him, since GKMatchRequest.recipients only takes GKPlayers as arguments.

Related

iOS 15 DualSense is opening App Library on PS button long press

On iOS 15 a long press on the PS Button of the DualSense controller is opening the App Library and I don't receive a callback via the valueChangedHandler function. The App library which will be opened looks like this
This is how I handle all controller inputs:
func handleController(controller: GCController) {
controller.extendedGamepad?.valueChangedHandler = { [weak self] (gamepad: GCExtendedGamepad, element: GCControllerElement) in
guard let self = self else {
return
}
// no feedback received when performing a long press on the PS button
}
Can the game library be suppressed somehow? Sony's PS Remote Play app somehow manages to suppress it, but I don't know how, nor can I find anything in Apple's official API documentation.
Edit: Seems this problem only occurs on iPads, on iPhones this problem doesn't exist. Is there some API or anything on iPads to suppress this behaviour? I assume the most majority of users don't want to open the App Library in the middle of the game.
If someone ever faces the same problem you can actually disable system gestures for the Home button.
In Swift all you have to add is this line (controller is a GCController object)
controller.physicalInputProfile.buttons[GCInputButtonHome]?.preferredSystemGestureState = .disabled
In ObjectiveC it would work like this
controller.physicalInputProfile.buttons[GCInputButtonHome].preferredSystemGestureState = GCSystemGestureStateDisabled;
Thanks to the Apple employee who helped me here
https://developer.apple.com/forums/thread/711905
Edit: on tvOS this isn't working as the PS button (menu button) of a controller always have to act as home event
https://developer.apple.com/forums/thread/715012

ReplayKit Broadcast upload extension - Service not found

I'm working on an IOS swift application that will allow the user to record the entire screen, any app and even the home screen.
In order to do that, I added a Broadcast Upload Extension to my app.
First I used the RPSystemBroadcastPickerView class in order to add a record button to my view that allow the user to open the record popup and select to which app he wants to broadcast the screen flow. And it's working fine :
But I would like to avoid this step and directly open the popup when the app launch.
So I wrote the following code to do that :
RPBroadcastActivityViewController.load(withPreferredExtension: "ch.jroueche.RecordApp.TestScreen", handler: {broadcastAVC,error in
guard error == nil else {
print("Cannot load Broadcast Activity View Controller.")
return
}
if let broadcastAVC = broadcastAVC {
broadcastAVC.delegate = self
self.present(broadcastAVC, animated: true, completion: {
// broadcastactivityviewcontroller will perform the callback when the broadcast starts (or fails)
print("I've START")
})
}
})
Unlikeenter code here the RPSystemBroadcastPickerView solution, I'm getting the following error :
The preferred broadcast service could not be found.
My issue is similar to the following post :
App not showing up as a broadcast service in RPBroadcastActivityViewController
I also added the extension and the preferred extension identifier is correct.
Why would it be possible using the RPSystemBroadcastPickerView and not programmatically using RPBroadcastActivityViewControllerclass. That does not make sense for me.
Does someone have an idea of what could be the issue and how could I fix it ? Or a workaround in order to do this screen record.
Thanks in advance
It appears that RPBroadcastActivityViewController shows ONLY Broadcast Setup UI Extension, while RPSystemBroadcastPickerView shows ONLY Broadcast Upload Extension. But I have no idea why, as both of them are stated to show list of available providers/services.
It would be very helpful if someone could bring more details on the topic.

How to Hide *DTMF* number while making Phone Call in iOS

I'm trying to initiate a call which also contains DTMF Numbers
ex:- 012345678,1*0001*000*1*1#
and i'm using the following code to initiate the call
guard let number = URL(string: "tel://" + number) else { return }
UIApplication.shared.open(number)
and then the systems shows popup to the user to make the call with the Full number also including the DTMF.
so i was wondering if it is possible that we can hide the DTMF part from that Popup ?
so the user only sees "012345678" instead of "012345678,1*0001*000*1*1#" as this DTMF numbers are secure data that he shouldn't see it.
Thanks
That's not possible, as far as I know. That popup is created by iOS itself and you have no control over it.

How can you extract the overall stream title from AVPlayer?

I'm using AVPlayer and AVPlayerItem in Swift to play internet radio streams.
Observing the "timedMetadata" gives me the track currently playing, however I never seem to get a handle of the radio title
See this example using VLC, I can obtain the "Now playing" part easily with timedMetadata, however I never receive the overall title of the radio "Title".
What am I missing, should I be observing something else to access the stream's/shoutcast/icecast information?
Try this:
let title = AVMetadataItem.metadataItems(from: urlAsset.commonMetadata, withKey: AVMetadataKey.commonKeyTitle, keySpace: AVMetadataKeySpace.common).first?.value as? String
print(title)
This works for media I have with metadata in the title (set using the Apple Music app). If this doesn't work for your media, please post it somewhere online along with your current code.

iOS UI Tests iMessage App/Extension

I'm currently using Fastlane Snapshot to automate taking screenshots for my application. It's all based on UI Tests.
I'm trying to add this same functionality to an iMessage App/Extension.
So currently I have a test that goes through taps buttons, fills in text fields, takes the screenshots, etc.
After all that is done I'd like it to close the application (click the home button), open iMessage, interact with my iMessage application and take some screenshots there as well.
Is this possible? If so how can I achieve this? Automating screenshots for this one application has been amazing and I'd love to be able to do that for the iMessage App as well.
There is no UI Tests for iMessage app extension in Xcode currently. But you can perform it by launching Messages by yourself and find elements in the Messages app. At first, you'll have to launch the Message app and open a conversation :
let messageApp = XCUIApplication(bundleIdentifier: "com.apple.MobileSMS")
messageApp.terminate()
messageApp.activate()
messageApp.cells.firstMatch.tap()
Then, you can access your iMessage app by doing so :
// Replace appIndex by the position of your app in the iMessage bottom bar
let appIndex = 2
messageApp.collectionViews.descendants(matching: .cell).element(boundBy: appIndex).tap()
When your iMessage app is opened in the expanded mode, you can access the close button :
let closeButton = messageApp.buttons.element(boundBy: 1)
If you want to test your iMessage app when the user send a message and then open it, you can do it this way :
// Send your message after it is inserted in the Messages app text field
let sendButton = messageApp.buttons["sendButton"]
waitForElementToExists(sendButton)
sendButton.tap()
// Tap on the iMessage first bubble
let firstBubble = messageApp.collectionViews["TranscriptCollectionView"].cells.element(boundBy: 2)
waitForElementToExists(firstBubble)
firstBubble.tap()
private func waitForElementToExists(_ element: XCUIElement) {
let exists = NSPredicate(format: "exists == 1")
expectation(for: exists, evaluatedWith: element, handler: nil)
waitForExpectations(timeout: 5, handler: nil)
}
With Xcode 9 you can easily switch to the other applications like Messages. The following code switches to Messages, interacts with elements within the app and then switches back to your own app.
let messageApp = XCUIApplication(bundleIdentifier: "com.apple.MobileSMS")
messageApp.terminate()
messageApp.activate()
messageApp.cells.staticTexts["Kate Bell"].tap()
XCUIApplication().activate()

Resources