I'm currently trying to implement custom divider views in between each cell of my collection view. I found this answer online that adds the custom view in the inter-line spacing (link).
private let separatorDecorationView = "separator"
final class CustomFlowLayout: UICollectionViewFlowLayout {
override init() {
super.init()
register(SeparatorView.self,
forDecorationViewOfKind: separatorDecorationView)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let layoutAttributes = super.layoutAttributesForElements(in: rect) ?? []
let lineWidth = self.minimumLineSpacing
var decorationAttributes: [UICollectionViewLayoutAttributes] = []
// skip first cell
for layoutAttribute in layoutAttributes where layoutAttribute.indexPath.item > 0 {
let separatorAttribute = UICollectionViewLayoutAttributes(forDecorationViewOfKind: separatorDecorationView,
with: layoutAttribute.indexPath)
let cellFrame = layoutAttribute.frame
separatorAttribute.frame = CGRect(x: cellFrame.origin.x,
y: cellFrame.origin.y - lineWidth,
width: cellFrame.size.width,
height: lineWidth)
separatorAttribute.zIndex = Int.max
decorationAttributes.append(separatorAttribute)
}
return layoutAttributes + decorationAttributes
}
}
private final class SeparatorView: UICollectionReusableView {
private let imageView: UIImageView = {
let iv = UIImageView(image: UIImage(named: "cell-divider"))
iv.contentMode = .scaleAspectFit
iv.translatesAutoresizingMaskIntoConstraints = false
return iv
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(imageView)
imageView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
imageView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
imageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
self.frame = layoutAttributes.frame
}
}
This solution actually works, and I'm able to see the dividers. The problem arises, however, when the user clicks on one of the cells. The behavior I want is for the cell to expand to show more details when the cell is clicked. The way I'm implementing this is by keeping track of which indexPaths are selected, and returning a larger size if they are selected in sizeForItemAt. In didSelectItemAt, I reload the collection view. This approach works when I'm using the normal UICollectionViewFlowLayout, but when I try using my custom flow layout (above), I get the following crash:
no UICollectionViewLayoutAttributes instance for -layoutAttributesForDecorationViewOfKind: separator at path <NSIndexPath: 0xf75c5b66b8a0a8ab> {length = 2, path = 0 - 6}
I tried looking up solutions and found these two stack overflows here and here but none of the answers I tried seemed to work.
I tried:
Invalidating the layout when I reload the collection view.
Implementing a cache that I return from when I override layoutAttributesForItem in my custom layout.
Any help would be greatly appreciated at this point!
It seems that I had to overwrite two methods in my custom layout:
override func layoutAttributesForDecorationView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
let layoutAttributes = UICollectionViewLayoutAttributes(forDecorationViewOfKind: elementKind,
with: indexPath)
return layoutAttributes;
}
override func initialLayoutAttributesForAppearingDecorationElement(ofKind elementKind: String, at decorationIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
let attributes = layoutAttributesForDecorationView(ofKind: elementKind,
at: decorationIndexPath)
return attributes
}
I also needed to keep the layout invalidation call when I reloaded the data.
collectionView.reloadData()
let context = collectionViewLayout.invalidationContext(forBoundsChange: bounds)
context.contentOffsetAdjustment = CGPoint.zero
collectionView.collectionViewLayout.invalidateLayout(with: context)
layoutSubviews()
Related
I have a ViewController with a CollectionView inside and a CollectionViewCell with a TableView inside. When the user click on a TableViewCell i want to present a ViewController showing a detailed view of the user's task but i get this error "Missing argument for parameter 'coder' in call" at this line let vc = MyTasksDetailController().
Here's my code :
ProfileController
final class ProfileController: UIViewController {
private var collectionView: UICollectionView?
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 1
layout.minimumInteritemSpacing = 1
layout.sectionInset = UIEdgeInsets(top: 0, left: 1, bottom: 0, right: 1)
let size = (view.width - 4)/3
layout.itemSize = CGSize(width: size, height: size)
collectionView = UICollectionView(frame: .zero,
collectionViewLayout: layout)
// Headers
collectionView?.register(ProfileInfoHeader.self,
forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
withReuseIdentifier: ProfileInfoHeader.identifier)
collectionView?.register(MyTasksCollectionCell.self,
forCellWithReuseIdentifier: MyTasksCollectionCell.identifier)
collectionView?.delegate = self
collectionView?.dataSource = self
guard let collectionView = collectionView else {
return
}
view.addSubview(collectionView)
}
extension ProfileController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyTasksCollectionCell.identifier,
for: indexPath)as! MyTasksCollectionCell
return cell
}
MyTaskCollectionCell
class MyTasksCollectionCell: UICollectionViewCell, UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let task = {() -> Add in
switch (displayedTask) {
case .current:
// First segment tapped
return self.tasks[indexPath.row]
case past:
// Second segment tapped
return self.pastTasks[indexPath.row]
}
}()
let vc = MyTasksDetailController() //ERROR HERE: Missing argument for parameter 'coder' in call : Insert 'coder: <#NSCoder#>'
self.present(vc, animated: true, completion: nil)
}
MyTaskTableCell
class MyPostsTableCell: UITableViewCell {
var setdescriptionTitleLabel: String? {
didSet {
descriptionTitleLabel.text = setdescriptionTitleLabel ?? ""
}
}
var setdateLabel: String? {
didSet {
dateLabel.text = setdateLabel ?? ""
}
}
var sethourLabel: String? {
didSet {
hourLabel.text = sethourLabel ?? ""
}
}
var setDateIcon: UIImage? {
didSet {
dateIcon.image = UIImage()
}
}
var setHourIcon: UIImage? {
didSet {
hourIcon.image = UIImage()
}
}
MyTasksDetailController
class MyTasksDetailController: UIViewController {
internal var task: Add? {
didSet {
if let task = task {
setDescriptionLabel = task.description
setDescriptionTitleLabel = task.descriptionTitle
}
}
}
var setDescriptionLabel: String? {
didSet {
descriptionLabel.text = setDescriptionLabel ?? ""
}
}
var setdescriptionTitleLabel: String? {
didSet {
descriptionTitleLabel.text = setdescriptionTitleLabel ?? ""
}
}
let descriptionLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.font = UIFont.systemFont(ofSize: 28, weight: .bold)
label.textAlignment = .center
return label
}()
let descriptionTitleLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.font = UIFont.systemFont(ofSize: 18, weight: .bold)
label.textAlignment = .center
label.numberOfLines = 3
return label
}()
let container: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.clipsToBounds = true
v.backgroundColor = .white
v.layer.cornerRadius = 24
v.backgroundColor =
// 1
UIColor { traitCollection in
// 2
switch traitCollection.userInterfaceStyle {
case .dark:
// 3
v.layer.borderColor = UIColor.label.cgColor
return UIColor.systemBackground
default:
// 4
v.layer.borderColor = UIColor.black.cgColor
return UIColor.systemBackground
}
}
return v
}()
lazy var stackContainer: UIStackView = {
let stackContainer = UIStackView(arrangedSubviews: [stackDesLabel, stackDesTitLabel])
stackContainer.translatesAutoresizingMaskIntoConstraints = false
stackContainer.axis = .vertical
stackContainer.distribution = UIStackView.Distribution.fillEqually
return stackContainer
}()
lazy var stackDesLabel: UIStackView = {
let stackDesLabel = UIStackView(arrangedSubviews: [descriptionLabel])
stackDesLabel.translatesAutoresizingMaskIntoConstraints = false
stackDesLabel.axis = .vertical
stackDesLabel.distribution = UIStackView.Distribution.fillProportionally
return stackDesLabel
}()
lazy var stackDesTitLabel: UIStackView = {
let stackDesTitLabel = UIStackView(arrangedSubviews: [descriptionTitleLabel])
stackDesTitLabel.translatesAutoresizingMaskIntoConstraints = false
stackDesTitLabel.axis = .horizontal
stackDesTitLabel.distribution = UIStackView.Distribution.fillEqually
return stackDesTitLabel
}()
override func viewDidLoad() {
view.addSubview(stackDesLabel)
view.addSubview(stackDesTitLabel)
stackContainer.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true
stackContainer.trailingAnchor.constraint(equalTo: container.trailingAnchor).isActive = true
stackContainer.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
stackContainer.centerXAnchor.constraint(equalTo: container.centerXAnchor).isActive = true
stackContainer.heightAnchor.constraint(equalTo: container.heightAnchor).isActive = true
stackContainer.widthAnchor.constraint(equalTo: container.widthAnchor).isActive = true
stackDesTitLabel.topAnchor.constraint(equalTo: stackContainer.topAnchor, constant: 50).isActive = true
stackDesTitLabel.widthAnchor.constraint(equalTo: stackContainer.widthAnchor).isActive = true
stackDesTitLabel.centerXAnchor.constraint(equalTo: stackContainer.centerXAnchor).isActive = true
stackDesLabel.topAnchor.constraint(equalTo: stackDesTitLabel.bottomAnchor, constant: 50).isActive = true
stackDesLabel.leadingAnchor.constraint(equalTo: stackContainer.leadingAnchor, constant: 5).isActive = true
stackDesLabel.widthAnchor.constraint(equalTo: stackContainer.widthAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
Add(Data struct)
struct Add {
static var details: Add = Add()
var descriptionTitle: String = ""
var description: String = ""
var id: String?
var date: String = ""
var hour: String = ""
func getDict() -> [String: Any] {
let dict = [
"descriptionTitle": self.descriptionTitle,
"description": self.description,
"date": self.date,
"hour": self.hour,
] as [String : Any]
return dict
}
}
As I suspected, the issue is in MyTasksDetailController with your implementation of
required init?(coder aDecoder: NSCoder)
If you just want a quick solution, you can do one of 2 things based on what makes the most sense to your application:
Remove the required init?(coder aDecoder: NSCoder)
Add your own initializer like this:
init() {
// Keep nil if you are not initializing from XIB
super.init(nibName: nil, bundle: nil)
}
Explanation
What you tried to achieve breaks the rules of initialization inheritance I believe which is why you get that error.
I am looking at all rules from here.
When you do this: class MyTasksDetailController: UIViewController - you are automatically inheriting the initializers of from UIViewController if you follow these rules:
Automatic Initializer Inheritance
Rule 1
If your subclass doesn’t define any designated initializers, it
automatically inherits all of its superclass designated initializers.
Rule 2
If your subclass provides an implementation of all of its
superclass designated initializers—either by inheriting them as per
rule 1, or by providing a custom implementation as part of its
definition—then it automatically inherits all of the superclass
convenience initializers.
These rules apply even if your subclass adds
further convenience initializers.
So now when you added:
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
It breaks rule 1, you are adding your own designated initializer and so you lost all other initializers you inherited previous so you get this error:
So now you have 2 options as described earlier.
1. Remove the required init?(coder aDecoder: NSCoder)
This version of init is needed if you create view controllers in storyboard as it is called automatically called in that situation. If you are not planning on doing that you can remove it. If you are planning on using it in storyboard, you need to complete it:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
2. Add your own designated initializer
By adding required init?(coder aDecoder: NSCoder), you lost the default initializer you were inheriting before and so now you need to make your own:
init() {
// Initialize your local vars
// Call designated initializer from the super class
// Keep nil if you are not initializing from XIB
super.init(nibName: nil, bundle: nil)
}
Either of these should fix your problem:
Update with final thoughts
The above should fix your errors with initialization
However, you will have an error on the next line self.present(vc, animated: true, completion: nil)
In short, present (documentation reference) can only be called by view controllers.
In your code MyTasksCollectionCell is a UICollectionViewCell so you need to notify the view controller that your collection view is in that a cell was tapped and the view controller needs to handle presenting the new view.
You can do this in two ways:
Delegates - give responsibility to your view controller to handle cell tap and present another view controller
Observers - notify your view controller to handle cell tap and present another view controller
Both of these will
These are just quick links to give you an idea but I suggest googling bit more on them to see which is the best for your situation
I am writing a calendar, and each day is a cell, each cell has a Rounded UILabel in contentView, but I don't know why is there the little black border on each cell
Calendar image
In 3d View 3d preview
class CalendarCell: UICollectionViewCell {
static var identifier: String = "DayCell"
let dayLabel: UILabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
self.setUpUI()
self.contentView.addSubview(dayLabel)
}
private func setUpUI() {
dayLabel.text = nil
dayLabel.sizeToFit()
dayLabel.backgroundColor = .white
//dayLabel.layer.borderWidth = 0.5
dayLabel.textColor = .black
dayLabel.textAlignment = .center
dayLabel.clipsToBounds = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
dayLabel.frame = self.contentView.frame
dayLabel.layer.cornerRadius = dayLabel.frame.width / 2
}
override func prepareForReuse() {
super.prepareForReuse()
setUpUI()
}
I'm not sure what's causing the problem but I'm pretty sure you can fix it and achieve the same behavior by changing your code to this:
let collectionViewCellWidth: CGFLoat = 150 // or whatever you want. You'd define this in the file with your custom flow layout or wherever your give the cell size to the collectionView.
class CalendarCell: UICollectionViewCell {
static let identifier = "DayCell" // type inference doesn't need the annotations on these two
let dayLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
setUpUI()
}
private func setUpUI() {
contentView.layer.cornerRadius = collectionViewCellWidth / 2
contentView.clipsToBounds = true
contentView.backgroundColor = .white // or orange, whatever
dayLabel.text = nil
dayLabel.backgroundColor = .white
//dayLabel.layer.borderWidth = 0.5
dayLabel.textColor = .black
dayLabel.textAlignment = .center
dayLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(dayLabel)
NSLayoutConstraint.activate([
dayLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
dayLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor)
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//override func layoutSubviews() {
// dayLabel.frame = self.contentView.frame
// dayLabel.layer.cornerRadius = dayLabel.frame.width / 2
//}
// also as your code currently is, you don't do anything in your setup function that needs to be redone when a cell is dequeued for reuse. Unless you were setting some unique information for a cell like its color or text. Just FYI
override func prepareForReuse() {
super.prepareForReuse()
setUpUI()
}
}
Problem:
The custom view's background colour for each cell in my tableView always uses the initial colour set when declaring my statusColour variable, and the colour set dynamically in cellForRowAt IndexPath is always ignored.
This is my UIView subclass:
class SlantedView: UIView {
var path: UIBezierPath!
var backgroundColour: UIColor!
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func slantedView() {
// Drawing code
// Get Height and Width
let layerHeight = CGFloat(90)
let layerWidth = CGFloat(300)
// Create Path
let bezierPath = UIBezierPath()
// Points
let pointA = CGPoint(x: 0, y: 0)
let pointB = CGPoint(x: layerWidth, y: 89)
let pointC = CGPoint(x: layerWidth, y: layerHeight)
let pointD = CGPoint(x: 0, y: layerHeight)
// Draw the path
bezierPath.move(to: pointA)
bezierPath.addLine(to: pointB)
bezierPath.addLine(to: pointC)
bezierPath.addLine(to: pointD)
bezierPath.close()
// Mask to Path
let shapeLayer = CAShapeLayer()
shapeLayer.path = bezierPath.cgPath
layer.mask = shapeLayer
}
override func draw(_ rect: CGRect) {
self.slantedView()
self.backgroundColor = backgroundColour
self.backgroundColor?.setFill()
UIGraphicsGetCurrentContext()!.fill(rect)
}
}
This is my custom cell:
class CustomTableViewCell: UITableViewCell {
var statusColour: UIColor = {
let colour = UIColor.red
return colour
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let statusContainer = SlantedView()
statusContainer.backgroundColour = self.statusColour
self.addSubview(statusContainer)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
}
This is my cellForRow method:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! CustomTableViewCell
cell.statusColour = sampleData[indexPath.row].statusColour //Contains different colours
return cell
}
The problem is definitely coming from the UIView subclass. According some prior research, it looks like the overridden draw function could be causing the issue.
I followed the advice given in some other Stack Overflow questions by adding these lines:
self.backgroundColor?.setFill()
UIGraphicsGetCurrentContext()!.fill(rect)
What could I be doing wrong?
Thanks in advance.
Add slantedView in awakeFromNib() method instead of init() and also use property observers to change the backgroung color of slantedView as shown below:
class CustomTableViewCell: UITableViewCell {
var statusContainer: SlantedView!
var statusColour: UIColor? {
didSet {
guard let color = statusColour else {
statusContainer.backgroundColor = UIColor.black
return
}
statusContainer.backgroundColor = color
}
}
override func awakeFromNib() {
super.awakeFromNib()
statusContainer = SlantedView(frame: self.bounds)
self.addSubview(statusContainer)
}
}
Lastly, remove last two lines from draw(_ rect: CGRect) method:-
override func draw(_ rect: CGRect) {
self.slantedView()
self.backgroundColor = backgroundColour
}
I know this question might have a lot of answers on SO. But after trying every solution found on the interweb (+ some of my custom inventions ..) I still can't do what I want to achieve.
Here is the story :
I have a UICollectionViewCell with a Subclass of a UITextField embeded in it.
Here is my Subclass :
class CustomTextField: UITextField {
private let padding = UIEdgeInsets(top: 6.0, left: 0.0, bottom: 0.0, right: 2.0)
private lazy var lineView: UIView = {
let lineView = UIView()
lineView.translatesAutoresizingMaskIntoConstraints = false
lineView.isUserInteractionEnabled = false
lineView.frame.size.height = 2
lineView.backgroundColor = UIColor.tiara
return lineView
}()
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func toggleColors() {
if isFirstResponder {
lineView.backgroundColor = .black
} else {
lineView.backgroundColor = UIColor.tiara
}
}
}
private extension CustomTextField {
func commonInit() {
addSubview(lineView)
constraintLineView()
textColor = UIColor.tiara
}
func constraintLineView() {
lineView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
lineView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
lineView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
lineView.heightAnchor.constraint(equalToConstant: 2.0).isActive = true
}
}
And here is the code I use in my UICollectionViewCell :
#discardableResult
func setFirstResponder() -> Bool {
return customTextField.becomeFirstResponder()
}
func endEditing() {
customTextField.resignFirstResponder()
}
The result of customTextField.becomeFirstResponder is always false.
It's called from my UIViewController :
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard indexPath.row != 0 else { return }
dispatchService.stop()
let topIndexPath = IndexPath(item: 0, section: 0)
let topCell: Cell = collectionView.dequeueReusableCell(for: topIndexPath)
topCell.endEditing()
service.data.rearrange(from: indexPath.row, to: 0)
update()
collectionView.performBatchUpdates({
collectionView.moveItem(at: indexPath, to: topIndexPath)
collectionView.scrollToItem(at: topIndexPath, at: .top, animated: true)
}) { (_) in
let secondCell: Cell = collectionView.dequeueReusableCell(for: topIndexPath)
secondCell.setFirstResponder()
self.dispatchService.reset()
}
}
I really don't know where to start, this is the last solution I came with and it stills stays without any keyboard displayed.
I am working on a real device, iPhone X iOS 12.1.
I may not have the quiet right answer but, I think the problem comes from the way you are getting your cell inside collectionView(didSelectItemAt:).
You are using the dequeueReusableCell instead of using cellForItem(at:) for getting your cells. So you are creating a reusable cell and not getting the one you are interested in.
I have been trying to mimic an UITableView layout using UICollectionView. So far I have gotten this:
class TableViewLayout: UICollectionViewFlowLayout {
override init() {
super.init()
minimumInteritemSpacing = 0
minimumLineSpacing = 6
scrollDirection = .vertical
estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
let currentBounds = collectionView?.bounds ?? .zero
return newBounds.width != currentBounds.width
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let attributes = super.layoutAttributesForElements(in: rect) else { return [] }
let sectionInsets: CGFloat = sectionInset.left + sectionInset.right
let contentInsets: CGFloat = (collectionView?.contentInset.left ?? 0) + (collectionView?.contentInset.right ?? 0)
for attribute in attributes where attribute.frame.intersects(rect) {
attribute.size.width = collectionView!.readableContentGuide.layoutFrame.width - sectionInsets - contentInsets
}
return attributes
}
}
Which works pretty great until I rotate the device from landscape to portrait, after that the layout hangs saying that the cell is wider than the actual item size.
Am I missing something trivial here? I don't see any glaring problems standing out. The layout is pretty simple just UILabels with an underdetermine amount of text. They can be seen in here
Portrait
Landscape
Error after portrait from landscape