in an attempt to create a spreadsheet like table without using UICollectionViews, I decided to use nested UIStackViews.
However, since I am using them in a UITableViewCell, and programmatically create them, I have to remove them from cell, otherwise, when it redraws the cell, the new views will overlap with the old ones.
But when removing them from parent view, it crashes. How to correctly remove nested UIStackViews?
My Code to create nested UIStackViews:
let table = UIStackView()
table.axis = .Vertical
table.spacing = 8
let json = JSON(data: jsonNew)
for i in 0..<json["Rows"].count{
let horizontal = UIStackView()
horizontal.axis = .Horizontal
horizontal.spacing = 8
for j in 0..<json["Rows"][i]["Column"].count{
let label = UILabel()
label.text = json["Rows"][i]["Column"][j].string!
label.lineBreakMode = .ByWordWrapping
label.numberOfLines = 0
label.font = label.font.fontWithSize(12)
horizontal.addArrangedSubview(label)
}
table.addArrangedSubview(horizontal)
}
This is how I remove all views from cell:
for myview in view.subviews{
myview.removeFromSuperview()
}
This is the error:
2016-05-17 11:37:58.745 TestProject[678:26088] _UIConstraintBasedLayoutLogUnsatisfiable is OFF 2016-05-17 11:38:16.563 TestProject[678:26088] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '{objective 0x12faebf00: <1100:16, 760:-6.10352e-05, 750:100, 251:563, 250:-512.5> + <760:-1>*0x12ddfbd00:UISV-text-width-disambiguation.negError{id: 13416} + <760:1>*0x12ddfbd00:UISV-text-width-disambiguation.posErrorMarker{id: 13415} + <760:-1>*0x12ddfbd50:UISV-text-width-disambiguation.negError{id: 13431} + <760:1>*0x12ddfbd50:UISV-text-width-disambiguation.posErrorMarker{id: 13430} + <750:1, 250:1>*0x12f80df30.negError{id: 13501} + <750:1, 250:1>*0x12f80f000.negError{id: 13499} + <250:1>*0x12f84df70:UISV-alignment.marker{id: 13578} + <250:4.6875>*0x12f85ee40:UISV-canvas-connection.marker{id: 13524} + <750:1, 250:1>*0x12f873b40.posErrorMarker{id: 13486} + <1100:1>*0x12f8a5730:UIView-Encapsulated-Layout-Width.marker{id: 13587} + <250:-1>*0x12f8b54e0:UISV-alignment.marker{id: 13557} + <250:-4.6875>*0x12f8d1d70:UISV-canvas-connection.marker{id: 13522} + <760:-1>*0x12f904f30:UISV-text-width-disambiguation.negError{id: 13412} + <760:1>*0x12f904f30:UISV-text-width-disambiguation.posErrorMarker{id: 13411} + <760:1>*0x12f904fa0:UISV-spacing.marker{id: 13413} + <251:-1>*0x12f98e950.marker{id: 12953} + <251:1>*0x12f9b0580.marker{id: 12949} + <760:1>*0x12f9cec00:UISV-canvas-connection.marker{id: 13406} + <250:4.6875>*0x12fa05f30:UISV-spacing.marker{id: 13535} + <999:1, 250:-5.6875>*0x12fa11cd0:UISV-fill-proportionally.negError{id: 13530} + <999:1, 250:5.6875>*0x12fa11cd0:UISV-fill-proportionally.posErrorMarker{id: 13529} + <1100:1>*0x12fa146d0.marker{id: 13000} + <750:1, 250:1>*0x12fa27ab0.posErrorMarker{id: 13492} + <1100:-1>*0x12fa3cc90.marker{id: 12998} + <750:1, 250:1>*0x12fa3cd80.negError{id: 13511} + <750:1, 250:1>*0x12fa3ea20.negError{id: 13513} + <250:1>*0x12fa47260:UISV-alignment.marker{id: 13572} + <750:1, 251:1>*0x12fa4e480.negError{id: 13020} + <1100:-1, 251:1>*0x12fa55880.marker{id: 14140} + <250:1>*0x12fa5bc10:UISV-alignment.marker{id: 13581} + <750:1, 250:1>*0x12fa6a5c0.negError{id: 13495} + <750:1, 250:1>*0x12fa711c0.negError{id: 13483} + <994:1, 250:-5.6875>*0x12fa78560:UISV-fill-proportionally.negError{id: 13547} + <994:1, 250:5.6875>*0x12fa78560:UISV-fill-proportionally.posErrorMarker{id: 13546} + <250:-1>*0x12fa7c820:UISV-alignment.marker{id: 13565} + <250:-1>*0x12fa7c870:UISV-alignment.marker{id: 13567} + <250:1>*0x12fa7c8c0:UISV-alignment.marker{id: 13569} + <250:1>*0x12fa7f990:UISV-alignment.marker{id: 13575} + <250:4.6875>*0x12fa7fc20:UISV-spacing.marker{id: 13527} + <250:4.6875>*0x12fa93c40:UISV-spacing.marker{id: 13531} + <750:1, 250:1>*0x12fa94dd0.negError{id: 13517} + <750:-1, 250:4.6875>*0x12fa980e0:UISV-hiding.marker{id: 13550} + <250:-1>*0x12fa98d50:UISV-alignment.marker{id: 13559} + <750:1, 250:1>*0x12fa990f0.negError{id: 13505} + <750:-1, 250:4.6875>*0x12faad3d0:UISV-hiding.marker{id: 13551} + <750:1, 251:1>*0x12fab93e0.negError{id: 13022} + <750:1, 250:1>*0x12fac5ee0.negError{id: 13481} + <250:7>*0x12facbf60:UISV-canvas-connection.marker{id: 13552} + <750:1, 250:1>*0x12fad6cb0.negError{id: 13489} + <250:4.6875>*0x12fadb570:UISV-spacing.marker{id: 13543} + <250:1>*0x12fae21d0:UISV-alignment.marker{id: 13584} + <250:-7>*0x12fae8940:UISV-canvas-connection.marker{id: 13554} + <750:1, 250:1>*0x12faec7c0.negError{id: 13519} + <760:-1>*0x12fc0f8a0:UISV-canvas-connection.marker{id: 13403} + <251:-1>*0x12fc1a8a0.marker{id: 12975} + <760:1>*0x12fc276f0:UISV-spacing.marker{id: 13409} + <760:1>*0x12fc54e40:UISV-spacing.marker{id: 13417} + <760:-1>*0x12fc54e90:UISV-text-width-disambiguation.negError{id: 13429} + <760:1>*0x12fc54e90:UISV-text-width-disambiguation.posErrorMarker{id: 13428} + <251:-1>*0x12fc6dd10.marker{id: 12972} + <1100:1>*0x12fc6e830.marker{id: 12969} + <760:-1>*0x12fc75b80:UISV-text-width-disambiguation.negError{id: 13424} + <760:1>*0x12fc75bf0:UISV-spacing.marker{id: 13425} + <760:-1>*0x12fc78190:UISV-text-width-disambiguation.negError{id: 13420} + <760:1>*0x12fc78190:UISV-text-width-disambiguation.posErrorMarker{id: 13419} + <760:1>*0x12fc78200:UISV-spacing.marker{id: 13421} + <251:-1>*0x12fc8fd20.marker{id: 12957} + <1100:1>*0x12fc95e90.marker{id: 12963} + <250:7>*0x12fc960b0.marker{id: 12955} + <250:4.6875>*0x12fd06e40:UISV-spacing.marker{id: 13533} + <750:1, 250:1>*0x12fd07210.negError{id: 13507} + <996:1, 250:-5.6875>*0x12fd1a3a0:UISV-fill-proportionally.negError{id: 13538} + <996:1, 250:5.6875>*0x12fd1a3a0:UISV-fill-proportionally.posErrorMarker{id: 13537} + <995:1, 250:-5.6875>*0x12fd1b3f0:UISV-fill-proportionally.negError{id: 13542} + <995:1, 250:5.6875>*0x12fd1b3f0:UISV-fill-proportionally.posErrorMarker{id: 13541} + <250:4.6875>*0x12fd1bd50:UISV-spacing.marker{id: 13539} + <993:1, 250:-5.6875>*0x12fd1c370:UISV-fill-proportionally.negError{id: 13549} + <993:1, 250:5.6875>*0x12fd1c370:UISV-fill-proportionally.posErrorMarker{id: 13548} + <250:-1>*0x12fd1e670:UISV-alignment.marker{id: 13561} + <250:-1>*0x12fd1e6c0:UISV-alignment.marker{id: 13563} + <750:0.00277778>*UILabel:0x12f884240'2016-04-11'.Width{id: 13061} + <750:0.00277778>*UILabel:0x12fa2f410'2031839'.Width{id: 13031} + <750:0.00277778>*UILabel:0x12fa2fd90'OTOTAY İÇ VE DIŞ PAZ.A.Ş.'.Width{id: 13037} + <750:0.00277778>*UILabel:0x12fa52010'TL'.Width{id: 13055} + <750:0.00277778>*UILabel:0x12fafa3d0'MAHMUT ÇETİNTÜRK'.Width{id: 13043} + <750:0.00277778>*UILabel:0x12fafa6a0'15000,00'.Width{id: 13049} + <760:0>*UIStackView:0x12fa081c0.Width{id: 13152} + <760:0, 750:-0.00277778>*UIStackView:0x12fb2b740.Width{id: 13067} + <760:0>*UIStackView:0x12fc44970.Width{id: 13322} + <760:0>*UIStackView:0x12fc65df0.Width{id: 13237}}: internal error. Setting empty vector for variable UILabel:0x12f905720'6955677'.Width{id: 13371}.' * First throw call stack: (0x18221ae38 0x18187ff80 0x18221ad80 0x182b52de0 0x182ccf4d4 0x182b4fcc8 0x182b53108 0x182b50d18 0x182b53928 0x182b585e4 0x182b4d010 0x182b4cd78 0x187464c80 0x187357368 0x187356c1c 0x182b4cd50 0x187356ac4 0x1876702c4 0x1873554e8 0x100143634 0x100148164 0x1876b2f40 0x1876b3120 0x1876b6a2c 0x1874a9500 0x1874a923c 0x1874a8ebc 0x187448aa0 0x1876a1a34 0x1876b7b74 0x1874487ac 0x1873580e4 0x184cfea28 0x184cf9634 0x184cf94f4 0x184cf8b24 0x184cf886c 0x184cf1dd8 0x1821d07b0 0x1821ce554 0x1821ce984 0x1820f8d10 0x1839e0088 0x1873c5f70 0x100107234 0x181c968b8) libc++abi.dylib: terminating with uncaught exception of type NSException
A streamlined interface for laying out a collection of views in either a column or a row.
UISV-alignment constraints align subviews horizontally by making them have equal . bottom and equal . top layout attributes ( NSLayoutAttribute ). Notice that the stack view pins all the subviews to the first one. UISV-canvas-connection constraints connect subviews to the 'canvas' which is a stack view itself.
Using the object library, drag a Text Field anywhere into your view, then drag a Horizontal Stack View directly below it. Don't worry about size and position: all that matters is that the text field is above the stack view.
The problem is due the insidestackview
, this one will grow in height variably and the problem is when you scroll down
or change the view, and the cells needs to be reused and the other Label content height will be different from the one who is trying to reuse.
The solution may depends what are your needs, but if you want to keep
label.numberOfLines = 0
and label.lineBreakMode = .ByWordWrapping
(grow stackview to wrap as many lines as necessary)
You can play with the distribution and Heights and multipliers > 0 in your constraints. So it can be .equalSpacing
or if you have a max-height for any of that you can use .fill
(which is the default):
Option1: stack.distribution = .equalSpacing
Option2:
NSLayoutConstraint(item: outsideStackView, attribute: .top, relatedBy: .equal, toItem: parentView, attribute: .bottom, multiplier: 2, constant: 20)
Option3: Give a MaxHeight to inside stackview
Option4: Remove...
label.lineBreakMode = .ByWordWrapping
label.numberOfLines = 0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With