iOS spreadsheetview not able to display multiple blocks in cell - ios

I’m using Spreadsheetview library in order to show case Jobber functionality.
There is one critical issues which is blocking project release. This is mentioned below:
Problem: Not able to display multi block content in custom cell.
Scenario: Suppose userA has task1 from 10:00 AM to 12:00 AM, userB has task2 from 10:00 AM to 11:00 AM, userC has task3 from 10:00 AM to 11:30 AM so these three task should be displayed in merged cell with one after another.
Refer below screenshot.
Code:
func spreadsheetView(_ spreadsheetView: SpreadsheetView, cellForItemAt indexPath: IndexPath) -> Cell? {
if self.jobDetails == nil {
return nil
}
. . .
//other cases handled like displaying time, date, visit person name which is not having any issue
. . .
else if case (1...(calenderData.count + 1), 2...(Constants.timeIntervals.count + 1)) = (indexPath.column, indexPath.row) {
let cell = spreadsheetView.dequeueReusableCell(withReuseIdentifier: String(describing: ScheduleCell1.self), for: indexPath) as! ScheduleCell1
if(cell.firstBlockLabel.text != nil) || (cell.secondBlockLabel.text != nil) || (cell.thirdBlockLabel.text != nil) {
return nil
}
let visits = calenderData[indexPath.column - 1].calendarRows
for visit in visits {
let diff = findTimeDifference(firstTime: cellTime,secondTime: visit.startTime)
print("startTime: \(visit.startTime) endTime \(visit.endTime) title \(visit.title) totalBlocks \(visit.totalBlocks)")
if(diff >= -30 && diff <= 30 && diff != -1) {
switch visit.totalBlocks {
case 0,1:
cell.firstBlockLabel.isHidden = false
cell.secondBlockLabel.isHidden = true
cell.thirdBlockLabel.isHidden = true
cell.firstBlockLabel.text = "1 - case 1"
if visit.blockSerialNo == 1 {
if(visit.statusCode.caseInsensitiveCompare("completed") == .orderedSame){
cell.firstBlockLabel.attributedText = "\(visit.title)".strikeThrough()
} else {
cell.firstBlockLabel.text = "\(visit.title)"
}
cell.firstBlockLabel.backgroundColor = hexStringToUIColor(hex: visit.statusTagProp.background)
cell.firstBlockLabel.textColor = hexStringToUIColor(hex: visit.statusTagProp.text)
}
case 2:
cell.firstBlockLabel.isHidden = false
cell.secondBlockLabel.isHidden = false
cell.thirdBlockLabel.isHidden = true
cell.firstBlockLabel.text = "1 - case 2"
cell.secondBlockLabel.text = "2 - case 2"
if visit.blockSerialNo == 2 {
if(visit.statusCode.caseInsensitiveCompare("completed") == .orderedSame){
cell.secondBlockLabel.attributedText = "\(visit.title)".strikeThrough()
} else {
cell.secondBlockLabel.text = "\(visit.title)"
}
cell.secondBlockLabel.backgroundColor = hexStringToUIColor(hex: visit.statusTagProp.background)
cell.secondBlockLabel.textColor = hexStringToUIColor(hex: visit.statusTagProp.text)
}
case 3:
cell.firstBlockLabel.isHidden = false
cell.secondBlockLabel.isHidden = false
cell.thirdBlockLabel.isHidden = false
cell.firstBlockLabel.text = "1 - case 3"
cell.secondBlockLabel.text = "2 - case 3"
cell.thirdBlockLabel.text = "3 - case 3"
if visit.blockSerialNo == 3 {
if(visit.statusCode.caseInsensitiveCompare("completed") == .orderedSame){
cell.thirdBlockLabel.attributedText = "\(visit.title)".strikeThrough()
} else {
cell.thirdBlockLabel.text = "\(visit.title)"
}
cell.thirdBlockLabel.backgroundColor = hexStringToUIColor(hex: visit.statusTagProp.background)
cell.thirdBlockLabel.textColor = hexStringToUIColor(hex: visit.statusTagProp.text)
}
default:
break
}
break
}
}
return cell
}
return nil
}
class ScheduleCell1: Cell {
let firstBlockLabel = UILabel()
let secondBlockLabel = UILabel()
let thirdBlockLabel = UILabel()
let stackview = UIStackView()
let lineLabel = UILabel()
var lineYPosition: Int = 0
override var frame: CGRect {
didSet {
firstBlockLabel.frame = CGRect(x: 0, y: 0, width: 500, height: 500)
secondBlockLabel.frame = CGRect(x: 0, y: 0, width: 500, height: 500)
thirdBlockLabel.frame = CGRect(x: 0, y: 0, width: 500, height: 500)
lineLabel.frame = bounds.insetBy(dx: 0, dy: 0)
lineLabel.frame = CGRect(x: 0, y: lineYPosition, width: 300, height: 1)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
lineLabel.frame = bounds
lineLabel.backgroundColor = .red
firstBlockLabel.textAlignment = .center
//firstBlockLabel.text = "firstBlockLabel"
firstBlockLabel.numberOfLines = 0
firstBlockLabel.lineBreakMode = .byTruncatingTail
firstBlockLabel.translatesAutoresizingMaskIntoConstraints = false
secondBlockLabel.textAlignment = .center
//secondBlockLabel.text = "secondBlockLabel"
secondBlockLabel.numberOfLines = 0
secondBlockLabel.lineBreakMode = .byTruncatingTail
secondBlockLabel.translatesAutoresizingMaskIntoConstraints = false
thirdBlockLabel.textAlignment = .center
//thirdBlockLabel.text = "thirdBlockLabel"
thirdBlockLabel.numberOfLines = 0
thirdBlockLabel.lineBreakMode = .byTruncatingTail
thirdBlockLabel.translatesAutoresizingMaskIntoConstraints = false
stackview.frame = bounds
stackview.axis = .horizontal
stackview.spacing = .leastNonzeroMagnitude
stackview.contentMode = .scaleToFill
stackview.translatesAutoresizingMaskIntoConstraints = false
stackview.alignment = .fill
stackview.distribution = .fill
stackview.distribution = .fillProportionally
stackview.addArrangedSubview(firstBlockLabel)
stackview.addArrangedSubview(secondBlockLabel)
stackview.addArrangedSubview(thirdBlockLabel)
firstBlockLabel.backgroundColor = .yellow
secondBlockLabel.backgroundColor = .purple
thirdBlockLabel.backgroundColor = .green
stackview.backgroundColor = .magenta
//contentView.backgroundColor = .magenta
contentView.addSubview(lineLabel)
contentView.bringSubviewToFront(lineLabel)
contentView.addSubview(stackview)
stackview.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
stackview.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
So I’ve added two property totalBlocks (determines how may blocks to be displayed) and BlockSrNo (determines which serial number of block). Logic for this is mentioned below:
func determineMultiBlocks() {
for data in calenderData {
let visits = data.calendarRows
for var i in 0..<visits.count {
let visit = visits[i]
for var j in (i+1)..<visits.count {
let nextVisit = visits[j]
let timeOverlapExists = CheckIfTimeExistBetweenTwoTimeInterval(withStartTime: visit.startTime.timeInSeconds, withEndTime: visit.endTime.timeInSeconds, withTimeToCheck: nextVisit.startTime.timeInSeconds)
if timeOverlapExists {
visit.totalBlocks = visit.totalBlocks + 1
nextVisit.totalBlocks = 0 //nextVisit.totalBlocks - 1
nextVisit.blockSerialNo = visit.totalBlocks
j = j + 1
}
}
break
}
Can help me where am I going wrong? If there is any other solution instead of using totalBlocks/blockSerialNo then let me know.
Appreciate all solutions!

Related

How to dupply an element

Greetings colleagues I am trying to duplicate the blue box with the numbers 1234 but I can not do it, any guidance that you could give me.
enter image description here
this is the parte where i make the view
final class IBANInvesOptView: UIView {
let container: UIView = UIView()
let stackView: UIStackView = UIStackView()
private let products: UIScrollView = {
let products = UIScrollView()
products.isDirectionalLockEnabled = true
products.isScrollEnabled = true
products.bounces = true
products.canCancelContentTouches = false
products.delaysContentTouches = true
products.alwaysBounceVertical = true
products.showsHorizontalScrollIndicator = false
products.alwaysBounceHorizontal = false
return products
}()
let imageView: UIImageView = UIImageView()
private let lblTitle: UILabel = {
let lblTitle = UILabel().usingAutoLayout()
lblTitle.textAlignment = .center
lblTitle.numberOfLines = 3
lblTitle.adjustsFontSizeToFitWidth = true
lblTitle.attributedText = "pipeline.title".localized().bold40(.newBlue)
return lblTitle
}()
private let lblDescription: UILabel = {
let lblDescription = UILabel().usingAutoLayout()
lblDescription.numberOfLines = 3
lblDescription.adjustsFontSizeToFitWidth = true
lblDescription.attributedText = "pipeline.subtitle".localized().book20(.newBlue)
return lblDescription
}()
let stackPipe: UIStackView = {
let stackPipe = UIStackView().usingAutoLayout()
stackPipe.axis = .vertical
stackPipe.alignment = .fill
stackPipe.isLayoutMarginsRelativeArrangement = true
stackPipe.layoutMargins = UIEdgeInsets(top: 30, left: 15, bottom: 30, right: 15)
return stackPipe
}()
private let lblAgree: UILabel = {
let lblAgree = UILabel().usingAutoLayout()
lblAgree.numberOfLines = 3
lblAgree.adjustsFontSizeToFitWidth = true
lblAgree.attributedText = "pipeline.confirm".localized().book15(.newBlue)
return lblAgree
}()
let checkBox: Checkbox = Checkbox()
let stackViewBtns: UIStackView = UIStackView()
let disposeBag: DisposeBag = DisposeBag()
var buttons = [UILabel()]
override init(frame: CGRect) {
super.init(frame: frame)
pipeline()
listSubviewsOfView()
for item in 1...5 {
print("alguna vez entra?")
self.products.addSubview(self.stackPipe)
self.stackPipe.addArrangedSubview(lblTitleCompo)
buttons.append(lblTitleCompo)
constrain(lblTitleCompo) {
lblTitleCompo in
if let superview = lblTitleCompo.superview {
lblTitleCompo.top == superview.top - 10
lblTitleCompo.leading == superview.leading + 10
lblTitleCompo.trailing == superview.trailing - 10
}
}
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
let lblTitleCompo: UILabel = {
let lblTitleCompo = UILabel().usingAutoLayout()
lblTitleCompo.textAlignment = .center
lblTitleCompo.numberOfLines = 3
lblTitleCompo.adjustsFontSizeToFitWidth = true
lblTitleCompo.attributedText = "12345".localized().book20(.slateGray)
return lblTitleCompo
}()
func listSubviewsOfView() {
for item in 1...5 {
print("alguna vez entra?")
self.products.addSubview(self.stackPipe)
self.stackPipe.addArrangedSubview(lblTitleCompo)
buttons.append(lblTitleCompo)
constrain(lblTitleCompo) {
lblTitleCompo in
if let superview = lblTitleCompo.superview {
lblTitleCompo.top == superview.top - 10
lblTitleCompo.leading == superview.leading + 10
lblTitleCompo.trailing == superview.trailing - 10
}
}
}
}
private func setupView() {
backgroundColor = .clear
self.addBlurToBackground()
self.container.backgroundColor = .red
self.container.layer.cornerRadius = 8
self.stackView.axis = .vertical
self.stackView.alignment = .center
self.stackView.distribution = .fillProportionally
self.stackView.spacing = 15
self.stackView.backgroundColor = .blue
self.products.backgroundColor = .yellow
self.products.layer.cornerRadius = 8
self.stackPipe.roundedCornersAndShadow()
self.stackPipe.backgroundColor = .newBlue
self.checkBox.isSelected = false
self.imageView.contentMode = .center
self.imageView.clipsToBounds = true
self.stackViewBtns.axis = .horizontal
self.stackViewBtns.alignment = .center
self.stackViewBtns.distribution = .fillEqually
self.stackViewBtns.spacing = 9
addSubview(self.container)
self.container.addSubview(self.stackView)
self.container.addSubview(self.products)
self.container.addSubview(self.lblAgree)
self.container.addSubview(self.checkBox)
self.stackView.addArrangedSubview(self.imageView)
self.stackView.addArrangedSubview(self.lblTitle)
self.stackView.addArrangedSubview(self.lblDescription)
self.container.addSubview(self.stackViewBtns)
self.products.addSubview(self.stackPipe)
self.constrainViews()
}
private func addBlurToBackground() {
let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(blurEffectView)
}
private func constrainViews() {
constrain(self.container, self.stackView, self.stackViewBtns, self.products, self.checkBox, self.stackPipe, self.lblAgree) {
container, stackView, stackViewBtns, products, checkBox, stackPipe, lblAgree in
if let superview = container.superview {
container.centerY == superview.centerY
container.leading == superview.leading + 20
container.trailing == superview.trailing - 20
container.top == superview.top + 40
container.bottom == superview.bottom - 40
}
stackView.top == container.top + 10
stackView.leading == container.leading + 5
stackView.trailing == container.trailing - 5
products.top == stackView.bottom + 25
products.leading == container.leading + 5
products.trailing == container.trailing - 5
products.height == 460
stackPipe.top == products.top + 25
stackPipe.leading == container.leading + 10
stackPipe.trailing == container.trailing - 10
stackPipe.height == 100
lblAgree.top == stackViewBtns.top - 60
lblAgree.leading == checkBox.trailing + 10
lblAgree.trailing == container.trailing - 20
checkBox.top == stackViewBtns.top - 50
checkBox.leading == container.leading + 20
stackViewBtns.leading >= container.leading + 15
stackViewBtns.trailing <= container.trailing - 15
stackViewBtns.centerX == container.centerX
stackViewBtns.bottom == container.bottom - 20
}
constrain(self.lblTitle, self.lblDescription) {
lblTitle, lblDescription in
if let superview = lblTitle.superview {
lblTitle.top == superview.top + 10
lblDescription.top == lblTitle.bottom + 5
lblDescription.leading == superview.leading + 85
lblDescription.trailing == superview.trailing - 85
}
}
constrain(self.imageView) {
imageView in
imageView.height == 200
imageView.width == 80 ~ UILayoutPriority(750)
}
}
func build(title: String,
description: String?,
image: UIImage?,
buttons: [IBANInvesOptButtonConfiguration]) -> Observable<Int> {
let createdBtns = buttons
.map { createButton(with: $0) }
createdBtns
.forEach { stackViewBtns.addArrangedSubview($0) }
self.setupView()
setNeedsLayout()
let obsBtns = createdBtns
.enumerated()
.map { index, element in
element.rx.tap.asObservable().map { index }
}
return Observable.from(obsBtns).merge()
}
this is how i manage the view, you can check the for loop that's where im trying to dupply the element
override init(frame: CGRect) {
super.init(frame: frame)
pipeline()
listSubviewsOfView()
for item in 1...5 {
print("alguna vez entra?")
self.products.addSubview(self.stackPipe)
self.stackPipe.addArrangedSubview(lblTitleCompo)
The above doesn't make much sense. You are adding stackPipe and lblTitleCompo multiple times. A view can only have one parent view.
If you want five stackPipes and five lblTitleCompos, you will have to make five of them.
Instead of using a let make a func that will create your views...
func makeLabelTitle() -> UILabel {
let lblTitle = UILabel().usingAutoLayout()
lblTitle.textAlignment = .center
lblTitle.numberOfLines = 3
lblTitle.adjustsFontSizeToFitWidth = true
lblTitle.attributedText = "pipeline.title".localized().bold40(.newBlue)
return lblTitle
}
Every time you call the above, it will create a new label.

Swift Readjust / Resize layout (ASDisplayNode) on show hide of the children node

I new to AsyncDisplayKit. So, I create a new app to learn AsyncDisplayKit animationTransition based on my real project code.
The show / hide animation works perfect, but i dont know why the parent node (ASDisplayNode) is not readjusting the layout when the children's hidden (Sorry if my english is bad)
i already tried to put setNeedsLayout() on transitionLayout measurementCompletion, but nothing change
import AsyncDisplayKit
class HomeView: ASDisplayNode {
let topWrapperNode: TopWrapperNode
let loginButtonNode: LoginButtonNode
override required init() {
self.topWrapperNode = TopWrapperNode()
self.loginButtonNode = LoginButtonNode()
super.init()
self.automaticallyManagesSubnodes = true
self.automaticallyRelayoutOnSafeAreaChanges = true
self.insetsLayoutMarginsFromSafeArea = true
}
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
let verticalStackSpec = ASStackLayoutSpec.vertical()
verticalStackSpec.children = [
self.topWrapperNode,
self.loginButtonNode
]
verticalStackSpec.alignItems = .stretch
verticalStackSpec.justifyContent = .spaceBetween
let displayInset = ASInsetLayoutSpec(
insets: UIEdgeInsets(top: 0, left: 32, bottom: 16, right: 32),
child: verticalStackSpec
)
return ASInsetLayoutSpec(insets: safeAreaInsets, child: displayInset)
}
func keyboardShowUpdateLayout(keyboardHeight: CGFloat) {
// self.topWrapperNode.hideWelcomeLabelNode()
}
func keyboardHideUpdateLayout() {
// self.topWrapperNode.showWelcomeLabelNode()
}
}
// MARK - TopWrapperNode
class TopWrapperNode: ASDisplayNode {
let welcomeLabelNode: WelcomeLabelNode
// let textFieldNode: TextFieldNode
override required init() {
welcomeLabelNode = WelcomeLabelNode()
// textFieldNode = TextFieldNode()
super.init()
self.automaticallyManagesSubnodes = true
self.autoresizesSubviews = true
}
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
let verticalStackSpec = ASStackLayoutSpec.vertical()
verticalStackSpec.children = [
self.logoImage,
self.welcomeLabelNode,
// self.textFieldNode,
]
verticalStackSpec.alignItems = .stretch
verticalStackSpec.justifyContent = .spaceBetween
self.backgroundColor = .yellow
let displayInset = ASInsetLayoutSpec(
insets: UIEdgeInsets(top: 24, left: 0, bottom: 0, right: 0),
child: verticalStackSpec
)
return ASInsetLayoutSpec(insets: safeAreaInsets, child: displayInset)
}
private let logoImage: ASImageNode = {
let imageNode = ASImageNode()
imageNode.image = UIImage(named: "logo")
imageNode.frame.size = CGSize(
width: CGFloat(SizeScaler().moderateScale(size: 98)),
height: CGFloat(SizeScaler().moderateScale(size: 48))
)
imageNode.contentMode = .scaleAspectFill
imageNode.style.alignSelf = .center
return imageNode
}()
func hideWelcomeLabelNode() {
self.welcomeLabelNode.setHide(visibility: true)
self.welcomeLabelNode.transitionLayout(withAnimation: true, shouldMeasureAsync: false)
}
func showWelcomeLabelNode() {
self.welcomeLabelNode.setHide(visibility: false)
self.welcomeLabelNode.transitionLayout(withAnimation: true, shouldMeasureAsync: false)
}
}
// MARK: - WelcomeLabel
class WelcomeLabelNode: ASDisplayNode {
var isHide: Bool = false
override required init() {
super.init()
self.automaticallyManagesSubnodes = true
self.autoresizesSubviews = true
self.shouldAnimateSizeChanges = true
}
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
let verticalStackSpec = ASStackLayoutSpec.vertical()
verticalStackSpec.children = [self.welcomeTitleLabel, self.welcomeDescLabel]
verticalStackSpec.alignItems = .start
self.backgroundColor = .green
return ASInsetLayoutSpec(
insets: UIEdgeInsets(top: 0, left: 0, bottom: 40, right: 0),
child: verticalStackSpec
)
}
override func animateLayoutTransition(_ context: ASContextTransitioning) {
if (self.isHide) {
let initialTitle = context.initialFrame(for: self.welcomeTitleLabel)
let initialDesc = context.initialFrame(for: self.welcomeDescLabel)
self.welcomeTitleLabel.alpha = 1
self.welcomeTitleLabel.frame = initialTitle
self.welcomeDescLabel.alpha = 1
self.welcomeDescLabel.frame = initialDesc
var finalTitle = context.finalFrame(for: self.welcomeTitleLabel)
finalTitle.origin.y -= 50
var finalDesc = context.finalFrame(for: self.welcomeDescLabel)
finalDesc.origin.y -= 50
UIView.animate(withDuration: 0.4, animations: {
self.welcomeTitleLabel.alpha = 0
self.welcomeTitleLabel.frame = finalTitle
self.welcomeDescLabel.alpha = 0
self.welcomeDescLabel.frame = finalDesc
}, completion: { finished in
context.completeTransition(finished)
})
} else {
var finalTitle = context.finalFrame(for: self.welcomeTitleLabel)
finalTitle.origin.y -= 50
var finalDesc = context.finalFrame(for: self.welcomeDescLabel)
finalDesc.origin.y -= 50
self.welcomeTitleLabel.alpha = 0
self.welcomeTitleLabel.frame = finalTitle
self.welcomeDescLabel.alpha = 0
self.welcomeDescLabel.frame = finalDesc
let initialTitle = context.initialFrame(for: self.welcomeTitleLabel)
let initialDesc = context.initialFrame(for: self.welcomeDescLabel)
UIView.animate(withDuration: 0.4, animations: {
self.welcomeTitleLabel.alpha = 1
self.welcomeTitleLabel.frame = initialTitle
self.welcomeDescLabel.alpha = 1
self.welcomeDescLabel.frame = initialDesc
}, completion: { finished in
context.completeTransition(finished)
})
}
}
let welcomeTitleLabel: QlueWorkLabel = {
let label = QlueWorkLabel()
label.setFont34(text: "Selamat datang!", fontType: "medium")
label.textContainerInset = UIEdgeInsets(top: 32, left: 0, bottom: 8, right: 0)
label.style.flexGrow = 1
label.style.flexShrink = 1
label.backgroundColor = .cyan
return label
}()
let welcomeDescLabel: QlueWorkLabel = {
let label = QlueWorkLabel()
label.setFont16or20(
text: "Pantau pekerjaanmu lebih mudah dengan QlueWork",
fontType: "regular"
)
label.style.flexGrow = 1
label.style.flexShrink = 1
label.backgroundColor = .blue
return label
}()
func setHide(visibility: Bool) {
self.isHide = visibility
}
}
i expect the parent node readjusting layout when the children is hide / show like the flexBox should be.
Can anyone help me or tell me why did i do wrong?
after rendering complete, you cannot expect parentNode to adjust itself with changing its child dimension
but you can do work arround with ask parentNode to re-render itself
like this
DispatchQueue.main.async{
parentNode.transitionLayout(withAnimation: false,
shouldMeasureAsync: true,
measurementCompletion: nil)
}
make sure to run transitionLayout on main thread
Happy Texturing

Matching Row Height Between UITableviews

My application is to display employee schedules at a store.
My design is that on the left side I have a tableview with employee names in each cell, on the right side I have a header with store operation times and below that a colored bar that extends from an employee's start time to their end time.
The right side of the table must scroll horizontally to so that the user can scroll and see the schedule for any part of the day. I accomplished this effect by putting the times header and the right side table into a scrollview.
In the heightForRowAt function I have
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if tableView.accessibilityIdentifier == "SecondaryTable" {
var height = tblView.rowHeight
if let nameCell = tblView.cellForRow(at: indexPath) {
height = nameCell.frame.height
} else {
height = tblView.rowHeight
}
return height
}
else {
return UITableView.automaticDimension
}
}
Which for the name table returns UITableView.automaticDimension and for the hours table (accessibility identifier "SecondaryTable") should return the height for the corresponding cell on the name table to make sure they line up properly.
The issue is for some reason heightForRowAt is being called for the schedule table when the name table has not loaded the corresponding cell and so it returns tblView.rowHeight which is not the correct height. You can see this in the second to last row in the above image. I verified this by checking what indexPath the schedule table was loading and that the index was not in the list of visible cells for the name table.
The only time these tables are being reloaded is in the viewWillAppear right now:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
DispatchQueue.main.async {
self.tblView.reloadData()
self.secondTblView.reloadData()
}
}
This is only affecting the last row in the table when initially loaded but when the name table does load in the cell doesn't line up with the schedule. It looks like this corrects itself later on but doesn't reload the cell because the information in the cell doesn't change to fill the cell but the next cell starts at the correct spot and the separator lines line up properly.
In case it helps, here is my cellForRow:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "scheduleCell") as? ScheduleCell ?? ScheduleCell()
let cellSchedule = schedule[indexPath.row]
if tableView.accessibilityIdentifier == "SecondaryTable" {
let coloredLabel = UILabel()
coloredLabel.text = " " + cellSchedule.role
coloredLabel.backgroundColor = UIColor.green.darker(by: 35)
coloredLabel.textColor = UIColor.white
timesHeader.layoutSubviews()
var drawStartOnHalfHour = false
var drawEndOnHalfHour = false
var clockFormat = ClockFormat.TwentyFourHour
for hour in self.timesHeader.arrangedSubviews{
let lineLayer = CAShapeLayer()
let x = hour.center.x
switch indexPath.row % 2 {
case 0:
lineLayer.strokeColor = UIColor.lightGray.cgColor
break
default:
lineLayer.strokeColor = UIColor.white.cgColor
break
}
lineLayer.lineWidth = 2
let path = CGMutablePath()
if let header = hour as? UILabel, header.text != nil {
lineLayer.lineDashPattern = [1,5]
path.addLines(between: [CGPoint(x: x, y: 5),
CGPoint(x: x, y: cell.contentView.frame.maxY - 5)])
} else {
path.addLines(between: [CGPoint(x: x, y: cell.contentView.frame.maxY/2 - 2),
CGPoint(x: x, y: cell.contentView.frame.maxY/2 + 2)])
}
lineLayer.path = path
DispatchQueue.main.async {
cell.contentView.layer.addSublayer(lineLayer)
}
if let header = hour as? UILabel {
if header.text != nil {
var afterNoon = false
//On the hour logic
var formatCheck = ""
if header.text!.split(separator: ":").count == 1 {
clockFormat = .TwelveHour
formatCheck = String(describing: header.text!.split(separator: " ")[1] )
}
var headerTime = 0
if clockFormat == .TwentyFourHour {
headerTime = Int(String(describing: header.text!.split(separator: ":")[0])) ?? 0
} else {
headerTime = Int(String(describing: header.text!.split(separator: " ")[0])) ?? 0
}
var UTCCalendar = Calendar.current
UTCCalendar.timeZone = TimeZone(abbreviation: "UTC")!
var t = UTCCalendar.component(.hour, from: cellSchedule.StartTime)
if clockFormat == .TwelveHour && t >= 12{
if t > 12 {
t = t-12
}
afterNoon = true
}
if headerTime == t {
let m = UTCCalendar.component(.minute, from: cellSchedule.StartTime)
if clockFormat == .TwentyFourHour || ((afterNoon && formatCheck.contains("p")) || (!afterNoon && formatCheck.contains("a"))) {
if m == 0 {
//Logic for start times on the hour
coloredLabel.frame = CGRect(x: x, y: cell.contentView.frame.maxY/4,
width: 5, height: cell.contentView.frame.maxY/2)
} else {
//Logic for handling start times on half-hour
drawStartOnHalfHour = true
}
}
}
var e = UTCCalendar.component(.hour, from: cellSchedule.EndTime)
if clockFormat == .TwelveHour && e >= 12{
if e > 12 {
e = e - 12
}
afterNoon = true
}
if headerTime == e {
let m = UTCCalendar.component(.minute, from: cellSchedule.EndTime)
if clockFormat == .TwentyFourHour || ((afterNoon && formatCheck.contains("p")) || (!afterNoon && formatCheck.contains("a"))) {
if m == 0 {
//Logic for end time on the hour
let width = x - coloredLabel.frame.minX
coloredLabel.frame = CGRect(x: coloredLabel.frame.minX,
y: coloredLabel.frame.minY,
width: width, height: coloredLabel.frame.height)
} else {
//Logic for end time on the half-hour
drawEndOnHalfHour = true
}
}
}
} else {
//Half-hour logic
if drawStartOnHalfHour {
drawStartOnHalfHour = false
coloredLabel.frame = CGRect(x: x, y: cell.contentView.frame.maxY/4,
width: 5, height: cell.contentView.frame.maxY/2)
} else if drawEndOnHalfHour {
drawEndOnHalfHour = false
let width = x - coloredLabel.frame.minX
coloredLabel.frame = CGRect(x: coloredLabel.frame.minX,
y: coloredLabel.frame.minY,
width: width, height: coloredLabel.frame.height)
}
}
}
}
DispatchQueue.main.async {
cell.contentView.addSubview(coloredLabel)
}
switch indexPath.row % 2 {
case 0:
let backGround = CALayer()
backGround.frame = cell.contentView.frame
backGround.backgroundColor = UIColor.white.cgColor
cell.contentView.layer.addSublayer(backGround)
break
default:
let backGround = CALayer()
backGround.frame = CGRect(x: 0,
y: 0,
width: self.timesHeader.frame.width,
height: cell.contentView.frame.height)
backGround.backgroundColor = UIColor.lightGray.cgColor
cell.contentView.layer.addSublayer(backGround)
break
}
} else {
cell.textLabel?.numberOfLines = 2
let firstName = String(describing: cellSchedule.FirstName!.prefix(35))
let lastName = String(describing: cellSchedule.LastName!.prefix(35))
cell.textLabel?.text = firstName.trimmingCharacters(in: CharacterSet(charactersIn: " ")) + "\n" + lastName.trimmingCharacters(in: CharacterSet(charactersIn: " "))
cell.textLabel?.sizeToFit()
switch indexPath.row % 2 {
case 0:
cell.textLabel?.textColor = UIColor.black
cell.contentView.backgroundColor = UIColor.white
break
default:
cell.textLabel?.textColor = UIColor.white
cell.contentView.backgroundColor = UIColor.lightGray
break
}
}
return cell
}
Any idea on a clean way to accomplish this?

Adding addChildViewController hangs the app

I am new in iOS.
I have a view controller in which I have added child view controller using addChildViewController in Parent Controller and it hangs the app.
addChildViewController has 2 webservice calling in the viewDidAppear method. It works fine when webservice calling complete. I want to know how to stop the app hangs problem when adding child view controller.
Below is the code how we add the child view controller:
self.stickerController = StickersViewController()
self.addChildViewController(self.stickerController)
self.addSubview(subView: self.stickerController.view, toView: self.view)
self.stickerController.view.isHidden = true
self.stickerController.didMove(toParentViewController: self)
StickersViewController view controller:
import Foundation
class StickersViewController: UIViewController,UICollectionViewDelegateFlowLayout, UICollectionViewDataSource,UISearchBarDelegate {
var yValue:CGFloat = 65
var navheight:CGFloat = 65
var searchView = UIView()
var searchField = UISearchBar()
let cellReuseIdentifier = "cell"
var tableView: UICollectionView!
var dataDictionary: NSMutableArray!
var imageCache = [String:UIImage]()
var titleHeight:CGFloat = 260
var pagenumber: String = "1"
var showAnimator: Bool = true
var isgetLastInsertId: Bool = false
var isRequestSend: Bool = false
var stopPagging : Bool = false
var callFromPagging: Bool = false
var noDataLabel = UILabel()
var tryAgainButton = UIButton()
var gallery_id:Int = 0
let cellReuseIdentifierEmoji = "cell"
var tableViewEmoji: UICollectionView!
var dataDictionaryEmoji: NSMutableArray!
var pagenumberEmoji: String = "1"
var isRequestSendEmoji: Bool = false
var stopPaggingEmoji : Bool = false
var noDataLabelEmoji = UILabel()
var callFromPaggingEmoji:Bool = false
var emojisCategory:UIScrollView!
var sepratorView:UIView!
var plusEmojiBtn = UILabel()
var userEmojiData:NSMutableArray!
var tabMenuHeight:CGFloat = 40
var isSearchBarHidden:Bool = false
var searchBarHeight:CGFloat = 40
var viewHeight:CGFloat = 0
var categoryTabMenuHeight:CGFloat = 0
override func viewDidLoad() {
if isSearchBarHidden == true{
yValue = 0
}else{
searchBarHeight = 80
}
if isSearchBarHidden == false{
viewHeight = self.view.frame.height
}
self.view.addSubview(searchView)
makeSearchView()
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
layout.itemSize = CGSize(width: view.frame.width, height: view.frame.height)
self.tableView = UICollectionView(frame:CGRect(x: 0, y: yValue , width: appWidth,height: viewHeight - yValue - searchBarHeight), collectionViewLayout: layout)
tableView.delegate = self
tableView.dataSource = self
tableView.register(EmoticonsCategoryTableViewCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)
tableView.backgroundColor = appBackgroundColor
self.tableView.alwaysBounceVertical = true
self.tableView.alpha = 1
self.tableView.tag = 1
self.view.addSubview(tableView)
//emoji table
let layoutEmoji: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layoutEmoji.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
layoutEmoji.itemSize = CGSize(width: view.frame.width, height: view.frame.height)
self.tableViewEmoji = UICollectionView(frame:CGRect(x: 0, y: yValue , width: appWidth,height: viewHeight - yValue - tabMenuHeight - searchBarHeight - categoryTabMenuHeight), collectionViewLayout: layoutEmoji)
self.tableViewEmoji.tag = 2
tableViewEmoji.delegate = self
tableViewEmoji.dataSource = self
tableViewEmoji.register(ContentFeelingTableViewCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)
tableViewEmoji.backgroundColor = appBackgroundColor
self.tableViewEmoji.alwaysBounceVertical = true
tableViewEmoji.alpha = 0
self.view.addSubview(tableViewEmoji)
showAnimator = true;
paramsPost.removeAll(keepingCapacity: false)
emojisCategory = UIScrollView(frame: CGRect(x: 0, y: viewHeight - searchBarHeight, width: appWidth - 40, height: 40))
view.addSubview(emojisCategory)
emojisCategory.backgroundColor = appBackgroundColor
sepratorView = UIView(frame: CGRect(x: 0, y: emojisCategory.frame.origin.y, width: appWidth , height: 1/divideSepratorScaleValue))
sepratorView.backgroundColor = appSepratorColor
view.addSubview(sepratorView)
plusEmojiBtn.frame = CGRect(x: emojisCategory.frame.width, y: emojisCategory.frame.origin.y + 1/divideSepratorScaleValue, width: 40, height: 40)
plusEmojiBtn.backgroundColor = appforgroundcolor
plusEmojiBtn.textColor = navigationColor
plusEmojiBtn.font = UIFont(name: fontIcon, size: fontSizeHuge)
plusEmojiBtn.text = "\u{f067}"
plusEmojiBtn.textAlignment = .center
view.addSubview(plusEmojiBtn)
plusEmojiBtn.isUserInteractionEnabled = true
let tabbedPlus = UITapGestureRecognizer(target: self, action: #selector(self.plusTabbed))
plusEmojiBtn.addGestureRecognizer(tabbedPlus)
}
#objc func plusTabbed() {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "EmojiStoreButtonClicked"), object: nil)
let pVc = EmojiStickerStore()
pVc.modalTransitionStyle = UIModalTransitionStyle.coverVertical
let navigationController = UINavigationController(rootViewController: pVc)
self.present(navigationController, animated: true, completion: nil)
}
func getData(){
let width = appWidth
let height = appHeight
if(showAnimator == true){
//show activity indicator
if(callFromPagging == false){
animator.center = self.tableView.center
}else{
animator.center = CGPoint(x: width/2, y: (height - CGFloat(activityIndicatorBottomHeight)))
}
animator.hidesWhenStopped = true
animator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
animator.startAnimating()
self.view.addSubview(animator)
}
if Reachability.isConnectedToNetwork() {
isRequestSend = true
noDataLabel.isHidden = true
tryAgainButton.isHidden = true
let imageData = Data()
paramsPost.removeAll(keepingCapacity: false)
//remove previous stored data
if !(searchField.text?.isEmpty)!{
paramsPost["search"] = searchField.text!
}
sendRequest(paramsPost as Dictionary<String, AnyObject>, url: "stickers/stickers/limit/"+limitCount+"/page/"+pagenumber, method: "POST",image:imageData) { (succeeded) -> () in
DispatchQueue.main.async(execute: {
if(self.pagenumber == "1" && self.dataDictionary != nil){
//remove all stored data from global variable
self.dataDictionary.removeAllObjects()
}
animator.stopAnimating()
if self.isgetLastInsertId == true
{
//stop refresh spinner
refreshControl.endRefreshing()
}
if(succeeded["error_message"] != nil){
if let code = succeeded["error_message"] as? String{
if !code.isEmpty{
openMaintainanceMode(view: self,code: code)
return
}
}
//alert error
self.view.makeToast(succeeded["error_message"]! as! String, duration: 5, position: .bottom)
}else{
//success
if let responseResult = succeeded["result"] as? NSDictionary{
//pagging data
// self.pagenumber = "\(responseResult["next_page"]!)"
//if(responseResult["total_page"] as! Int == responseResult["current_page"] /as! Int){
// self.stopPagging = true
//}else{
// self.stopPagging = false
// }
self.stopPagging = true
if(self.dataDictionary != nil && self.dataDictionary.count > 0){
for data in responseResult["emotions"] as! NSMutableArray {
self.dataDictionary.add(data as AnyObject)
}
}else{
// store in global variable
if(responseResult["emotions"] != nil){
self.dataDictionary = responseResult["emotions"] as! NSMutableArray
self.noDataLabel.isHidden = true
self.tryAgainButton.isHidden = true
//reload table view
self.tableView.reloadData()
}
}
}
self.tableView.reloadData()
}
if self.dataDictionary == nil || self.dataDictionary.count == 0{
self.noData()
}
//reinitialize default variables
self.isRequestSend = false
self.isgetLastInsertId = false
self.callFromPagging = false
})
}
}else{
self.view.makeToast(String(format: NSLocalizedString("No Internet Connection", comment: "")), duration: 5, position: .bottom)
}
}
func makeScrollEmojiContent() {
for i in 0..<userEmojiData.count{
if let dic = userEmojiData[i] as? NSDictionary{
let title = dic["title"] as! String
let id = dic["gallery_id"] as! Int
let label = UILabel(frame: CGRect(x: CGFloat(i*40), y: 0, width: 40, height: 40))
label.tag = id
if title == "search"{
label.font = UIFont(name: fontIcon, size: fontSizeHuge)
label.text = "\u{f002}"
label.textColor = navigationColor
label.backgroundColor = titleLightColor
}else{
let icon = dic["icon"] as! String
let attachment: NSTextAttachment = NSTextAttachment()
if let img = self.imageCache[icon]{
attachment.image = img
}else{
if let url = NSURL(string: icon) {
if let data = NSData.init(contentsOf: url as URL) {
let imageI = UIImage(data: data as Data)!
attachment.image = imageI
self.imageCache[icon] = imageI
}
}
}
attachment.bounds = CGRect(x: 0, y: -3, width: fontSizeHuge, height: fontSizeHuge)
let attachmentString: NSAttributedString = NSAttributedString(attachment: attachment)
label.attributedText = attachmentString
}
label.isUserInteractionEnabled = true
let tabbedPlus = UITapGestureRecognizer(target: self, action: #selector(self.labelTabbed(_:)))
label.addGestureRecognizer(tabbedPlus)
label.textAlignment = .center
emojisCategory.addSubview(label)
}
}
if userEmojiData != nil{
emojisCategory.contentSize = CGSize(width: CGFloat(userEmojiData.count * 40), height: emojisCategory.frame.height)
}
}
#objc func labelTabbed(_ sender:UITapGestureRecognizer) {
let viewS = sender.view as! UILabel
let tag = viewS.tag
for obj in emojisCategory.subviews{
if obj.tag != tag{
obj.backgroundColor = UIColor.clear
}else{
obj.backgroundColor = titleLightColor
}
}
self.searchField.text = ""
if tag == 0{
self.tableView.alpha = 1
self.searchView.alpha = 1
self.tableViewEmoji.alpha = 0
self.tableViewEmoji.frame.origin.y = yValue
self.noDataLabelEmoji.isHidden = true
self.tableViewEmoji.frame.size.height = viewHeight - yValue - tabMenuHeight - searchBarHeight
}else{
self.tableView.alpha = 0
self.searchView.alpha = 0
gallery_id = tag
self.tableViewEmoji.frame.origin.y = navheight
self.tableViewEmoji.frame.size.height = viewHeight - yValue - tabMenuHeight - categoryTabMenuHeight
if dataDictionaryEmoji != nil && dataDictionaryEmoji.count > 0{
dataDictionaryEmoji.removeAllObjects()
}
tableViewEmoji.reloadData()
getEmojiFeelingData()
}
}
func getEmojiFeelingData(){
self.tableView.alpha = 0
self.tableViewEmoji.alpha = 1
let width = appWidth
let height = appHeight
if(showAnimator == true){
//show activity indicator
if(callFromPagging == false){
animator.center = self.view.center
}else{
animator.center = CGPoint(x: width/2, y: (height - CGFloat(activityIndicatorBottomHeight)))
}
animator.hidesWhenStopped = true
animator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
animator.startAnimating()
self.view.addSubview(animator)
}
if Reachability.isConnectedToNetwork() {
isRequestSendEmoji = true
let imageData = Data()
paramsPost.removeAll(keepingCapacity: false)
//remove previous stored data
if !(searchField.text?.isEmpty)!{
paramsPost["search"] = searchField.text!
}
paramsPost["gallery_id"] = "\(self.gallery_id)"
sendRequest(paramsPost as Dictionary<String, AnyObject>, url: "stickers/emoji-content/", method: "POST",image:imageData) { (succeeded) -> () in
DispatchQueue.main.async(execute: {
if(self.pagenumberEmoji == "1" && self.dataDictionaryEmoji != nil){
//remove all stored data from global variable
self.dataDictionaryEmoji.removeAllObjects()
}
animator.stopAnimating()
if(succeeded["error_message"] != nil){
if let code = succeeded["error_message"] as? String{
if !code.isEmpty{
openMaintainanceMode(view: self,code: code)
return
}
}
//alert error
self.view.makeToast(succeeded["error_message"]! as! String, duration: 5, position: .bottom)
}else{
//success
if let responseResult = succeeded["result"] as? NSDictionary{
self.stopPaggingEmoji = true
if(self.dataDictionaryEmoji != nil && self.dataDictionaryEmoji.count > 0){
for data in responseResult["emotions"] as! NSMutableArray {
self.dataDictionaryEmoji.add(data as AnyObject)
}
}else{
// store in global variable
if(responseResult["emotions"] != nil){
self.dataDictionaryEmoji = responseResult["emotions"] as! NSMutableArray
self.noDataLabelEmoji.isHidden = true
//reload table view
self.tableViewEmoji.reloadData()
}
}
}
self.tableViewEmoji.reloadData()
}
if self.dataDictionaryEmoji == nil || self.dataDictionaryEmoji.count == 0{
self.noDataEmoji()
}
//reinitialize default variables
self.isRequestSendEmoji = false
self.callFromPaggingEmoji = false
})
}
}else{
self.view.makeToast(String(format: NSLocalizedString("No Internet Connection", comment: "")), duration: 5, position: .bottom)
}
}
func scrollViewDidScroll(_ sender:UIScrollView) {
view.endEditing(true)
}
func noDataEmoji() {
self.noDataLabelEmoji = UILabel(frame: CGRect( x: 0, y: 0, width: appWidth, height: 30))
self.noDataLabelEmoji.font = UIFont(name: fontName, size: fontSizeLarge)
self.view.backgroundColor = appBackgroundColor
self.noDataLabelEmoji.textFontColor()
self.noDataLabelEmoji.textAlignment = .center
self.noDataLabelEmoji.text = NSLocalizedString("No stickers to show.", comment: "")
self.noDataLabelEmoji.center = self.tableViewEmoji.center
self.view.addSubview(self.noDataLabelEmoji)
}
func noData() {
self.noDataLabel = UILabel(frame: CGRect( x: 0, y: 0, width: appWidth, height: 30))
self.noDataLabel.font = UIFont(name: fontName, size: fontSizeLarge)
self.view.backgroundColor = appBackgroundColor
self.noDataLabel.textAlignment = .center
self.noDataLabel.textColor = noDataLabelTextColor
self.noDataLabel.text = NSLocalizedString("No category found with the given search.", comment: "")
self.noDataLabel.center = self.tableView.center
self.view.addSubview(self.noDataLabel)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView.tag == 2{
if(dataDictionaryEmoji != nil){
return dataDictionaryEmoji.count
}else{
return 0
}
}else{
if(dataDictionary != nil){
return dataDictionary.count
}else{
return 0
}
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
var width = appWidth - 20
if collectionView.tag == 1{
if (UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad)
{
// Ipad
width = (width - 5*2)/3
}
else
{
width = (width - 5*1)/2
}
return CGSize(width: width, height: 40)
}else{
if (UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad)
{
// Ipad
width = (width - 5*6)/6
}
else
{
width = (width - 5*4)/4
}
return CGSize(width: width, height: 60)
}
}
func makeSearchView() {
searchView.frame = CGRect(x: 0, y: yValue, width: appWidth, height: 50)
yValue = yValue + 50
searchField.frame = CGRect(x: 0, y: 0, width: appWidth, height: 50)
searchField.delegate = self
searchField.placeholder = NSLocalizedString("Search stickers", comment: "")
searchView.addSubview(searchField)
//change search text field attributes
for mainView in searchField.subviews {
for subView in mainView.subviews {
if let textField = subView as? UITextField {
textField.textColor = searchBarTextColor
textField.font = UIFont(name: fontName, size: fontSizeMedium)
}
}
}
}
func userEmojis() {
if Reachability.isConnectedToNetwork() {
let imageData = Data()
paramsPost.removeAll()
paramsPost["user_emojis"] = "1"
sendRequest(paramsPost as Dictionary<String, AnyObject>, url: "stickers/stickers/", method: "POST",image:imageData) { (succeeded) -> () in
DispatchQueue.main.async(execute: {
if(succeeded["error_message"] != nil){
if let code = succeeded["error_message"] as? String{
if !code.isEmpty{
openMaintainanceMode(view: self,code: code)
return
}
}
}else{
for obj in self.emojisCategory.subviews{
obj.removeFromSuperview()
}
//success
if let responseResult = succeeded["result"] as? NSDictionary{
if let userEmoji = responseResult["useremotions"] as? NSMutableArray{
self.emojisCategory.isHidden = false
self.sepratorView.isHidden = false
self.userEmojiData = userEmoji
self.makeScrollEmojiContent()
}else{
self.emojisCategory.isHidden = true
self.sepratorView.isHidden = true
}
}
}
})
}
}
}
override func viewDidAppear(_ animated: Bool) {
self.getData()
self.userEmojis()
}
func changeTableViewSize() {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "emojiSearchButtonTabbed"), object: nil)
}
}

UIButton Action doesn't call in Swift?

In my project I have create the Left View and Right View, its dynamically show two different Views, Left View side create firstView and the FirstView inside show Title, Comments, Image and Video. And Also RightView side create secondView inside show Title,Comments, Image and Video. Image and Video show only some of the Views. The design is fully created programmatically, my design is given below,
My problem is play button(UIButton) Action not Called why?
I don't know,
my code is give below, UIButton Name: btnPlay, Action Name: buttonAction:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var scrollViewBase: UIScrollView!
var leftView = UIView()
var rightView = UIView()
var wholeYLeft = CGFloat()
var wholeYRight = CGFloat()
let btnPlay = UIButton()
var myArrayOfDict: NSArray = [
["Title": "MacBook", "Text": "Our goal with MacBook was to do the impossible: engineer a full-sized experience into the lightest and most compact Mac notebook ever. That meant reimagining every element to make it not only lighter and thinner but also better.", "Image":"MacBook1","video":""],
["Title": "OS X", "Text": "OS X is the operating system that makes it possible to do all the things you do on a Mac.", "Image":"","video":""],
["Title": "MacBook Pro", "Text": "Now with the force Touch trackpad,longer battery life and faster flash storage", "Image":"MacBookPro1","video":""],
["Title": "Mac Mini", "Text": "Mac mini is an affordable powerhouse that packs the entire Mac experience into a 19.7cm-square frame. Just connect your own display, keyboard and mouse, and you’re ready to make big things happen.", "Image":"Mini","video":""],
["Title": "iMac", "Text": "The idea behind iMac has never wavered: to craft the ultimate desktop experience. The best display, paired with high-performance processors, graphics and storage ", "Image":"","video":""],
["Title": "MacBook Air", "Text": "The 11-inch MacBook Air lasts up to 9 hours between charges and the 13-inch model lasts up to an incredible 12 hours. So from your morning coffee till your evening commute, you can work unplugged.", "Image":"VideoThumn","video":"Official Apple MacBook Air Video YouTube.mp4"]
]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.title = "Dynamic Cell"
leftView.frame = CGRectMake(0, 0, self.view.frame.width/2, self.view.frame.height)
rightView.frame = CGRectMake(self.view.frame.width/2, 0, self.view.frame.width/2, self.view.frame.height)
// leftView.backgroundColor = UIColor.lightGrayColor()
// rightView.backgroundColor = UIColor.grayColor()
self.scrollViewBase.addSubview(leftView)
self.scrollViewBase.addSubview(rightView)
self.callViewMethod()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func callViewMethod() {
var yFloatLeft : CGFloat! = 5
var yFloatRight : CGFloat! = 5
wholeYLeft = 0
wholeYRight = 0
for var i = 0; i < myArrayOfDict.count; i++ {
let isCheckImage = myArrayOfDict[i].valueForKey("Image") as! String
let isCheckVideo = myArrayOfDict[i].valueForKey("video") as! String
let str = myArrayOfDict[i].valueForKey("Text") as? String
let boundingRectHeight = str!.boundingRectWithSize(CGSizeMake(self.leftView.frame.width-10, CGFloat.max),
options:NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: UIFont(name: "Arial", size: 14.0)!], context:nil).size.height + 60.0
if(i%2 == 0) {
let firstView = UIView()
print(yFloatLeft)
if(isCheckImage == "") {
firstView.frame = CGRectMake(5, yFloatLeft, self.leftView.frame.width-10, 30 + boundingRectHeight)
} else {
firstView.frame = CGRectMake(5, yFloatLeft, self.leftView.frame.width-10, 180 + boundingRectHeight)
}
// firstView.backgroundColor = UIColor.redColor()
firstView.layer.borderWidth = 2.0
firstView.layer.borderColor = UIColor.lightGrayColor().CGColor
leftView.addSubview(firstView)
let lblTitle = UILabel()
lblTitle.frame = CGRectMake(0, 0, self.leftView.frame.width-10, 30)
lblTitle.textAlignment = NSTextAlignment.Center
lblTitle.text = myArrayOfDict[i].valueForKey("Title") as? String
let lblText = lblInset()
lblText.frame = CGRectMake(0, 30, self.leftView.frame.width-10, boundingRectHeight)
lblText.text = myArrayOfDict[i].valueForKey("Text") as? String
lblText.numberOfLines = 0
lblText.lineBreakMode = .ByWordWrapping
lblText.font = UIFont(name: "Arial", size: 16)
lblText.textAlignment = NSTextAlignment.Justified
let mainImageView = UIImageView()
if(isCheckImage == "") {
mainImageView.hidden = true
yFloatLeft = yFloatLeft + 30 + boundingRectHeight + 10
} else {
mainImageView.hidden = false
mainImageView.frame = CGRectMake(0, 30 + boundingRectHeight, self.leftView.frame.width-10, 150)
mainImageView.image = UIImage(named: (myArrayOfDict[i].valueForKey("Image") as? String)!)
if(isCheckVideo == "") {
btnPlay.hidden = true
} else {
btnPlay.hidden = false
btnPlay.frame = CGRectMake((mainImageView.frame.width/2)-10, (mainImageView.frame.height/2)-10, 30, 30)
btnPlay.backgroundColor = UIColor.blackColor()
btnPlay.userInteractionEnabled = true
btnPlay.addTarget(self, action: "buttonAction:", forControlEvents: .TouchUpInside)
btnPlay.setImage(UIImage(named: "Play"), forState: .Normal)
mainImageView.addSubview(btnPlay)
}
yFloatLeft = yFloatLeft + 30 + boundingRectHeight + 160
}
firstView.addSubview(lblTitle)
firstView.addSubview(lblText)
firstView.addSubview(mainImageView)
firstView.bringSubviewToFront(btnPlay)
} else {
let secondView = UIView()
if(isCheckImage == "") {
secondView.frame = CGRectMake(5, yFloatRight, self.rightView.frame.width-10, 30 + boundingRectHeight)
} else {
secondView.frame = CGRectMake(5, yFloatRight, self.rightView.frame.width-10, 180 + boundingRectHeight)
}
// secondView.backgroundColor = UIColor.purpleColor()
secondView.layer.borderWidth = 2.0
secondView.layer.borderColor = UIColor.lightGrayColor().CGColor
rightView.addSubview(secondView)
let lblTitle = UILabel()
lblTitle.frame = CGRectMake(0, 0, self.leftView.frame.width-10, 30)
lblTitle.textAlignment = NSTextAlignment.Center
lblTitle.text = myArrayOfDict[i].valueForKey("Title") as? String
let lblText = lblInset()
lblText.frame = CGRectMake(0, 30, self.leftView.frame.width-10, boundingRectHeight)
lblText.text = myArrayOfDict[i].valueForKey("Text") as? String
lblText.numberOfLines = 0
lblText.lineBreakMode = .ByWordWrapping
lblText.font = UIFont(name: "Arial", size: 16)
lblText.textAlignment = NSTextAlignment.Justified
let mainImageView = UIImageView()
if(isCheckImage == "") {
mainImageView.hidden = true
yFloatRight = yFloatRight + 30 + boundingRectHeight + 10
} else {
mainImageView.hidden = false
mainImageView.frame = CGRectMake(0, 30 + boundingRectHeight, self.leftView.frame.width-10, 150)
mainImageView.image = UIImage(named: (myArrayOfDict[i].valueForKey("Image") as? String)!)
if(isCheckVideo == "") {
btnPlay.hidden = true
} else {
btnPlay.hidden = false
btnPlay.frame = CGRectMake((mainImageView.frame.width/2)-10, (mainImageView.frame.height/2)-10, 30, 30)
btnPlay.userInteractionEnabled = true
btnPlay.backgroundColor = UIColor.blackColor()
btnPlay.setImage(UIImage(named: "Play"), forState: .Normal)
btnPlay.addTarget(self, action: Selector("buttonAction:"), forControlEvents: .TouchUpInside)
mainImageView.addSubview(btnPlay)
}
yFloatRight = yFloatRight + 30 + boundingRectHeight + 160
}
secondView.addSubview(lblTitle)
secondView.addSubview(lblText)
secondView.addSubview(mainImageView)
secondView.bringSubviewToFront(btnPlay)
}
wholeYLeft = yFloatLeft
wholeYRight = yFloatRight
}
print(wholeYLeft)
print(wholeYRight)
leftView.frame = CGRectMake(0, 0, self.view.frame.width/2, wholeYLeft)
rightView.frame = CGRectMake(self.view.frame.width/2, 0, self.view.frame.width/2, wholeYRight)
if(wholeYRight > wholeYLeft) {
self.scrollViewBase.contentSize = CGSize(width:self.view.frame.width, height: wholeYRight)
} else {
self.scrollViewBase.contentSize = CGSize(width:self.view.frame.width, height: wholeYLeft)
}
}
func buttonAction(sender:UIButton!) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("PlayViewController") as! PlayViewController
controller.lblTitle.text = myArrayOfDict[5].valueForKey("Title") as? String
controller.lblComments.text = myArrayOfDict[5].valueForKey("Text") as? String
self.presentViewController(controller, animated: true, completion: nil)
}
}
I got an Answer, In UIButton (btnPlay) add subview give UIImageView, my problem is mainImageView.addSubview(btnPlay), so change the subView to UIView instead of UIImageView correct code is
secondView.addSubview(btnPlay)
secondView.bringSubviewToFront(btnPlay)
its working for me
You have to enable user interaction for dynamically created Imageview, so write one more line after,
let mainImageView = UIImageView()
mainImageView.userInteractionEnabled = true
Hope this will work.
You have to tag the button then only it can recognise which button is that
btnPlay.tag = 1

Resources