Reputation: 2708
In a UIViewController
there is a Segmented Controller placed at the top of the view. Constraints: left: 0, right:0, top: 0, height:90.
Every time a UIApplicationDidBecomeActive
notification is posted, segmented control should update it's view with the newest date by calling func updateUI()
On first load, when viewDidLoad
is called the text in each segment is displayed as expected.
However, if the app goes in background, when it comes back in foreground, the label of the segmented control does not accommodate the text and shows 3 dots... after. See attachment and gif below.
Scope: update segmented control title for each segment every time .UIApplicationDidBecomeActive
notification is posted.
Public Github project https://github.com/bibscy/testProject
class ViewController: UIViewController {
var stringDates = [String]()
var dateNow: Date {
return Date()
}
@IBOutlet weak var segmentedControl: UISegmentedControl!
func updateUI() {
//create string dates and set the title of for each segment in segmented control
self.getNextDays()
}
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: .UIApplicationDidBecomeActive, object: nil)
UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0
self.getNextDays()
}
}
extension ViewController {
//for each segment, construct a string date with the currentDate() being first, followed by 5 consecutive days
func getNextDays() {
stringDates.removeAll() //clear any previous data
for i in 0...5 {
let dateFormatter = DateFormatter()
let today = dateNow
let calendar = Calendar.current
if i == 0 {
let dayComponent = Calendar.current.component(.weekday,from: today)
let day = Calendar.current.component(.day, from: today) //Int
let dayString = dateFormatter.shortWeekdaySymbols[dayComponent-1] //Symbol
let month = Calendar.current.component(.month, from: today)
let monthSymbol = dateFormatter.shortMonthSymbols[month-1]
let dayMonthString = dayString + " " + String(day) + " " + monthSymbol
stringDates.append(dayMonthString)
} else {
var components = DateComponents()
components.weekday = i
let nextDay = calendar.date(byAdding: components, to: today)
let nextDayComponent = Calendar.current.component(.weekday,from: nextDay!)
let day = Calendar.current.component(.day, from: nextDay!)
let dayString = dateFormatter.shortWeekdaySymbols[nextDayComponent-1] // Symbol
let month = Calendar.current.component(.month, from: nextDay!)
let monthSymbol = dateFormatter.shortMonthSymbols[month-1]
let dayMonthString = dayString + " " + String(day) + " " + monthSymbol
stringDates.append(dayMonthString)
}
}
//set the title for each segment from stringDates array
for value in 0...5 {
self.segmentedControl.setTitle(self.stringDates[value], forSegmentAt: value)
}
} //end of getNextDays()
}
Upvotes: 0
Views: 1938
Reputation: 146
The problem is only reproduced in 10.3 iOS version. Solution:
Store initial properties of a segmented label:
fileprivate var height: CGFloat!
fileprivate var width: CGFloat!
Add to ViewDidLoad just before getNextDays
:
let label = segmentedControl.subviews[0].subviews[0] as! UILabel
height = label.frame.height
width = label.frame.width
Set text :
for value in 0...5 {
segmentedControl.setTitle(stringDates[value], forSegmentAt: value)
}
And fix frames after that:
let labels = segmentedControl.subviews.map{ $0.subviews[1] } as! [UILabel]
labels.forEach { (label) in
label.numberOfLines = 0
let frame = label.frame
label.frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: width, height: height)
}
Sample code with some crash protection
Upvotes: 2