Provide summary of container like tableview with Voice Over - ios

I'm trying to enable voice over for a tableview with a few standard cells. I've configured the cell views to have the appropriate accessibilityLabel and trait, but I'm stuck trying to implement the following behaviour:
When the table view is in focus, it should say: "Recipes List, 16 elements", then move to the first entry. I wonder how this could be accomplished?
Apple does something similar in the weather app. If Voice Over is active and you scroll to the details section (sun rise, sun set, humidity etc), it will say "Details, sun rise ...". When you tap directly onto the label however, it will say "sun rise, ..." (without "Details").
One workaround I thought of is to add the text to the first cell, but that feels a bit hacky, since the label logically belongs to the table view, not the cell.
Any suggestions?

A container and its children cannot be accessible all together (explanation here).
I think that a custom accessibility element should overlap the table view (both with the same frame) and ordering must have been setup in order to read out the new view before the first cell of the table view.
The table view is definitely not read out if its cells are accessible with VoiceOver.
This is just an assumption because I can't find the behavior you mentioned for the Apple weather app.

Related

Should I choose ViewController or TableViewController?

New to Swift. I am trying to write a recipe-sharing app for fun. One of the features is to let users create a new recipe. On this page, users should be able to give an intro to the recipe to be created, upload an image THEN add a LIST of ingredients dynamically (as we have no idea how many ingredients in total beforehand).
I have created a UIViewController, which includes a UIViewTable, an image view and a "add another ingredient" button. I have created a class for the ingredient. And when the "add" button is pressed, a new "Ingredient" cell will be added to the table. However, I found that adjusting the UIViewTable height dynamically is quite hard.
I want my table to adjust its height according to the number of cells (rows). I haven't found much useful info online.
Or maybe I should've not even used this structure. Instead, just use UITableController (The entire page is a table)? But I got confused that some of the elements (image view, submit a recipe button, recipe-intro textfield etc) will be only created once. Why do I bother making them as prototype cells and add them to my view programmatically?
Thanks in advance!
First of all, welcome to Swift!
You put a few questions together, I will try to answer them one by one. Let's start with the simple stuff.
Don't try to change the height of UITableView based on the number of items. If you want to achieve similar functionality, take a look at UIStackView. Set fixed size for the tableView, ideally with constraints using auto layout.
UITableView is supposed to fill specified space and scroll items inside or show cell on top if there are not enough cells to cover all space.
UITableView is highly optimized to scroll over huge amount of cells as the cells are reused on the background. If you are new to the iOS world, take a look at this function https://developer.apple.com/documentation/uikit/uitableviewcell/1623223-prepareforreuse it can save you hours of debugging (I have been there)
UITableView vs UITableController
UITableController can save you a few lines of code, but using UITableView inside of UIViewController can give you more freedom and save you refactoring if your app is likely to change in the future. There is no specific advantage of UITableController
If you want to provide the extra elements (image view, submit button, text field etc), you can use several methods and this is where the UIViewController with your own UITableView comes in handy.
You can put some buttons, like a plus icon or "Done" button into the navigation bar, as the native Calendar app does.
You can put the static content (intro text field, image view) above the table view (visible always). Use constraints to place the static content on the viewController.view and constraint the table view under your static content. The table view will take less space on the view keeping the space for your content.
Insert your static content as a table view header (will scroll out with the content). Search "HeaderView" here on stack overflow to see how to achieve that.
Place your content over the tableView. If your button is small (rounded), you can place it over the tableView, eg. Twitter uses this for a new tween button.
Hope this answer your questions. Cheers!

Create a listing inside of a ScrollView

I am writing a Swift app, and on my main screen I have a long scrollview with several regions of content in it (upcoming events, announcements, and then featured products, and finally some basic info). So it's this really long scroll, and you can swipe down to the bottom.
So visualize 4 boxes, if you will, stacked vertically.
The 3rd box shows featured products. This can be anywhere from 1 to 30 items, depending upon any filters the user has in their settings.
My first try was using a UITableView for region#3 inside of this parent scrollview, but the problem is it only shows the first few items/rows and then the rest you scroll inside the table (which is the default/natural behavior of a table, right?). Unfortunately, the requirement I have is that the inner table can't scroll - it needs to display everything at once and you have to scroll (in the main UIScrollView) to get to the bottom (not scroll inside the inner uitableview scroll). Also, everyone seems to say don't use UITableView inside of a scroll.
So how do I create some sort of list where I create one template (like how you would in a xib/tablecell, and then assign a data source to it, and then repeat down without scrolling? Should I use a tableview after all, and just make the height of it very high and turn scrolling off?
Do I somehow instantiate xibs in a for loop and assign them dynamically to some view?
Thanks so much!
Sounds like you want a Table View with Grouped style. That would make it fairly easy to keep your "4 boxes" segregated, and your "3rd box" would simply be 1 to 30 rows in that section.
On note: you don't want to have a "very tall" table view - or any other type of view, for that matter. You want to allow iOS to manage memory for you, and to load and display only those parts of your content that is visible at any one time.
In other words, use a table view like its designed to be used :)

XCode autocomplete

I'm new to IOS development, I have a few questions.
1) What's the purpose of property rowheight on table view cell, I mean it does nothing even if I change its value, it always takes the value from its parent view i.e a tableview property rowheight? It visually changes in the IB but nothing happens when I run the app.
2) What's the purpose of Content View why is it even there? Let's say If I have to make some image equal to the height of the cell it restricts me. Or is there any way a content view can be changed to be equal to the cell height & width? I have to put constraints on the image in relation with the cell which is not the immediate parent of the image and I don't know if this is the correct way to do it.
3)How does Xcode Autocomplete works? like if I want to write a function tableview(_:tableview didselectrowwithindex:IndexPath) and I type tableview it shows a list, what to do next? I mean I can't type the whole fucntion with params or find the func in the huge list.
The height of the cell set at the IB is primarily used for simulation, the views described at IB are normally resized when actually used. E.g. you can set rows height to be 100 for the table view, 30 for some of the cells and keep the whole controller simulating a nice screen of iPhone 6. The same view will be used for all devices and will be scaled accordingly as well as the cells with the help of your delegate.
The content view is there for the reasons directly related to your additional requests. It holds all the content while there other views that accompany your content and are part of the cell like separators, accessory views, slide action views. Without a content view the responsibility of managing all the additional parts would most likely fall on you as a developer and while you might think that that is fine at the simple layouts, a simple enhancement to it would make a huge impact.
Fuzzy autocompletion at Xcode seems to be something Apple is working on now. If you can't wait and find it too difficult to navigate through the list, there are Xcode plugins available that provide fuzzy autocompletion.
Answering the question in the topic:
example: tableview(_:tableview didselectrowwithindex:IndexPath)
if you write tableview it will show all the symbols that start with tableview. For functions, it will show all the functions sorted by the second parameter name (didSelectRowWithIndex).
[EDIT]
it will autocomplete as far as the answer is unique and then show you a list full of options. I don't know any tricks to skip looking through the massive list. But after a while you'll know what you're looking for and it gets faster.
[\EDIT]
when you press tab, it
by the way: the delegate functions names start with the name of the object they're related to.
So UITableViewDelegate functions start with tableview.
as for your first two questions there are tons of answers for those questions on SO. This one seems closely related to yours.

Dynamically Change isAccessibilityElement

I've got a bit of a weird situation. I need to have an element not be read out by VoiceOver when I use the 2 finger swipe method, but to be read when tapping on it still.
The object is part of a TableView cell, and I've given the TableView cell its own accessibilityLabel, because it contains two interactive elements, one of which doesn't actually need to be read when tapped on, so I've disabled its accessibility property.
However, my other one needs to be read still when tapped on. The issue is, it's already being read as part of the cell's accessibilityLabel, and then it is read again because it is still an accessible element. Is there any way to differentiate between why VoiceOver is reading an element? Or to dynamically change the accessibilityLabel?
You can dynamically change accessibilityLabel simply by assigning it or overriding the method on the accessible view. However, you shouldn't rely on VoiceOver respecting the change in real time.
Users can navigate via tap or swipe and expect elements to persist regardless of how they were reached. In general, I discourage clever solutions that assume how users interact with VoiceOver.
I'd encourage you to either override the cell summary to omit the label or disable accessibility on the label and leave the content in the cell summary.

Giving a grouped UITableView "First Crack" at touches when using a section header view containing a control

I am using a standard grouped style UITableView that returns a custom header view for one of it's sections (using the tableView's delegate method viewForHeaderInSection:). The view that is returned for the section header contains a control. It displays an image and is a control so it can tapped to let the user change the image. My desired UI is similar to the photo for a contact in the Apple Contacts app (a floating imageView-like control in a grouped style table).
The problem I'd like to solve is that touches on the tableView section header go straight to the control. I'd like the table to get a chance to determine if the touch is actually the beginning of a scroll gesture. If not, then the table can pass the event to the section header view for processing.
This is how all the rows in the table behave since I have "delaysContentTouches" for the table on. I suspect the problem is because the section header view is not in the table's view hierarchy. So everything is probably working per spec. just not the way I want.
I want the section header view to behave regarding touches just like rows do (table gets first chance to process).
BTW I am not placing this control in a table row (which would solve the problem) because I want the rounded rect grouped style for all table rows, but not for this one UI element. This control is in the center of my table (header for section 1) which is why I want drags on it to scroll the table.
OK, so apparently this is simulator issue only. On a device my tableView gets the first chance at the event. So I guess I need to listen to the Apple mantra of "always test on an actual device" before posting to StackOverflow. Sorry friends... may my error be helpful to others who, like me, probably spend too much time in the simulator.

Resources