I have a set of steppers than when added up they're supposed to give an X-amount. They're all in a UICollectionview and I used delegates to pass values between them and the ViewController.
You're supposed to allocate points among different players, once you reach the total number of points you were given to allocate you can no longer "add" points. I want to disable "half" of the stepper once the total number of points is reached. How can I do this? (without disabling the whole stepper, since the user might want to re-allocate points and return some of its points back).
Here's my code so far:
protocol CollectionVCDelegate: class {
func usedPoints() -> Int
func returnPoints() -> Int
}
class PointAllocationVC: UIViewController, CollectionVCDelegate {
func usedPoints() -> Int {
pointsToAllocate -= 1
totalPointsLabel.text = String(pointsToAllocate)
return pointsToAllocate
}
func returnPoints() -> Int
{
pointsToAllocate += 1
totalPointsLabel.text = String(pointsToAllocate)
return pointsToAllocate
}
var pointsToAllocate: Int = 5 //may change, 5 for example
#IBOutlet weak var ptsAllocView: UIView!
#IBOutlet weak var totalPointsLabel: UILabel!
#IBOutlet weak var addAllButton: UIButton!
#IBOutlet weak var ptAllocCollectionView: UICollectionView!
}
extension PointAllocationVC: UICollectionViewDelegate, UICollectionViewDataSource
{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return currentPlayers.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let myptCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ptsCell", for: indexPath) as! PtsAllocationViewCell
myptCell.playerNameLabel.text = currentPlayers[indexPath.row]
myptCell.playerScoreLabel.text = "Score: \(currentScore[indexPath.row])"
myptCell.delegate = self
if indexPath.row == 0
{
myptCell.ptsAllocStepper.minimumValue = 0
}
else
{
myptCell.ptsAllocStepper.maximumValue = 0
myptCell.isSelf = false
}
return myptCell
}
}
Now, here's the code for the ViewCells:
import UIKit
class PtsAllocationViewCell: UICollectionViewCell {
var delegate: CollectionVCDelegate? = nil
var isSelf = true
var ptsRemaining: Int = 0
#IBOutlet weak var ptsLabel: UILabel!
#IBOutlet weak var playerNameLabel: UILabel!
#IBOutlet weak var playerScoreLabel: UILabel!
#IBOutlet weak var ptsAllocStepper: UIStepper!
#IBAction func stepperTapped(_ sender: UIStepper) {
let myInt: Int = Int(ptsLabel.text!)!
if delegate != nil
{
if isSelf
{
if myInt > Int(sender.value)
{
ptsRemaining = (delegate?.returnPoints())!
}
else
{
ptsRemaining = (delegate?.usedPoints())!
}
}
else
{
if myInt > Int(sender.value)
{
ptsRemaining = (delegate?.usedPoints())!
}
else
{
ptsRemaining = (delegate?.returnPoints())!
}
}
}
ptsLabel.text = String(Int(sender.value))
}
}
NOTE: This code works so far as much as I want it to (as far as adding/subtracting from the ViewController pointsToAllocate and updating labels and all. However, as of now there are no locks preventing the user form over-usings points (say he can put 5 on each and have a total of -15 points at the end, you shouldn't be able to go below 0)
and just for added clarity here's a picture, note it will have around 4 - 6 different "players":
Set all the steppers' maximumValue to the total number of points, minus the points that were already allocated each time when a stepper's value changes. You should observe UIControlEvents.valueChanged for that.
That way, the stepper's + half will be disabled if you reach the maximum amount of points.
You probably cannot "disable the + side"...
Options:
Use two buttons, instead of a stepper. Disable the "+" button as desired, or
Set the Increment Image to indicate it's disabled when you want to disable it, and just don't process the "+" taps.
Each side of the UIStepper will be automatically disabled when it reaches its min or max value. See the answer from #the4kman
Related
I'm a Swift beginner and I'm trying to make a simple app for ordering food. The user could add a new order by setting food name, price and serving. After adding an order, that order will be shown on the tableView as a FoodTableViewCell, and the user could change the serving with an UIStepper called stepper in each cell. Each order is a FoodItem stored in an array called foodList, and you can see all orders listed in a tableView in ShoppingListVC.
My problem is: When I press "+" or "-" button on stepper, my servingLabel doesn't change to corresponding value. I tried to use NotificationCenter to pass serving value to stepper, and store new value back to food.serving after stepperValueChanged with delegate pattern. However, there still seems to be some bugs. I've been kind of confused after browsing lots of solutions on the Internet. Any help is appreciated.
Update
I removed NotificationCenter and addTarget related methods as #Tarun Tyagi 's suggestion. Now my UIStepper value turns back to 1 whereas the servingLabels are showing different numbers of serving. Since NotificationCenter doesn't help, how can I connect the label and stepper value together? Is it recommended to implement another delegate?
Here are my codes(Updated on July 8):
FoodItem
class FoodItem: Equatable {
static func == (lhs: FoodItem, rhs: FoodItem) -> Bool {
return lhs === rhs
}
var name: String
var price: Int
var serving: Int
var foodID: String
init(name: String, price: Int, serving: Int) {
self.name = name
self.price = price
self.serving = serving
self.foodID = UUID().uuidString
}
}
ViewController
import UIKit
class ShoppingListVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
var foodList = [FoodItem]()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
...
for i in 1...5 {
let testItem = FoodItem(name: "Food\(i)", price: Int.random(in: 60...100), serving: Int.random(in: 1...10))
self.foodList.append(testItem)
}
}
// MARK: - Table view data source
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "foodCell", for: indexPath) as! FoodTableViewCell
let food = foodList[indexPath.row]
cell.nameLabel.text = food.name
cell.priceLabel.text = "$\(String(food.price)) / serving"
cell.servingLabel.text = "\(String(food.serving)) serving"
cell.stepper.tag = indexPath.row
cell.delegate = self
return cell
}
}
// MARK: - FoodTableViewCellDelegate Method.
extension ShoppingListVC: FoodTableViewCellDelegate {
func stepper(_ stepper: UIStepper, at index: Int, didChangeValueTo newValue: Double) {
let indexPath = IndexPath(item: index, section: 0)
guard let cell = tableView.cellForRow(at: indexPath) as? FoodTableViewCell else { return }
let foodToBeUpdated = foodList[indexPath.row]
print("foodToBeUpdated.serving: \(foodToBeUpdated.serving)")
foodToBeUpdated.serving = Int(newValue)
print("Value changed in VC: \(newValue)")
cell.servingLabel.text = "\(String(format: "%.0f", newValue)) serving"
}
}
TableViewCell
import UIKit
protocol FoodTableViewCellDelegate: AnyObject {
func stepper(_ stepper: UIStepper, at index: Int, didChangeValueTo newValue: Double)
}
class FoodTableViewCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var servingLabel: UILabel!
#IBOutlet weak var stepper: UIStepper!
weak var delegate: FoodTableViewCellDelegate?
#IBAction func stepperValueChanged(_ sender: UIStepper) {
sender.minimumValue = 1
servingLabel.text = "\(String(format: "%.0f", sender.value)) serving"
// Pass the new value to ShoppingListVC and notify which cell to update using tag.
print("sender.value: \(sender.value)")
delegate?.stepper(stepper, at: stepper.tag, didChangeValueTo: sender.value)
}
override func awakeFromNib() {
super.awakeFromNib()
print(stepper.value)
}
}
Initially FoodTableViewCell is the ONLY target for UIStepper value changed (looking at #IBAction inside FoodTableViewCell).
When you dequeue a cell to display on screen, you call -
cell.stepper.addTarget(self, action: #selector(stepperValueChanged(_:)), for: .valueChanged)
which causes your ShoppingListVC instance to be added as an additional target every time a cellForRow call is executed.
Things to fix :
Remove all of your NotificationCenter related code from both classes.
Remove cell.stepper.addTarget() line as well.
This would give you a better idea of why it is happening this way. Update your question with these changes in case you still don't have what you want.
UPDATE
// Inside cellForRow
cell.stepper.value = food.serving
Cell Config:
protocol FoodTableViewCellDelegate: AnyObject {
func stepper(sender: FoodTableViewCell)
}
#IBAction func stepperButtonTapped(sender: UIStepper) {
delegate?.stepperButton(sender: self)
stepperLabel.text = "\(Int(countStepper.value))"
}
Controller Config:
cellForRow:
cell.countStepper.value = Double(foodList[indexPath.row].serving);
cell.stepperLabel.text = "\(Int(cell.countStepper.value))"
Delegate Method:
func stepperButton(sender: FoodTableViewCell) {
if let indexPath = tableView.indexPath(for: sender){
print(indexPath)
foodList[sender.tag].serving = Int(sender.countStepper.value)
}
}
Please check value stepper pod it will help you: Value stepper
Integrate value stepper pod and use below code for basic implementation.
import ValueStepper
let valueStepper: ValueStepper = {
let stepper = ValueStepper()
stepper.tintColor = .whiteColor()
stepper.minimumValue = 0
stepper.maximumValue = 1000
stepper.stepValue = 100
return stepper
}()
override func viewDidLoad() {
super.viewDidLoad()
valueStepper.addTarget(self, action: "valueChanged:", forControlEvents: .ValueChanged)
}
#IBAction func valueChanged1(sender: ValueStepper) {
// Use sender.value to do whatever you want
}
Its simplify custom stepper implantation.Take outlet of value stepper view in table tableview and use it.
I have a table consist of more than 20 rows and each row has 3 text field named Rate, minutes and total. calculation is as rate/60 * minutes = total. I want to get total of all 20 rows in another text field Balance that is not a part of table view cell but of view controller. I want to calculate the value in real time and get the addition of total text field named as Rupees Text field below table view cell enter image description here.I can see on 3 rows on screen and 17 other are down. I get for only 3 text field in row not for all. I h have written this code but can calculate for 3 rows not for all 20. Please do check Thanks in advance. second issue I have used notification to pass string and it send me the last value in string not the updated one . Please do check the image
import UIKit
class calculationTVC: UITableViewCell, UITextFieldDelegate{
var numberOfItems = 0
var myTV : UITableView!
#IBOutlet weak var minutes: UITextField!
#IBOutlet weak var total: UITextField!
#IBOutlet weak var rate: UITextField!
#IBAction func rateChanged(_ sender: UITextField) {
// print(minutes.text, total.text, rate.text)
ratesischanged()
}
public func ratesischanged(){
let first = Double(rate.text!)
let second = Double(minutes.text!)
let third = Double(0)
if minutes.text?.count == 0{
total.text = "\(third)"
}
if minutes.text?.count == 0{
// print("null")
total.text = "\(third)"
// print("got zero")
}else{
let output = Double((first!/60) * second!)
total.text = "\(output)"
let rows = myTV.numberOfRows(inSection: 0)
var add : Double!
var c = [Int]()
for i in 0..<rows{
let path = IndexPath(row: i, section: 0)
let cell = myTV.cellForRow(at: path) as? calculationTVC
add = (cell?.total.text as NSString?)?.doubleValue
// print(Int(add))
//print(add)
if add != nil{
c += [Int(add)]
// print(c)
}
}
var sum = 0
var counter = 0
// Enter your code below
while counter < c.count {
var newValue = c[counter]
sum += newValue
counter += 1
// print(sum, "sum")
}
var myString = String(describing: sum)
NotificationCenter.default.post(name: calculationScreen.notificationName, object: nil, userInfo: ["DataMy": myString ?? ""])
//print(ar, "new ar")
}
}
func numberOfRows(numberInt : Int,tableView : UITableView){
numberOfItems = numberInt
myTV = tableView
}
}
you can define protocol on tableViewCell and fire it when the UITextField on each cell modified, and in your viewController implement of delegate:
protocol TableViewCellDelegate: class {
func textViewValueChanged(minutes: String, rate: String, total: String)
}
class calculationTVC: UITableViewCell { // delete UITextFieldDelegate
weak var delegate: TableViewCellDelegate?
// ... the rest of your code
#IBAction func textFieldEditingChanged(_ sender: UIButton) { //action of ***Editing Changed*** and connected to all *UITextField*
//calculate total
delegate?.textViewValueChanged(minutes: self.minutes, rate: self.rate, total: self.total)
}
}
class viewController: UIViewController, UITableView, UITableViewDelegate, UITableViewdataSource, TableViewCellDelegate { //and what you want to implement
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: IndexPath) as? calculationTVC
cell.delegate = self
// ... the rest of your code
return cell
}
func textViewValueChanged(minutes: String, rate: String, total: String) {
var total = 0
for i in 1...20 {
let cell = tableView.cellForRow(at: i) as? calculationTVC
total += cell.rate/60 * cell.minutes
}
//set your totalLabel
}
}
I can't seem to make my custom collectionView Cell visible. I know that the CollectionView shows up because I changed the background color on the attributes inspector, but the custom cell is not showing up. I set the constraints in the attributes inspector and have a horizontal stack view under the image.
I followed the direction from a Udemy course exactly but it doesn't seem to work. This is how I have configured the cell to look:
The code is below:
import UIKit
class ListVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var productsCollection: UICollectionView!
private(set) public var products = [Product]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
productsCollection.dataSource = self
productsCollection.delegate = self
}
func initProducts(Product: Product) {
products = DataService.instance.getGroceryOptions()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return products.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProductCell", for: indexPath) as? ProductCell {
let product = products[indexPath.row]
cell.updateViews(product: product)
return cell
}
return ProductCell()
}
}
Here is the ProductCell implementation:
class ProductCell: UICollectionViewCell {
#IBOutlet weak var itemImage: UIImageView!
#IBOutlet weak var productName: UILabel!
#IBOutlet weak var productPrice: UILabel!
#IBOutlet weak var calCount: UILabel!
func updateViews(product: Product){
itemImage.image = UIImage(named: product.imageName)
productName.text = product.title
calCount.text = product.cal
productPrice.text = product.price
}
}
Here is the DataService implementation:
class DataService {
static let instance = DataService()
private let item = [
Product(title: "Eggs", price: "4.94", imageName: "eggs.jpeg", cal: "340"),
]
private let Groceries = [Product]()
func getGroceryOptions() -> [Product] {
return Products
}
}
Here is the Product implementation:
struct Product {
private(set) public var title: String
private(set) public var price: String
private(set) public var imageName: String
private(set) public var cal: String
init(title: String, price: String, imageName: String, cal: String) {
self.title = title
self.price = price
self.imageName = imageName
self.cal = cal
}
}
1) Your initProducts method is not called anywhere in the code.
2) You have to call collectionView.reloadData() after you update your data source. Which means, you have to call this method after updating products property.
3) Also, as other people in their answers mentioned, seems that your getGroceryOptions() method should actually return items instead of Products (what's that, btw?).
4) Please, follow swift style guide for writing your code. It will be easier for you to distinguish classes/struct from variables. You can learn more about it here and also here.
Your initProducts method is not called. Because of this products array stays empty and you see no cells in your collection.
You should call initProducts (e.g. in viewDidLoad) to fill products array with elements which will be shown in your collection.
Also consider removing parameters from this function (you're not using parameter within this method, so you don't need it there). It should look like:
func initProducts() {
products = DataService.instance.getGroceryOptions()
}
Plus you should correct getGroceryOptions method. It should return item as was pointed out in comments.
Do you have a numberOfSectionsInCollectionView section that goes before the other collectionView functions?
Take a look at this example:
func numberOfSectionsInCollectionView(collectionView:UICollectionView) -> Int {
return 1
}
I have a custom cell class given below:
class SizeAndQuantityCellView:UITableViewCell
{
#IBOutlet weak var imageview: UIImageView!
#IBOutlet weak var plusButton4x4: UIButton!
#IBOutlet weak var plusButton4x6: UIButton!
#IBOutlet weak var plusButton5x7: UIButton!
#IBOutlet weak var plusButton8x10: UIButton!
#IBOutlet weak var minusButton4x4: UIButton!
#IBOutlet weak var minusButton4x6: UIButton!
#IBOutlet weak var minusButton5x7: UIButton!
#IBOutlet weak var minusButton8x10: UIButton!
#IBOutlet weak var quantity4x4: UILabel!
#IBOutlet weak var quantity4x6: UILabel!
#IBOutlet weak var quantity5x7: UILabel!
#IBOutlet weak var quantity8x10: UILabel!
let sizeAndQuantityController = SizeAndQuantityController()
#IBAction func plusButtonClick(sender: UIButton)
{
let btnTag:Int = sender.tag
let tableView = sender.superview!.superview?.superview as! UITableView
let cellRow = tableView.indexPathForCell(self)?.row
sizeAndQuantityController.plusButtonClick(btnTag,cellRow: cellRow!)
}
#IBAction func minusButtonClick(sender: UIButton)
{
let btnTag:Int = sender.tag
let tableView = sender.superview!.superview?.superview as! UITableView
let cellRow = tableView.indexPathForCell(self)?.row
sizeAndQuantityController.plusButtonClick(btnTag,cellRow: cellRow!)
}
}
What i want to do is when i click the plus button the quantity should increase by one and when i click the minus button it should decrease by one.
Here's my controller class for that:
class SizeAndQuantityController
{
func plusButtonClick(tag:Int,cellRow:Int)
{
switch tag
{
case 13:
let quant = quantity4x4[cellRow]
quantity4x4[cellRow] = quant+1
break;
case 14:
let quant = quantity4x6[cellRow]
quantity4x6[cellRow] = quant+1
break;
case 15:
let quant = quantity5x7[cellRow]
quantity5x7[cellRow] = quant+1
break;
case 16:
let quant = quantity8x10[cellRow]
quantity8x10[cellRow] = quant+1
break;
default:
break
}
}
func minusButtonClick(tag:Int,cellRow:Int)
{
switch tag
{
case 17:
let quant = quantity4x4[cellRow]
quantity4x4[cellRow] = quant-1
break;
case 18:
let quant = quantity4x6[cellRow]
quantity4x6[cellRow] = quant-1
break;
case 19:
let quant = quantity5x7[cellRow]
quantity5x7[cellRow] = quant-1
break;
case 20:
let quant = quantity8x10[cellRow]
quantity8x10[cellRow] = quant-1
break;
default:
break
}
}
i have given different tags to all the buttons.
when i run the app it gives me the following error: "Could not cast value of type UITableViewWrapperView to UITableView" at the line where i set my tableview.
Doing sender.superview!.superview?.superview as! UITableView is very dangerous. In the transition between iOS6 and iOS7, an extra layer was actually introduced and that kind of call failed.
Rather just have a property rowIndex in cell, which you set in your cellForRowAtIndexPath. For Example:
class SizeAndQuantityCellView:UITableViewCell
{
var rowIndex: Int = 0
...
}
In your TableViewController
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myTableViewCell", for: indexPath) as! SizeAndQuantityCellView
cell.rowIndex = indexPath.row
...
return cell
}
From your code, it is not clear where quantity4x4[cellRow], for example, fits in but it seems to me that a Delegation Pattern might also be handy. I.o.w. Create a delegate protocol for SizeAndQuantityCellView and let your ViewController be the delegate of SizeAndQuantityCellView. When the buttons is tapped, fire an event to the delegate. That way your ViewController can handle the logic upon the pressing of the buttons.
A more sofisticated approach, involves the use of extensions and bitwise operator. Simplifying, you can use the tag property built-in with every UIButton, to store the whole value of of and IndexPath (that is identified by a row and a section) by packing it using bitwise operators and shifting.
Once the value is stored, you can use the computed property technique by extending your UIButton class and returning a new IndexPath that is created by unpacking the original values.
Below there's a simple extension that do the job:
extension UIButton {
func packing(low:Int, high:Int) -> Int {
//With the packing function we force our Packed number to be a 64 bit one
//we shift the high part 32bits to the left and OR the resulting value with the low part
return ((high << 32) | low)
}
func unpackHigh(packed:Int) -> Int {
//Unpacking the high part involve swifting to right the
//number in order to zero'ing all the non relevant bits.
return packed >> 32
}
func unpackLow(packed:Int) -> Int {
//Unpacking the low part involve masking the whole packed number with the max value allowed for an Int.
//note that using the Int.max function does not work as expected, returning a compile error.
//Maybe, it's a bug of compiler.
let mask = 2147483647
return mask & packed
}
//since we cannot use stored property on extensions, we need to compute realtime, every time the
//right value of our indexPath.
var indexPath:IndexPath {
get {
return IndexPath(row: unpackLow(packed: self.tag), section: unpackHigh(packed: self.tag))
}
set {
self.tag = packing(low: newValue.row, high: newValue.section)
}
}
}
and here you can find a simple application on a prototype cellForRowAtIndexPath:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let aCell = tableView.dequeueReusableCell(withIdentifier: "reuseCell") as! CustomTableViewCell
...
aCell.aButton.indexPath = indexPath
...
return aCell
}
note that you need to pass, after the dequeue, the right indexPath to the cell, in order to trigger the extension methods.
I have a View named AlarmView and a tableview named alarmtableview inside AlarmView , also I have a textfield
Now What I want is when a user enters any number in textfield , tableview will be reloaded with number of rows equal to that number entered by the user.
I have set the AlarmView height as 0 initially , so that when the textfield is empty AlarmView remains invisible from the users.
And after reloading the alarmtableview , I am updating the detailview's height equal to tableview's height.
But when I run the app the view's height is not updated. it remains invisible from the users even after reloading the tableview
Below Is the code I have written to achieve the same
#IBOutlet weak var AlarmViewHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var AlarmView: UIView!
#IBOutlet weak var AlarmTableView: UITableView!
#IBOutlet weak var FrequencyField: CustomUITextField!
func textFieldDidEndEditing(textField: UITextField) {
print("textFieldDidEndEditing called")
if textField === FrequencyField{
self.AlarmToggleAction(self.AlarmSwitch)
}
}
//MARK: ALARM Actions
#IBAction func AlarmToggleAction(sender: UISwitch) {
if sender.on{
if let count = Int(self.FrequencyField.text!) {
print("ON state")
alarmCount = count
AlarmTableView.reloadData()
print("AlarmTableView.frame.height : \(AlarmTableView.frame.height)")
AlarmViewHeightConstraint.constant = AlarmTableView.frame.height
}
}
else{
print("OFF state")
alarmCount = 0
//AlarmTableView.reloadData()
//AlarmViewHeightConstraint.constant = 0
}
}
//MARK: Tableview Actions
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("numberOfRowsInSection called alarmCount : \(alarmCount)")
return alarmCount
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("cellForRowAtIndexPath called")
let cell = tableView.dequeueReusableCellWithIdentifier("AlarmCell") as! AlarmCell
cell.TimeLabel.text = "Alarm \(indexPath.row + 1)"
cell.TimeField.tag = indexPath.row
cell.TimeSwitch.tag = indexPath.row
return cell
}
Please help me out of this problem.
Thanks in advance
Try using contentSize instead of frame size like:
AlarmViewHeightConstraint.constant = AlarmTableView.contentSize.height