In the last week, I’ve been updating an iOS application that I wrote roughly 5 years ago. A significant portion of the work has been porting the code to use the newer frameworks, and it’s been fairly tedious. I’ve learned a few tricks along the way though.
One of the reworks I did was to port a xib/frames-hardcoded view to use autolayout and storyboards. While I didn’t have time to do a full re-write, I was able to use a UIStackView to replace the original tableview approach. Inside the stackview, I have a detail screen that consists of a “header” (e.g. photo, title, favorite button), a custom Actions view (address, call buttons, etc.), and a “footer” view that has dynamic web content. A stackview was the perfect fit for this port, and it reduced the amount of autolayout work needed do it right.
Because the custom Actions view was built in code (and was the most risky piece to rewrite), I left that piece in tact. That meant I had to inject the Actions view at runtime. This worked well until you navigated around. I discovered that my Actions view would be duplicated and offset despite calling removeArrangedSubview. Turns out, I had neglected this tidbit from the Apple docs.
Removing a view from the arrangedSubviews array does not remove it as a subview. The stack view no longer manages the view’s size and position, but the view is still part of the view hierarchy, and is rendered on screen if it is visible.
While it seemed obvious after the fact, it definitely wasn’t intuitive. And I’m not exactly one to pour through API documentation until I’ve “just tried a few things.” Probably not the best practice, but old habits die hard.