"Compact" view in iOS - ios

I have a view in iOS (iPhone) that have multiple components, organized in sort of a stack way (one in top of the next). Those are user account properties, some could be blank.
So, I have in my view the components layout like this:
UITextField1 (Name)
UITextField2 (Location)
UITextField3 (Age)
UITextView1 (Bio)
UITableView (user entries).
Some of the fields could be blank. Instead of having blank spaces for the blank fields I would like the next field to move upper.
This is like this question of flowlayout: What is the best/easiest way to create 'flow layout' type layout in iOS.
I can only see two ways of dealing with this:
Creating a function that traverse all the UIViews and determines which ones are blank and move the following upper.
Creating a UITableView and use different cell heights for cells whose content is empty.
Ideally there would be a component, but I cannot find it (basically some sort of stack/flow layout).
Anyways, I believe that I am going to implement the option #1 above, but I don't know if there is an "standard" way of accomplishing this (I honestly don't even know the proper term to look for this feature).
Thanks.

I would lean more in the direction of your second choice by using a UITableView but not the way you propose.
This would be my approach using a UITableView:
Create a UITableViewCell (or custom cell) for each one of my
components and assign a tag value to each, we'll use these later. You can do this in viewDidLoad.
Add code in numberOfRowsInSection to check to see which fields have
data values present. Return the total count of the number of fields
with data values
In cellForRowAtIndexPath again, check if data exists for that field
If so, check to see if the cell created in step one has already been created or not (if not, create)
If not, increment a counter of some sort to increase your tag value and find the next field that has a value. Once found, use that "tag/index" number to "return" the proper cell.
In the end, you have a UITableView only displaying the fields with data.

Related

Why use UITableViewHeaderFooterView or tableHeaderView instead of multiple UITableViewCell?

Question
What is the benefit of using either tableHeaderView, tableFooterView or UITableViewHeaderFooterView as opposed to just using multiple UITableViewCell, and customising it to look like a header or footer?
Example
A static banner image
A static part with input fields that all look the same:
First name
Last name
Age
Height
Weight
A static part "Appointments", which can be expanded
A dynamic list of doctor's appointments
A static part "Images", which can be expanded
A dynamic list of images
A static part with a "Save" button
My gut reaction was making the top two static parts (1, 2) the tableHeaderView, the other static parts (3, 4) a section header, the dynamic lists (under 3,4) to becells inside sections, and the Save button the tableFooterView.
But then the input fields (under 2) look similar, so they could also be cells.
But then I need to treat sections in a special way, because the first section does not have a header view.
And then, 2 months later, the requirements change and 5 other special parts are added.
So all in all, I'm wondering, why not just implement everything as a UITableViewCell, and have a CellType enum that can easily be extended?
Then you have a flat array cells: [CellType] which is the single source of truth for the table view, and a single method func buildCells() where you populate this array.
So far, this is the only article I've found that talks about this, and I'm kind of agreeing with it.
This approach (just tableview cells, no header/footer views) works fine. In your example, I would have made all of these cells, too.
What is the benefit of using either tableHeaderView, tableFooterView or UITableViewHeaderFooterView as opposed to just using multiple UITableViewCell, and customising it to look like a header or footer?
While a series of cells might make sense in your particular example, I wouldn’t generalize that conclusion and, therefore, categorically dismiss the idea of header/footer views. There are many cases where the header/footer view approach is most logical and intuitive:
in many cases, the section headers don’t have any model data associated with them, but are just for organizational purposes ... in this case (e.g. grouping a list of contacts by the first letter), the header view approach makes a lot of sense;
in other cases, we’re dealing with arrays of arrays of homogenous items ... again, the header view approach makes lot of sense; it has the benefit that the index path section and row now map very nicely to the model;
sometimes we want a header to persist as it scrolls out of view (so the user can see what section they are in even though the header would have otherwise have scrolled out of view);
sometimes we want a footer that shows some derived, calculated value (e.g. when listing items on an invoice, perhaps the “total” should be shown in a footer).
Your scenario feels more like a heterogenous list of model objects. In that case, I think using cells for this model data is perfectly reasonable. But obviously header and footer views still have utility and, in many cases are simpler and more intuitive.

How to wrap self sizing UICollectionViewCell

My goal is to have a Swift implementation of a UICollectionView with dynamic content where each cell hold parts of a sentence. Each part of the sentence can be edited by the user. The problem is that some parts of a sentence might be longer than the container itself. Using sizeToFit is not an alternative because all content should have the same font size to maintain readability throughout the collection view.
Right now the behaviour I get, when I have a part of a sentence longer than the container is the following:
As you can see the third row has leading ellipsis.
What I would like to achieve is the following, the overflowing part of the cell should wrap as analogous to a span tag in HTML, like so:
Is this possible? How can I achieve such a thing?
As far as I can tell, it's possible but complex - here are a few pointers of what I'd say you're going to need:
2 additional collection view cell types: in the first, only the left edges are rounded, in the second only the right
Use Core Text API to measure where your text needs to be wrapped
In your datasource, you're going to have to then recognize the situation before you create the cells and then instead of creating a single cell, you create two, using those new types you have.

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.

iOS Swift How to Extract Strings from All Selected Rows in a TableView

I want to loop through a TableView and extract the text from all the selected rows. I suppose I "could" create and maintain a special array that is updated every time a row is selected/deselected using the didSelect/didDeselectRowAtIndexPath methods. But creating a separate array seems like an extra step. Is there no way to let the TableView itself serve as the array and then simply loop through it and get the selected rows? What would the code look like? I'm new to Swift, so this might be a silly question.
Part of the problem is that cells are supposed to be reused, and when used this way it is not possible to loop through them all. You could get around this by using a unique reuse identifier for each cell, such as the indexPath itself or some underlying unique id in your model. Then, you could indeed loop through all cells and retrieve whatever state you desired from each.
You would, however, find your application crushed under the weight of too many cells being instantiated and kept in memory. If you don't have many cells you won't be killed, but try it with a big data set and your app will enjoy a very quick death.
It is far more efficient to store one array with a bunch of id's than a large number of memory-intensive UITableViewCells.
As mentioned in comments, you should work with underlying datasource, not the table itself.
For example if your table shows rows from Array, it is way more faster to retrieve strings directly from that array than creating UITableViewCells and get strings from them.
Get indices of selected rows using UITableView's property indexPathsForSelectedRows.
Query datasource for each row.
As has been said the tableview only handles displaying, your datasource is what powers the data shown if you think about it.
Plus as said before the tableview dequeues cells as they scroll on and off the screen.
The best way to achieve what you want is to add a property to your datasource for each element that will allow you to filter out the select properties easily.
How are you storing the state for each selected cell currently? As this is the same functionally you would use to be able to generate your selected text array.

Creating NSArray of UITextField objects

I want to have a large number of text boxes which will be touch enabled and editable. Is creating NSArray of UItextField objects the best way for this? If Yes, How can I create? or Suggest other ways to achieve this.
It largely depends on what you are trying to do. An NSArray as a way to store all the text boxes you are using in you controller (instead of creating ivars for that purpose) is ok, but you could as well use a UITableView/UITableViewController for that.
Using a table view would give allow you to grow the number of your text boxes without any effort. On the other hand, if you can guarantee that your text boxes will never be more than those you can display on a single screen real estate, I don't think using a table view would give you big advantages. But, as I said, this largely depends on what you are trying to do.
If you decide to go for the array option, I would suggest using an NSDictionary instead, so that you can access each one of your views by name (or tag, if you associate a tag with each one).
Also keep in mind that you could use the getViewByTag: method on your container view to get a reference to any view that it contains based on the view tag you assigned. So, you could do:
//-- creating text box:
UITextField* textBox = ....;
textBox.tag = 1;
[self.view addSbview:textBox];
//-- accessing the text box:
UITextField* textBox = [self.view getViewByTag:1];
In this sense, a view already behaves as a container for you text boxes and gives you access to them.
EDIT:
Actually I'm trying to create a crossword grid
ok, so, if it's 2-dimensional, I would say that a table view is ruled out (it is not impossible to do, but I think there are easier ways).
as to your question, it all depends on how dynamic your crossword grid is: does it always have the same number of rows and columns? or can it be defined by the user? etc.
In the first case, I would go for an NSArray, or I would simply use tagging as shown above (that would also make memory management automatic).
Otherwise, you might inspect UICollectionView.
If your question is: which data structure is more appropriate to handle a crossword puzzle? then, have a look at this post. In any case, I would say: do not expect that you find a ready-made solution for that kind of problems...
A UITableView containing editable cells would be the best way to do this, if you're after what I think you're describing. There's lots of sample code on Apple's developer site detailing how best to use a table view to create a view showing a series of editable text inputs.
Better to use UI Table View instead of adding 'n' number of text fields.

Resources