CarPlay MPContentItem - swift

I’m working on CarPlay for audio app.
this is my code
if tabIndex == 0
{
let item = MPContentItem(identifier: "Tab \(tabIndex) Item")
item.title = Myarray[indexPath.row].name
item.subtitle = Myarray[indexPath.row].desc
item.artwork = MPMediaItemArtwork(image: imageLiteral(resourceName: Myarray[indexPath.row].imageURL))
item.isPlayable = true
if #available(iOS 10.0, *)
{
item.isStreamingContent = true
}
return item
}
So, the problem is this, when I load CarPlay I have 4 items with the same name/description/image. It should be 4 items with the different name, description and image. In my case all is the same. 1 item four time. The item is random. But when I click on it goes to the NowPlaying screen and it is the right item. Labels are correct and also the picture is correct. How can I fix this, please help.
Thanks
P.S. I also tested or real device

Problem: MPContentItem(identifier: "Tab (tabIndex) Item")
In your code you have set identifier as constant text that is why it's showing all items with the same name, description and image.
You have to provide unique value of identifier for each item. Then you will get the details as you want, check attached screen shot.

Related

How to force the order of UIKit pop up menu button items?

I have a couple of UIKit pop-up menu buttons with identical menu items on the same screen in a Swift app. The buttons are built by calling a function that uses an array of strings to create the list of menu items.
The problem is that depending on the button's vertical position on the screen, the menu items may appear in the order specified by the function, or reversed. If the button is in the upper half of the screen, the menu items are listed in the correct order. If the button is in the lower half of the screen the menu items are listed in reverse order.
I would prefer the menu items to appear in the same order regardless of the button's position on the screen. I could check the button location and have the menu creation function reverse the order, but that seems kind of clunky. I am hoping there's a cleaner way to override this behaviour.
The code and array used to create the button menus:
let buttonMenuItems = ["Spring","Summer","Autumn","Winter"]
func createAttributeMenu(menuNumber: Int)->UIMenu {
var menuActions: [UIAction] = []
for attribute in buttonMenuItems {
let item = UIAction(title: attribute) { action in
self.updateMenu(menuID: menuNumber, selected: attribute)
}
menuActions.append(item)
}
return UIMenu(title: "", children: menuActions)
}
The result is this:
Versions I'm using now in testing: Xcode 14.1, iOS 16.1, but I have seen this behaviour on earlier versions as well. (back to iOS 14.x)
Starting with iOS 16, there is a .preferredMenuElementOrder property that can be set on the button:
case automatic
A constant that allows the system to choose an ordering strategy according to the current context.
case priority
A constant that displays menu elements according to their priority.
case fixed
A constant that displays menu elements in a fixed order.
Best I can tell (as with many Apple definitions), there is no difference between .automatic and .priority.
From the .priority docs page:
Discussion
This ordering strategy displays the first menu element in the UIMenu closest to the location of the user interaction.
So, we get "reversed" order based on the position of the menu relative to the button.
To keep your defined order:
buttonNearTop.menu = createAttributeMenu(menuNumber: 1)
buttonNearBottom.menu = createAttributeMenu(menuNumber: 2)
if #available(iOS 16.0, *) {
buttonNearBottom.preferredMenuElementOrder = .fixed
buttonNearTop.preferredMenuElementOrder = .fixed
} else {
// out of luck... you get Apple's "priority" ordering
}

How to get the index of a cell given the text inside in XCUITest?

I'm testing a tableview the cell content in XCUItest. In my case, I don't know the order of the cell text, nor am I allowed to set an accessibility id for the text. How can I get the index of a cell given the text inside?
For instance, if I wanted to get the index of the cell containing text "Cell 2 Text" I would try something like this:
func testSample() {
let app = XCUIApplication()
let table = app.tables
let cells = table.cells
let indexOfCell2Text = cells.containing(.staticText, identifier: "Cell 2 Text").element.index(ofAccessibilityElement: "I dunno")
print(indexOfCell2Text)
}
I feel like I'm close, but I'm unsure. Can anyone suggest a solution?
I apologize if this question has been asked before. I wasn't able to find anything specific about this.
References I visited beforehand:
https://developer.apple.com/documentation/xctest/xcuielementquery/1500842-element
How can I verify existence of text inside a table view row given its index in an XCTest UI Test?
iOS UI Testing tap on first index of the table
The most reliable way really is to add the index into the accessibility identifier. But, you can't. Can you change the accessibility identifier of the cell instead of the text ?
Anyway, if you don't scroll your table view, you can handle it like that :
let idx = 0
for cell in table.cells.allElementsBoundByIndex {
if cell.staticTexts["Text you are looking for"].exists {
return idx
}
idx = idx + 1
}
Otherwise, the index you will use is related to cells which are displayed on the screen. So, after scrolling, the new first visible cell would become the cell at index 0 and would screw up your search.
for index in 0..<table.cells.count {
if table.cells.element(boundBy: index).staticTexts["Your Text"].exists {
return index
}
}

Swift UITest - No match found for textField with accessibility identifier

Trying to create a UITest for entering an email address/password into text fields and then hitting a login button. Using Xcode.
I watch the UITest navigate to the proper page, but it does not detect the text fields. I made sure that both text fields have the "Accessibility" box checked, and I've given them identifiers.
I'm getting this error:
UI Testing Failure - No matches found for text field
func testExample() {
let app = XCUIApplication()
//Test login page
app.buttons["loginButton"].tap()
//Here it navigates to the desired page
let emailField = app.textFields["email"]
emailField.tap()
emailField.typeText("xxx.xx.edu")
let passwordField = app.textFields["password"]
passwordField.tap()
passwordField.typeText("xxx")
app.buttons["loginButton"].tap()
// let loginAlert = app.alerts["alertVC"]
// XCTAssertEqual(loginAlert.title, "Error")
}
The accessibility indicators are "email" and "password" respectively. Logging in works fine when I run the simulator myself.
EDIT: Apparently there are no text fields at all (count = 0) even though I see them and use them on the page...
Image of storyboard with text fields:
If UITextFiled set SecureTextEntry true, you should use:
let passwordField = app.secureTextFields["password"]
I was having the same problem and I solved by unchecking the "accessibility enabled" box for the "views" of ViewControllers

AppleWatch Speech-to-Text functionality not working

I am trying to implement Speech-to-text feature for watchkit app.
I referred this question which has sample code.
Following is the code I tried:
self.presentTextInputControllerWithSuggestions(["Start it", "Stop it"], allowedInputMode: .Plain, completion: { (selectedAnswers) -> Void in
if selectedAnswers.count > 0 {
if let spokenReply = selectedAnswers[0] as? String {
self.label.setText("\(spokenReply)")
}
}
})
label is a label to display text I speak.
When I run it, it shows the screen where you are supposed to speak (Siri kind of screen) and you have two options on top: ‘Cancel', and ‘Done'. Once I am done speaking, I tap on ‘Done’ but screen doesn’t go away or shows me initial screen, I always have to tap on ‘Cancel’ to go back, and I don’t get any speech data in form of text. I checked it and seems like selectedAnswers is always an empty array, unless I tap on the "Start it"/"Stop it" options.
Can anyone help me with this? I want to show the spoken message on label. I have code inside awakeWithContext method in InterfaceController.swift file, am I supposed to put it somewhere else?
I am using iPhone with iOS 9 beta 2 and watchOS 2 beta on AppleWatch.
Thanks!
You can ask for user input and give him suggestion (see Swift example bellow).
self.presentTextInputControllerWithSuggestions(["suggestion 1", "suggestion 2"] allowedInputMode: .Plain, completion: { (answers) -> Void in
if answers && answers.count > 0 {
if let answer = answers[0] as? String {
println("\answer")
}
}
})
If suggestion is nil it goes directly to dictation. It is not working on the simulator but it is on real watch.
Your approach is correct but something is wrong with your SIRI , try changing the language.
It should work like these.

How do I control the UIPageViewController itemIndex in Swift?

I have set up a UIPageViewController. I therefore have two UIViewControllers and one UIPageViewController.
I am using this code and I would like to decrease or increase a variable called "character" when the user swipes forward or back.
class PageItemController: UIViewController {
/* As we’ll have only one class for all content controllers, we need to somehow identify different content items. In order to do it, each PageItemController should have its index and image name.*/
var itemIndex: Int = 0 {
didSet {
if itemIndex == 0 {
character = 1
}
if itemIndex == 1 {
character = 2
}
}
}
...
}
What I am doing is:
Tap on the Check button to check the value of the variable "character"
"Character 1" is being displayed
Swipe to the right
Tap on the Check button to check the value of the variable "character" once again
"Character 2" is being displayed
Swipe to the left
Tap on Check button
"Character 2" is being displayed. But wait, that variable character should contain "Character 1" instead!
So why is it happening? It should display character 1 instead of character 2.
If you need more details, check out this video: https://www.dropbox.com/s/gd6c7p0xvclixcr/IMG_0886.mov?dl=0
Check this answer:
https://stackoverflow.com/a/27934069/1135714
You need to workaround your way in by setting up multiple variables and edit their values when some UIPageControllers methods are activated.