当 KILabel 或 ActiveLabel 没有字符串时,将其高度设置为 0。但原始 UILabel 工作正常

Posted

技术标签:

【中文标题】当 KILabel 或 ActiveLabel 没有字符串时,将其高度设置为 0。但原始 UILabel 工作正常【英文标题】:Set the KILabel or ActiveLabel's height to 0 when it has no string. But Original UILabel is working fine 【发布时间】:2016-08-23 16:34:37 【问题描述】:

这个问题与UITableView和UILabel的高度有关。

您好,我正在使用自动布局来设置行中的动态高度。

这是我在表格单元格中的布局。

描述标签

LikeCountLabel 为蓝色“1”

评论标签

时间表是灰色的“标签”

时间标签

我还检查了 UILabel 的属性

import UIKit
import Parse

class ShopDetailCell: UITableViewCell 

@IBOutlet weak var commentBtn: UIButton!
    @IBOutlet weak var likeBtn: UIButton!
    @IBOutlet weak var profileImg: UIImageView!
    @IBOutlet weak var postImg: UIImageView!

    @IBOutlet weak var moreBtn: UIButton!
    @IBOutlet weak var userNameBtn: UIButton!
    @IBOutlet weak var uuidLabel: UILabel!
    @IBOutlet weak var descriptionLabel: KILabel!
    @IBOutlet weak var likesLabel: UILabel!


    @IBOutlet weak var commentLabel: KILabel!

    @IBOutlet weak var dateLabel: UILabel!


我的 TableView 控制器

import UIKit
import Parse
import SDWebImage

class FeedVC: UITableViewController 

    //UI Objects
    @IBOutlet weak var indicator: UIActivityIndicatorView!
    var refresher=UIRefreshControl()

    //arrays to hold server data
    var profileArray = [PFFile]()
    var usernameArray = [String]()
    var dateArray = [NSDate?]()

    var postArray = [PFFile]()
    var uuidArray = [String]()
    var descriptionArray = [String]()

    var commentsArray = [String]()

    var isLoadedView:Bool = false


    var sellingArray = [Bool]()

    var followArray = [String]()


    //advertise
    var advArray = [PFFile]()

    //page size
    var page : Int = 10



    //Default func
    override func viewDidLoad() 
        super.viewDidLoad()

        //background color
        tableView?.backgroundColor = UIColor(red: 0.0 / 255.0, green: 0.0 / 255.0, blue: 0.0 / 255.0, alpha: 1)


        //automatic row height
        tableView.estimatedRowHeight = 450
        tableView.rowHeight = UITableViewAutomaticDimension

        //pull to refresh
        refresher.addTarget(self, action: #selector(FeedVC.loadPosts), forControlEvents: UIControlEvents.ValueChanged)
        tableView.addSubview(refresher)

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(FeedVC.refresh), name: "liked", object: nil)

         NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(FeedVC.uploaded(_:)), name: "Uploaded", object: nil)


        self.navigationController?.setNavigationBarHidden(true, animated: true)
        //calling function to load posts
        loadPosts()



        //receive notification from UploadViewController
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(FeedVC.scrollToFirstRow(_:)), name: "scrollToTop", object: nil)

    



    func scrollToFirstRow(notification:NSNotification) 

        if isLoadedView == true 
            print("scrollToTop!!!!!")
            let indexPath = NSIndexPath(forRow: 0, inSection: 0)
            self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
        
    

    // reloading func with posts after received notification
    func uploaded(notification:NSNotification)
        print("receicev")
        loadPosts()
    

    //refresh function
    func refresh()

        self.tableView.reloadData()
    


    // load posts
    func loadPosts() 

        //STEP 1. Find posts related to people who we are following
        let followQuery = PFQuery(className: "fans")

        followQuery.whereKey("myfans", equalTo: PFUser.currentUser()!.username!)
        followQuery.findObjectsInBackgroundWithBlock ( (objects:[PFObject]?, error:NSError?) -> Void in

            if error == nil 
                //clean up
                self.followArray.removeAll(keepCapacity: false)

                //Appending where people following..
                //find related objects
                for object in objects! 
                    self.followArray.append(object.objectForKey("fan") as! String)
                
                //append current user to see own posts in feed
                self.followArray.append(PFUser.currentUser()!.username!)


                //STEP 2. Find posts made by people appended to followArray
                let query = PFQuery(className: "posts")
                query.whereKey("username", containedIn: self.followArray)
                query.limit = self.page
                query.addDescendingOrder("createdAt")
                query.findObjectsInBackgroundWithBlock( (objects:[PFObject]?, error:NSError?) -> Void in

                    if error == nil 

                        //clean up
                        self.usernameArray.removeAll(keepCapacity: false)
                        self.profileArray.removeAll(keepCapacity: false)
                        self.dateArray.removeAll(keepCapacity: false)
                        self.postArray.removeAll(keepCapacity: false)
                        self.descriptionArray.removeAll(keepCapacity: false)

                        self.uuidArray.removeAll(keepCapacity: false)

                        //find related objects
                        for object in objects! 
                            self.usernameArray.append(object.objectForKey("username") as! String)
                            self.profileArray.append(object.objectForKey("profileImg") as! PFFile)
                            self.dateArray.append(object.createdAt)
                            self.postArray.append(object.objectForKey("postImg") as! PFFile)
                            self.descriptionArray.append(object.objectForKey("title") as! String)
                            self.uuidArray.append(object.objectForKey("uuid") as! String)


                        


                        //reload tableView & end spinning of refresher
                        self.tableView.reloadData()
                        self.refresher.endRefreshing()

                     else 


                        print(error!.localizedDescription)
                    
                )


             else 
                print(error!.localizedDescription)
            

        )


    

    //scrolled down
    override func scrollViewDidScroll(scrollView: UIScrollView) 

        if scrollView.contentOffset.y >= scrollView.contentSize.height - self.view.frame.size.height * 2 

                loadMore()
        
    

    // pagination
    func loadMore()

        //if posts on the server are more than shown
        if page <= uuidArray.count 

            //start animating indicator
            indicator.startAnimating()

            //increase page size to load + 10 posts
            page = page + 10


            //STEP 1. Find posts related to people who we are following
            let followQuery = PFQuery(className: "fans")

            followQuery.whereKey("myfans", equalTo: PFUser.currentUser()!.username!)
            followQuery.findObjectsInBackgroundWithBlock ( (objects:[PFObject]?, error:NSError?) -> Void in

                if error == nil 
                    //clean up
                    self.followArray.removeAll(keepCapacity: false)

                    //Appending where people following..
                    //find related objects
                    for object in objects! 
                        self.followArray.append(object.objectForKey("fan") as! String)
                    
                    //append current user to see own posts in feed
                    self.followArray.append(PFUser.currentUser()!.username!)


                    //STEP 2. Find posts made by people appended to followArray
                    let query = PFQuery(className: "posts")
                    query.whereKey("username", containedIn: self.followArray)
                    query.limit = self.page
                    query.addDescendingOrder("createdAt")
                    query.findObjectsInBackgroundWithBlock( (objects:[PFObject]?, error:NSError?) -> Void in

                        if error == nil 

                            //clean up
                            self.usernameArray.removeAll(keepCapacity: false)
                            self.profileArray.removeAll(keepCapacity: false)
                            self.dateArray.removeAll(keepCapacity: false)
                            self.postArray.removeAll(keepCapacity: false)
                            self.descriptionArray.removeAll(keepCapacity: false)
                            self.uuidArray.removeAll(keepCapacity: false)

                          //find related objects

                            for object in objects! 
                                self.usernameArray.append(object.objectForKey("username") as! String)
                                self.profileArray.append(object.objectForKey("profileImg") as! PFFile)
                                self.dateArray.append(object.createdAt)
                                self.postArray.append(object.objectForKey("postImg") as! PFFile)
                                self.descriptionArray.append(object.objectForKey("title") as! String)
                                self.uuidArray.append(object.objectForKey("uuid") as! String)




                            


                            //reload tableView stop indicator animation
                            self.tableView.reloadData()
                            self.indicator.stopAnimating()

                         else 
                            print(error!.localizedDescription)
                        
                    )
                 else 
                    print(error!.localizedDescription)
                

            )

        

    


    //number of cell
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return uuidArray.count + 1
    


    // cell config
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 


        // 가장 첫 페이지는 광고영역..
        if indexPath.row == 0 

            let cell = tableView.dequeueReusableCellWithIdentifier("AdvertiseCell", forIndexPath: indexPath) as! AdvertiseCell

            return cell

        


        //define cell
        let cell = tableView.dequeueReusableCellWithIdentifier("ShopDetailCell", forIndexPath: indexPath) as! ShopDetailCell


        cell.userNameBtn.setTitle(usernameArray[indexPath.row - 1], forState: UIControlState.Normal)
        cell.userNameBtn.sizeToFit()


        cell.uuidLabel.text = uuidArray[indexPath.row - 1]

        cell.descriptionLabel.text = descriptionArray[indexPath.row - 1]
        cell.descriptionLabel.sizeToFit()


        // manipulate like button depending on did user like it or not
        let isComments = PFQuery(className: "comments")
        isComments.whereKey("to", equalTo: cell.uuidLabel.text!)
        isComments.limit = 1
        isComments.addAscendingOrder("createdAt")

        isComments.countObjectsInBackgroundWithBlock((count:Int32, error:NSError?) -> Void in

            //if no any likes are found, else found likes
            if count==0 
                cell.commentLabel.text = nil
                cell.commentLabel.sizeToFit()
//                cell.commentHeight.constant = 0

            else


                //STEP 2. Request last (page size 15) comments
                let query = PFQuery(className: "comments")
                query.whereKey("to", equalTo: cell.uuidLabel.text!)
                query.limit = 1
                query.addDescendingOrder("createdAt")
                query.findObjectsInBackgroundWithBlock((objects:[PFObject]?, error:NSError?) -> Void in

                    if error == nil 

                        //find related object
                        for object in objects!

                            let comment = object.objectForKey("comment") as! String
                            let by = object.objectForKey("username") as! String



                            let commentString = by + " " + comment
                            let boldString = NSMutableAttributedString(string: commentString)


                            boldString.addAttribute(NSFontAttributeName, value: UIFont(name: "SFUIText-Bold", size: 14)!, range: NSRange(0...by.characters.count))

                            cell.commentLabel.attributedText = boldString

                            cell.commentLabel.sizeToFit()
//                            self.tableView?.reloadData()



                        
                    else 
                        print(error?.localizedDescription)
                    
                )


            

        )


        //STEP 1. Load data of guest
        let profileImgQuery = PFQuery(className: "_User")
        profileImgQuery.whereKey("username", equalTo: usernameArray[indexPath.row - 1])

        profileImgQuery.findObjectsInBackgroundWithBlock((objects:[PFObject]?, error:NSError?) -> Void in

            if error == nil 

                //shown wrong user
                if objects!.isEmpty 
                    print("Wrong User")
                

                //find related to user information
                for object in objects! 

                    //Set Image
                    let profilePictureObject = object.objectForKey("profileImg") as? PFFile
                    profilePictureObject?.getDataInBackgroundWithBlock  (imageData:NSData?, error:NSError?) -> Void in

                        if(imageData != nil)
                        

                            let profileURL : NSURL = NSURL(string: profilePictureObject!.url!)!

                            cell.profileImg.sd_setImageWithURL(profileURL, placeholderImage: UIImage(named: "holderImg"))
                        

                    

                
             else 
                print(error?.localizedDescription)
            

        )

        // place post picture using the sdwebimage
        let postURL : NSURL = NSURL(string: postArray[indexPath.row - 1].url!)!
        cell.postImg.sd_setImageWithURL(postURL, placeholderImage: UIImage(named: "holderImg"))




        //Calculate post date
        let from = dateArray[indexPath.row - 1]
        let now = NSDate()

        let components : NSCalendarUnit = [.Second, .Minute, .Hour, .Day, .WeekOfMonth]

        let difference = NSCalendar.currentCalendar().components(components, fromDate: from!, toDate: now, options: [])


        // logic what to show : Seconds, minutes, hours, days, or weeks
        if difference.second <= 0 
            cell.dateLabel.text = "NOW"
        

        if difference.second > 0 && difference.minute == 0 

            cell.dateLabel.text = "\(difference.second) SEC AGO"
        

        if difference.minute > 0 && difference.hour == 0 

            cell.dateLabel.text = "\(difference.minute) MIN AGO"
        

        if difference.hour > 0 && difference.day == 0 
            cell.dateLabel.text = "\(difference.hour) HR AGO"

        

        if difference.day > 0 && difference.weekOfMonth == 0 

            cell.dateLabel.text = "\(difference.day) DAY AGO"
        

        if difference.weekOfMonth > 0 
            cell.dateLabel.text = "\(difference.weekOfMonth) WEEK AGO"
        
        //
        //



        // manipulate like button depending on did user like it or not
        let didLike = PFQuery(className: "likes")
        didLike.whereKey("by", equalTo: PFUser.currentUser()!.username!)
        didLike.whereKey("to", equalTo: cell.uuidLabel.text!)
        didLike.countObjectsInBackgroundWithBlock((count:Int32, error:NSError?) -> Void in

            //if no any likes are found, else found likes
            if count==0 

                cell.likeBtn.setTitle("unlike", forState: .Normal)
                cell.likeBtn.setBackgroundImage(UIImage(named:"heartBtn"), forState: .Normal)
            else

                cell.likeBtn.setTitle("like", forState: .Normal)
                cell.likeBtn.setBackgroundImage(UIImage(named: "heartTapBtn"), forState: .Normal)

            

        )

        //count total likes of shown post
        let countLikes = PFQuery(className: "likes")
        countLikes.whereKey("to", equalTo: cell.uuidLabel.text!)
        countLikes.countObjectsInBackgroundWithBlock((count:Int32, error:NSError?) -> Void in

            cell.likesLabel.text="\(count) likes"
        )

        //asign index
        cell.userNameBtn.layer.setValue(indexPath, forKey: "index")
        cell.commentBtn.layer.setValue(indexPath, forKey: "index")
        cell.moreBtn.layer.setValue(indexPath, forKey: "index")


        // @mention is tapped
        cell.descriptionLabel.userHandleLinkTapHandler =  label, handle, rang in
            var mention = handle
            mention = String(mention.characters.dropFirst())
            if mention.lowercaseString == PFUser.currentUser()?.username 
                let home = self.storyboard?.instantiateViewControllerWithIdentifier("MyShopCollectionVC") as! MyShopCollectionVC
                self.navigationController?.pushViewController(home, animated: true)
             else 
                guestname.append(mention.lowercaseString)
                let guest = self.storyboard?.instantiateViewControllerWithIdentifier("GuestShopCollectionVC") as! GuestShopCollectionVC
                self.navigationController?.pushViewController(guest, animated: true)
            
        

        // #Hashtag is tapped
        cell.descriptionLabel.hashtagLinkTapHandler = label, handle, range in
            var mention = handle
            mention = String(mention.characters.dropFirst())
            hashtag.append(mention.lowercaseString)
            let hashvc = self.storyboard?.instantiateViewControllerWithIdentifier("HashTagsCollectionVC") as! HashTagsCollectionVC
            self.navigationController?.pushViewController(hashvc, animated: true)


        


//        cell.layoutIfNeeded()

        return cell




    




    ////////

    @IBAction func userNameBtnTapped(sender: AnyObject) 


        //call index of button

        let i = sender.layer.valueForKey("index") as! NSIndexPath

        //call cell to call further cell data
        let cell = tableView.cellForRowAtIndexPath(i) as! ShopDetailCell

        //if user tapped on himeself go home, else go guest
        if cell.userNameBtn.titleLabel?.text == PFUser.currentUser()?.username 

            let home = self.storyboard?.instantiateViewControllerWithIdentifier("MyShopCollectionVC") as! MyShopCollectionVC
            self.navigationController?.pushViewController(home, animated: true)
        else 

            guestname.append(cell.userNameBtn.titleLabel!.text!)
            let guest = self.storyboard?.instantiateViewControllerWithIdentifier("GuestShopCollectionVC") as! GuestShopCollectionVC
            self.navigationController?.pushViewController(guest, animated: true)

        


    

    @IBAction func commentBtnTapped(sender: AnyObject) 

        print("commentTapped")

        // call index of button
        let i = sender.layer.valueForKey("index") as! NSIndexPath

        // call cell to call further cell data
        let cell = tableView.cellForRowAtIndexPath(i) as! ShopDetailCell

        //send related data to global variables
        commentUUID.append(cell.uuidLabel.text!)
        //            commentOwner.append(cell.userNameLabel.titleLabel!.text!)
        commentOwner.append(cell.userNameBtn.titleLabel!.text!)

        let comment = self.storyboard?.instantiateViewControllerWithIdentifier("CommentVC") as! CommentVC

        self.navigationController?.pushViewController(comment, animated: true)
    

    @IBAction func moreBtnTapped(sender: AnyObject) 

        let i = sender.layer.valueForKey("index") as! NSIndexPath

        //Call cell to call further cell date
        let cell = tableView.cellForRowAtIndexPath(i) as! ShopDetailCell

        //Delete Action
        let delete = UIAlertAction(title: "Delete", style: .Default)  (UIAlertAction) -> Void in

            //STEP 1. Delete row from tablevIEW
            self.usernameArray.removeAtIndex(i.row)
            self.profileArray.removeAtIndex(i.row)
            self.dateArray.removeAtIndex(i.row)
            self.postArray.removeAtIndex(i.row)
            self.descriptionArray.removeAtIndex(i.row)
            self.uuidArray.removeAtIndex(i.row)

            //STEP 2. Delete post from server
            let postQuery = PFQuery(className: "posts")
            postQuery.whereKey("uuid", equalTo: cell.uuidLabel.text!)
            postQuery.findObjectsInBackgroundWithBlock( (objects:[PFObject]?, error:NSError?) -> Void in

                if error == nil 
                    for object in objects! 

                        object.deleteInBackgroundWithBlock( (success:Bool, error:NSError?) -> Void in
                            if success 

                                //send notification to rootViewController to update shown posts
                                NSNotificationCenter.defaultCenter().postNotificationName("uploaded", object: nil)

                                //push back
                                self.navigationController?.popViewControllerAnimated(true)

                             else 
                                print(error?.localizedDescription)
                            
                        )
                    
                 else 
                    print(error?.localizedDescription)
                

            )

            //STEP 2. Delete likes of post from server
            let likeQuery = PFQuery(className: "likes")
            likeQuery.whereKey("to", equalTo: cell.uuidLabel.text!)
            likeQuery.findObjectsInBackgroundWithBlock( (objects:[PFObject]?, error:NSError?) -> Void in
                if error == nil 
                    for object in objects! 
                        object.deleteEventually()
                    
                
            )

            //STEP 3. Delete comments of post from server
            let commentQuery = PFQuery(className: "comments")
            commentQuery.whereKey("to", equalTo: cell.uuidLabel.text!)
            commentQuery.findObjectsInBackgroundWithBlock( (objects:[PFObject]?, error:NSError?) -> Void in
                if error == nil 
                    for object in objects! 
                        object.deleteEventually()

                    
                
            )

            //STEP 4. Delete hashtags of post from server
            let hashtagQuery = PFQuery(className: "hashtags")
            hashtagQuery.whereKey("to", equalTo: cell.uuidLabel.text!)
            hashtagQuery.findObjectsInBackgroundWithBlock( (objects:[PFObject]?, error:NSError?) -> Void in
                if error == nil 
                    for object in objects! 

                        object.deleteEventually()
                    
                
            )
        


        //Complain Action
        let complain = UIAlertAction(title: "Complain", style: .Default)  (UIAlertAction) -> Void in

            //send complain to server
            let complainObj = PFObject(className: "complain")
            complainObj["by"] = PFUser.currentUser()?.username
            complainObj["to"] = cell.uuidLabel.text
            complainObj["owner"] = cell.userNameBtn.titleLabel?.text
            complainObj.saveInBackgroundWithBlock( (success:Bool, error:NSError?) -> Void in
                if success 

                    self.alert("Complain has been made successfully", message: "Thank You! We will consider your complain")
                else 
                    self.alert("ERROR", message: error!.localizedDescription)
                
            )


        

        //Cancel ACTION
        let cancel = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)

        //create menu controller
        let menu = UIAlertController(title: "Menu", message: nil, preferredStyle: .ActionSheet)

        //if post belongs to user
        if cell.userNameBtn.titleLabel?.text == PFUser.currentUser()?.username 
            menu.addAction(delete)
            menu.addAction(cancel)
         else 
            menu.addAction(complain)
            menu.addAction(cancel)
        

        //show menu
        self.presentViewController(menu, animated: true, completion: nil)


    

    //alert action
    func alert(title: String, message:String)
        let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
        let ok = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
        alert.addAction(ok)
        presentViewController(alert, animated: true, completion: nil)

    



好吧,我的问题是……如果 UILabel 的字符串是 nil 或 "" 那么它的高度应该设置为零。表格单元格的高度也小于原始高度。

UILabel 没有字符串,但它仍然有高度。

【问题讨论】:

嘿,你找到解决办法了吗?因为我面临同样的问题 【参考方案1】:

似乎这是KILabel库中的问题,解决方案是(link)创建自定义标签类,继承自KILabel并覆盖此方法:

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines 
    if (self.text.length == 0) 
        return CGRectZero;
    
    return [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];

【讨论】:

【参考方案2】:

像这样声明你的UILabel 高度约束:-

@IBOutlet weak var likeLabelHeightConstraint: NSLayoutConstraint!   

然后像这样设置你的身高

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 

let height : CGFloat = 50  //Default cell Height
   if likeLabel.text == nil || likeLabel.text == ""

               height = height - likeLabelHeightConstraint.constant
               likeLabelHeightConstraint.constant = 0

         else

                 //Set default scenario
         
 return height

如果您正在检索数据 asynchronously,请确保在 DataSource 更新后重新加载数据....

【讨论】:

感谢您的回复。我的单元格已定义..DetailCell.swift。所以我试图在你的建议中声明,但我收到了“访问不正确”的消息。让 cell = tableView.dequeueReusableCellWithIdentifier("ShopDetailCell", forIndexPath: indexPath) as! ShopDetailCell 为您的表格视图类代码和自定义单元格类提供您遇到的实际错误 只有当我将 UILabel 更改为 KILabel 或 ActiveLabel 时才会发生这种情况。所以我认为这不是自动布局问题。但是有人知道这个问题吗?我该如何解决这个问题?

以上是关于当 KILabel 或 ActiveLabel 没有字符串时,将其高度设置为 0。但原始 UILabel 工作正常的主要内容,如果未能解决你的问题,请参考以下文章

UILabel 具有来自编程约束的内部填充

UILabel 垂直对齐

从标签Regex中删除点

当 XIB 没有时,UIImageView 在模拟器中调整大小

当其他编译器没有时,MinGW gcc 会出错

没注入 就旁注