Loading remote image with DTAttributeTextContentView - ios

I am developing an application for an online forum with DTCoreText to display thread replies that parsed from BBCode to HTML with text and images inside custom cells in a UITableView. I use interface builder to build my prototype cell and link it to my custom cell class using outlets. Texts are displaying correctly but the images are not loading and leaves a empty space inside the cell view. Heres my view controller and cell class code
My View Controller:
//
import UIKit
import NVActivityIndicatorView
class ContentViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
//MARK: Properties
var threadIdReceived: String = ""
var channelNow: String = ""
var isRated: Bool = false
var pageNow: Int = 1
var convertedText: String = ""
var op = OP(t: "",n: "",l: "",c: "",cH: "",a: "",d: "",gd: "",b: "",ge: "",ch: "")
var comments = [Replies]()
var replyCount = 1
#IBOutlet weak var contentTableView: UITableView!
#IBOutlet weak var pageButton: UIBarButtonItem!
#IBOutlet weak var goodCount: UIBarButtonItem!
#IBOutlet weak var badCount: UIBarButtonItem!
#IBOutlet weak var prevButton: UIBarButtonItem!
#IBOutlet weak var nextButton: UIBarButtonItem!
let backgroundIndicator = NVActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height),type: .ballPulseSync,padding: 175)
//HKGalden API (NOT included in GitHub repo)
var api = HKGaldenAPI()
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.tintColor = UIColor.white
self.navigationController?.navigationBar.isTranslucent = true
contentTableView.delegate = self
contentTableView.dataSource = self
backgroundIndicator.startAnimating()
self.view.addSubview(backgroundIndicator)
self.prevButton.isEnabled = false
self.pageButton.title = "第" + String(pageNow) + "頁"
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
contentTableView.isHidden = true
api.fetchContent(postId: threadIdReceived, pageNo: String(pageNow), completion: {
[weak self] op,comments,error in
if (error == nil) {
self?.op = op
self?.comments = comments
self?.title = op.title
self?.goodCount.title = op.good
self?.badCount.title = op.bad
self?.contentTableView.reloadData()
self?.backgroundIndicator.isHidden = true
self?.contentTableView.isHidden = false
self?.contentTableView.tableFooterView = UIView()
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (comments.count) + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ContentTableViewCell", for: indexPath) as! ContentTableViewCell
if(indexPath.row == 0) {
cell.configureOP(opData: op)
}
else {
cell.configureReply(comments: comments, indexPath: indexPath,pageNow: pageNow)
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func changePage(_ sender: UIBarButtonItem) {
switch (sender.tag) {
case 0:
contentTableView.isHidden = true
backgroundIndicator.isHidden = false
self.pageNow -= 1
self.pageButton.title = "第" + String(self.pageNow) + "頁"
self.api.fetchContent(postId: threadIdReceived, pageNo: String(pageNow), completion: {
[weak self] op,comments,error in
if (error == nil) {
self?.op = op
self?.comments = comments
self?.title = op.title
self?.goodCount.title = op.good
self?.badCount.title = op.bad
self?.contentTableView.reloadData()
self?.backgroundIndicator.isHidden = true
self?.contentTableView.isHidden = false
self?.contentTableView.tableFooterView = UIView()
}
})
case 1:
self.prevButton.isEnabled = true
contentTableView.isHidden = true
backgroundIndicator.isHidden = false
self.pageNow += 1
self.pageButton.title = "第" + String(self.pageNow) + "頁"
self.api.fetchContent(postId: threadIdReceived, pageNo: String(pageNow), completion: {
[weak self] op,comments,error in
if (error == nil) {
self?.op = op
self?.comments = comments
self?.title = op.title
self?.goodCount.title = op.good
self?.badCount.title = op.bad
self?.contentTableView.reloadData()
self?.backgroundIndicator.isHidden = true
self?.contentTableView.isHidden = false
self?.contentTableView.tableFooterView = UIView()
}
})
default:
print("nothing")
}
}
//MARK: Private Functions
private func barTintColorChanger(channelId: String) {
switch channelId {
case "bw":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 72/255, green: 125/255, blue: 174/255, alpha: 1)
case "et":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 152/255, green: 85/255, blue: 159/255, alpha: 1)
case "ca":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 33/255, green: 136/255, blue: 101/255, alpha: 1)
case "fn":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 33/255, green: 136/255, blue: 101/255, alpha: 1)
case "gm":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 37/255, green: 124/255, blue: 201/255, alpha: 1)
case "ap":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 41/255, green: 145/255, blue: 185/255, alpha: 1)
case "it":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 94/255, green: 106/255, blue: 125/255, alpha: 1)
case "mp":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 88/255, green: 100/255, blue: 174/255, alpha: 1)
case "sp":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 152/255, green: 64/255, blue: 81/255, alpha: 1)
case "lv":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 196/255, green: 53/255, blue: 94/255, alpha: 1)
case "sy":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 127/255, green: 112/255, blue: 106/255, alpha: 1)
case "ed":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 65/255, green: 143/255, blue: 66/255, alpha: 1)
case "tm":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 190/255, green: 71/255, blue: 30/255, alpha: 1)
case "tr":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 97/255, green: 118/255, blue: 83/255, alpha: 1)
case "an":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 171/255, green: 80/255, blue: 159/255, alpha: 1)
case "to":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 148/255, green: 95/255, blue: 50/255, alpha: 1)
case "mu":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 88/255, green: 95/255, blue: 202/255, alpha: 1)
case "vi":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 121/255, green: 78/255, blue: 126/255, alpha: 1)
case "dc":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 56/255, green: 102/255, blue: 118/255, alpha: 1)
case "st":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 128/255, green: 113/255, blue: 143/255, alpha: 1)
case "ts":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 172/255, green: 48/255, blue: 66/255, alpha: 1)
case "mb":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 124/255, green: 89/255, blue: 196/255, alpha: 1)
case "ia":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 132/255, green: 169/255, blue: 64/255, alpha: 1)
case "ac":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 150/255, green: 75/255, blue: 112/255, alpha: 1)
case "ep":
self.navigationController?.navigationBar.barTintColor = UIColor(red: 152/255, green: 112/255, blue: 93/255, alpha: 1)
default:
self.navigationController?.navigationBar.barTintColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1)
}
}
}
And heres my cell class:
import UIKit
import Kingfisher
import DTCoreText
class ContentTableViewCell: UITableViewCell, DTAttributedTextContentViewDelegate, DTLazyImageViewDelegate {
//MARK: Properties
#IBOutlet weak var userNameLabel: UILabel!
#IBOutlet weak var userLevelLabel: UILabel!
#IBOutlet weak var userAvatarImageView: UIImageView!
#IBOutlet weak var replyCountLabel: UILabel!
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var contentTextView: DTAttributedTextContentView!
let attributedOptions: NSDictionary = [
NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.html,
NSAttributedString.DocumentAttributeKey.characterEncoding: String.Encoding.utf8,
DTDefaultFontFamily: "Helvetica Neue",
DTDefaultFontSize: 15,
DTMaxImageSize: CGSize(width:280,height:450)
]
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
contentTextView.shouldDrawImages = false
contentTextView.delegate = self as DTAttributedTextContentViewDelegate
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func attributedTextContentView(_ attributedTextContentView: DTAttributedTextContentView!, viewFor attachment: DTTextAttachment!, frame: CGRect) -> UIView! {
if attachment is DTImageTextAttachment {
let imageView = DTLazyImageView(frame: frame)
imageView.contentView = contentTextView
imageView.delegate = self as DTLazyImageViewDelegate
//url for deferred loading
imageView.url = attachment.contentURL
imageView.shouldShowProgressiveDownload = true
return imageView
}
return nil
}
func lazyImageView(_ lazyImageView: DTLazyImageView!, didChangeImageSize size: CGSize) {
let url = lazyImageView.url
let pred = NSPredicate(format: "contentURL == %#",url! as CVarArg)
let array = self.contentTextView.layoutFrame.textAttachments(with: pred)
for _ in (array?.enumerated())! {
let element = DTTextAttachment()
element.originalSize = size
element.displaySize = size
}
contentTextView.layouter = nil
contentTextView.relayoutText()
}
func configureOP(opData: OP) {
userNameLabel.text = opData.name
if(opData.gender == "male") {
userNameLabel.textColor = UIColor(red:0.68, green:0.78, blue:0.81, alpha:1.0)
}
else {
userNameLabel.textColor = UIColor(red:1.00, green:0.41, blue:0.38, alpha:1.0)
}
if(opData.level == "lv1") {
userLevelLabel.text = "普通會然"
userLevelLabel.backgroundColor = UIColor.darkGray
}
else if (opData.level == "lv2") {
userLevelLabel.text = "迷の存在"
userLevelLabel.backgroundColor = UIColor(red:0.55, green:0.00, blue:0.00, alpha:1.0)
}
else if (opData.level == "lv3") {
userLevelLabel.text = "肉務腸"
userLevelLabel.backgroundColor = UIColor(red:0.47, green:0.87, blue:0.47, alpha:1.0)
}
else if (opData.level == "lv4") {
userLevelLabel.text = "唉屎"
userLevelLabel.backgroundColor = UIColor(red:0.00, green:1.00, blue:1.00, alpha:1.0)
}
let avatarURL = URL(string: "https://hkgalden.com" + opData.avatar)
if (opData.avatar == "") {
userAvatarImageView.image = UIImage(named: "DefaultAvatar")
}
else {
userAvatarImageView.kf.setImage(with: avatarURL)
}
//remove abundant </img> tag
opData.contentHTML = opData.contentHTML.replacingOccurrences(of: "</img>", with: "")
//print(opData.contentHTML)
let contentData = opData.contentHTML.data(using: .utf8)
let contentAttr = NSAttributedString.init(htmlData: contentData, options: attributedOptions as! [AnyHashable : Any], documentAttributes: nil)
//print(contentAttr)
contentTextView.attributedString = contentAttr
replyCountLabel.text = "OP"
dateLabel.text = opData.date
}
func configureReply(comments: [Replies],indexPath: IndexPath,pageNow: Int) {
userNameLabel.text = comments[indexPath.row - 1].name
if(comments[indexPath.row - 1].gender == "male") {
userNameLabel.textColor = UIColor(red:0.68, green:0.78, blue:0.81, alpha:1.0)
}
else {
userNameLabel.textColor = UIColor(red:1.00, green:0.41, blue:0.38, alpha:1.0)
}
if(comments[indexPath.row - 1].level == "lv1") {
userLevelLabel.text = "普通會然"
userLevelLabel.backgroundColor = UIColor.darkGray
}
else if (comments[indexPath.row - 1].level == "lv2") {
userLevelLabel.text = "迷の存在"
userLevelLabel.backgroundColor = UIColor(red:0.55, green:0.00, blue:0.00, alpha:1.0)
}
else if (comments[indexPath.row - 1].level == "lv3") {
userLevelLabel.text = "肉務腸"
userLevelLabel.backgroundColor = UIColor(red:0.47, green:0.87, blue:0.47, alpha:1.0)
}
else if (comments[indexPath.row - 1].level == "lv4") {
userLevelLabel.text = "唉屎"
userLevelLabel.backgroundColor = UIColor(red:0.00, green:1.00, blue:1.00, alpha:1.0)
}
let avatarURL = URL(string: "https://hkgalden.com" + comments[indexPath.row - 1].avatar)
if (comments[indexPath.row - 1].avatar == "") {
userAvatarImageView.image = UIImage(named: "DefaultAvatar")
}
else {
userAvatarImageView.kf.setImage(with: avatarURL)
}
replyCountLabel.text = "#" + String(25 * (pageNow - 1) + indexPath.row)
dateLabel.text = comments[indexPath.row - 1].date
let contentData = comments[indexPath.row - 1].contentHTML.data(using: .utf8)
let contentAttr = NSAttributedString.init(htmlData: contentData, options: attributedOptions as! [AnyHashable : Any], documentAttributes: nil)
//print(contentAttr)
contentTextView.attributedString = contentAttr
}
}

Try this category - it works for me
extension UIImageView {
public func imageFromUrl(url: URL?) {
if let url = url {
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else { return }
DispatchQueue.main.async { [weak self] in
self?.image = UIImage(data: data)
}
}
task.resume()
}
}
}

Related

UICollectionView with a custom data Structure

I am trying to create a collection view similar to Apple's shortcuts app. I was able to create the cells themselves but I am having a hard time create an individual data cell (if that makes sense). My goal is to have each cell display a title, subtitle, and possible a play button.
Right now, I am having a hard time figuring out where I am going wrong with my constraints or possible my data structure (its crashing on the background and the text isn't showing on the colored cell).
struct customData {
var title: String
var subtitle: String
}
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
//Mark : All Cards
fileprivate let data = [
customData (title: "iOS", subtitle: "12 Tips"),
customData (title: "iPadOS", subtitle: "11 Tips"),
customData (title: "macOS", subtitle: "10 Tips"),
customData (title: "tvOS", subtitle: "19 Tips"),
customData (title: "watchOS", subtitle: "18 Tips"),
customData (title: "Accessories", subtitle: "17 Tips"),
]
//MARK : Properites
let cellId = "Cell"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
setupCollectionView()
setupNavigationBarController()
}
//MARK : Setup Methods
fileprivate func setupNavigationBarController() {
self.navigationController?.navigationBar.shadowImage = UIImage()
navigationItem.title = "Lists"
if #available(iOS 13.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
}
}
fileprivate func setupCollectionView() {
collectionView?.backgroundColor = .red
collectionView.register(customCell.self, forCellWithReuseIdentifier: cellId)
collectionView.alwaysBounceVertical = true
}
//MARK : CollectionView Delegate Methods
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// 6
return data.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! customCell
cell.data = self.data[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: (view.frame.width / 2) - 20, height: 110)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
}
}
class customCell: UICollectionViewCell {
var data: customData? {
didSet {
guard let data = data else { return }
listName.text = data.title
subName.text = data.subtitle
}
}
fileprivate let listName: UILabel = {
let iv = UILabel ()
iv.textColor = .white
iv.font = UIFont(name: "Times" , size: 12)
return iv
}()
fileprivate let subName: UILabel = {
let iv = UILabel ()
return iv
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupCell()
contentView.addSubview(listName)
listName.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10).isActive = true
listName.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 30).isActive = true
listName.widthAnchor.constraint(equalTo: contentView.widthAnchor, constant: 12).isActive = true
listName.heightAnchor.constraint(equalTo: contentView.heightAnchor, constant: 80).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: Setup Cell
fileprivate func setupCell() {
roundCorner()
gradientBackgroundColor()
setCellShadow()
}
// MARK: Methods
func setCellShadow() {
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 0, height: 1)
self.layer.shadowOpacity = 0.2
self.layer.shadowRadius = 1.0
self.layer.masksToBounds = false
self.layer.cornerRadius = 3
self.clipsToBounds = false
}
func cellRandomBackgroundColors() -> [UIColor] {
//Colors
let red = [#colorLiteral(red: 0.9654200673, green: 0.1590853035, blue: 0.2688751221, alpha: 1),#colorLiteral(red: 0.7559037805, green: 0.1139892414, blue: 0.1577021778, alpha: 1)]
let orangeRed = [#colorLiteral(red: 0.9338900447, green: 0.4315618277, blue: 0.2564975619, alpha: 1),#colorLiteral(red: 0.8518816233, green: 0.1738803983, blue: 0.01849062555, alpha: 1)]
let orange = [#colorLiteral(red: 0.9953531623, green: 0.54947716, blue: 0.1281470656, alpha: 1),#colorLiteral(red: 0.9409626126, green: 0.7209432721, blue: 0.1315650344, alpha: 1)]
let yellow = [#colorLiteral(red: 0.9409626126, green: 0.7209432721, blue: 0.1315650344, alpha: 1),#colorLiteral(red: 0.8931249976, green: 0.5340107679, blue: 0.08877573162, alpha: 1)]
let green = [#colorLiteral(red: 0.3796315193, green: 0.7958304286, blue: 0.2592983842, alpha: 1),#colorLiteral(red: 0.2060100436, green: 0.6006633639, blue: 0.09944178909, alpha: 1)]
let greenBlue = [#colorLiteral(red: 0.2761503458, green: 0.824685812, blue: 0.7065336704, alpha: 1),#colorLiteral(red: 0, green: 0.6422213912, blue: 0.568986237, alpha: 1)]
let kindaBlue = [#colorLiteral(red: 0.2494148612, green: 0.8105323911, blue: 0.8425348401, alpha: 1),#colorLiteral(red: 0, green: 0.6073564887, blue: 0.7661359906, alpha: 1)]
let skyBlue = [#colorLiteral(red: 0.3045541644, green: 0.6749247313, blue: 0.9517192245, alpha: 1),#colorLiteral(red: 0.008423916064, green: 0.4699558616, blue: 0.882807076, alpha: 1)]
let blue = [#colorLiteral(red: 0.1774400771, green: 0.466574192, blue: 0.8732826114, alpha: 1),#colorLiteral(red: 0.00491155684, green: 0.287129879, blue: 0.7411141396, alpha: 1)]
let bluePurple = [#colorLiteral(red: 0.4613699913, green: 0.3118675947, blue: 0.8906354308, alpha: 1),#colorLiteral(red: 0.3018293083, green: 0.1458326578, blue: 0.7334778905, alpha: 1)]
let purple = [#colorLiteral(red: 0.7080290914, green: 0.3073516488, blue: 0.8653779626, alpha: 1),#colorLiteral(red: 0.5031493902, green: 0.1100070402, blue: 0.6790940762, alpha: 1)]
let pink = [#colorLiteral(red: 0.9495453238, green: 0.4185881019, blue: 0.6859942079, alpha: 1),#colorLiteral(red: 0.8123683333, green: 0.1657164991, blue: 0.5003474355, alpha: 1)]
let colorsTable: [Int: [UIColor]] = [0: red, 1: orangeRed, 2: orange, 3: yellow, 4: green, 5: greenBlue, 6: kindaBlue, 7: skyBlue, 8: blue, 9: bluePurple, 10: bluePurple, 11: purple, 12: pink]
let randomColors = colorsTable.values.randomElement()
return randomColors!
}
func gradientBackgroundColor() {
let colors = cellRandomBackgroundColors()
self.contentView.setGradientBackgroundColor(colorOne: colors[0], colorTow: colors[1])
}
func roundCorner() {
self.contentView.layer.cornerRadius = 12.0
self.contentView.layer.masksToBounds = true
self.contentView.layer.borderWidth = 1.0
self.contentView.layer.borderColor = UIColor.clear.cgColor
}
}
This is what I see:
To fix the warnings that say constraint cannot be satisfied you should set translatesAutoresizingMaskIntoConstraints of listName to false.
override init(frame: CGRect) {
super.init(frame: frame)
setupCell()
contentView.addSubview(listName)
listName.translatesAutoresizingMaskIntoConstraints = false // Add this
listName.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10).isActive = true
listName.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 30).isActive = true
listName.widthAnchor.constraint(equalTo: contentView.widthAnchor, constant: 12).isActive = true
listName.heightAnchor.constraint(equalTo: contentView.heightAnchor, constant: 80).isActive = true
}

UITableView Background Color Different From UITableViewCell

I am setting the tableView background color the same as the tableViewCell background color, but the colors look different. The colors look the same when set to a custom color but when there is no custom color set they are different. isColorSet is 0 on start so both should be set to UIColor(red: 74/255, green: 187/255, blue: 224/255, alpha: 1.0). How can I get the colors to look the same?
Setting tableView background color:
override func viewWillAppear(_ animated: Bool) {
//Set background color
if userDefaults.integer(forKey: "isColorSet") == 0 {
navigationController?.navigationBar.barTintColor = UIColor(red: 74/255, green: 187/255, blue: 224/255, alpha: 1.0)
tableView.backgroundColor = UIColor(red: 74/255, green: 187/255, blue: 224/255, alpha: 1.0)
} else if userDefaults.integer(forKey: "isColorSet") == 1 {
let red = CGFloat(userDefaults.float(forKey: "red"))
let green = CGFloat(userDefaults.float(forKey: "green"))
let blue = CGFloat(userDefaults.float(forKey: "blue"))
navigationController?.navigationBar.barTintColor = UIColor(red: red/255, green: green/255, blue: blue/255, alpha: 1.0)
tableView.backgroundColor = UIColor(red: red/255, green: green/255, blue: blue/255, alpha: 1.0)
}
}
Setting tableViewCell background color:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ideaCell") as! IdeaTableViewCell
cell.ideaTitleLabel.text = ideas[indexPath.section][indexPath.row].title
cell.ideaDescLabel.text = ideas[indexPath.section][indexPath.row].desc
//Set date
let date = userDefaults.object(forKey: "date.\(indexPath.section).\(indexPath.row)") as! Date
let month = Calendar.current.component(.month, from: date)
let day = Calendar.current.component(.day, from: date)
let year = Calendar.current.component(.year, from: date)
if userDefaults.string(forKey: "dateStyle") == "MDY" {
cell.ideaDateLabel.text = "\(month)/\(day)/\(year)"
} else if userDefaults.string(forKey: "dateStyle") == "DMY" {
cell.ideaDateLabel.text = "\(day)/\(month)/\(year)"
} else if userDefaults.string(forKey: "dateStyle") == "YMD" {
cell.ideaDateLabel.text = "\(year)/\(month)/\(day)"
}
//Set color
if userDefaults.integer(forKey: "isColorSet") == 0 {
cell.backgroundColor = UIColor(red: 74/255, green: 187/225, blue: 224/225, alpha: 1.0)
} else if userDefaults.integer(forKey: "isColorSet") == 1 {
let red = CGFloat(userDefaults.float(forKey: "red"))
let green = CGFloat(userDefaults.float(forKey: "green"))
let blue = CGFloat(userDefaults.float(forKey: "blue"))
cell.backgroundColor = UIColor(red: red/255, green: green/255, blue: blue/255, alpha: 1.0)
}
return cell
Setting rgb colors for UserDefaults:
func HSBColorColorPickerTouched(sender: HSBColorPicker, color: UIColor, point: CGPoint, state: UIGestureRecognizer.State) {
setButton.backgroundColor = color
red = color.rgb()?.red
green = color.rgb()?.green
blue = color.rgb()?.blue
redLabel.text = "Red: \(red!)"
redSlider.value = Float(red)
greenLabel.text = "Green: \(green!)"
greenSlider.value = Float(green)
blueLabel.text = "Blue: \(blue!)"
blueSlider.value = Float(blue)
}
#IBAction func sliderValueChanged(_ sender: Any) {
red = redSlider.value
green = greenSlider.value
blue = blueSlider.value
if red != nil {
redLabel.text = "Red: \(red!)"
}
if green != nil {
greenLabel.text = "Green: \(green!)"
}
if blue != nil {
blueLabel.text = "Blue: \(blue!)"
}
setButton.backgroundColor = UIColor(red: CGFloat(red/255), green: CGFloat(green/255), blue: CGFloat(blue/255), alpha: 1.0)
}
#IBAction func setColor(_ sender: Any) {
userDefaults.removeObject(forKey: "red")
userDefaults.removeObject(forKey: "green")
userDefaults.removeObject(forKey: "blue")
userDefaults.set(red, forKey: "red")
userDefaults.set(green, forKey: "green")
userDefaults.set(blue, forKey: "blue")
if userDefaults.float(forKey: "isColorSet") == 0 {
userDefaults.set(1, forKey: "isColorSet")
}
_ = navigationController?.popToRootViewController(animated: true)
}
Screenshot with isColorSet = 0
Screenshot with isColorSet = 1
Screenshot of Color Picker
The issue is a simple typo in the following line:
cell.backgroundColor = UIColor(red: 74/255, green: 187/225, blue: 224/225, alpha: 1.0)
Your denominator should be 255 for the green and blue values.

How to make cells pre-selected when app became launched?

I have typical table view with opportunity to be selected. I want to make them selected as default.
import UIKit
class WeekdaysViewController: UITableViewController {
var weekdays: [Int]!
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView()
view.backgroundColor = UIColor.white
weekdays = [1, 2, 3, 4, 5, 6, 7]
}
override func viewWillDisappear(_ animated: Bool) {
performSegue(withIdentifier: Id.weekdaysUnwindIdentifier, sender: self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
for weekday in weekdays {
if weekday == (indexPath.row + 1) {
cell.accessoryType = UITableViewCellAccessoryType.checkmark
//cell.tintColor = UIColor(red: 13.0/255.0, green: 211.0/255.0, blue: 90.0/255.0, alpha: 1.00)
cell.tintColor = UIColor(red: 255.0/255.0, green: 178.0/255.0, blue: 55.0/255.0, alpha: 1.00)
}
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)!
if let index = weekdays.index(of: (indexPath.row + 1)){
weekdays.remove(at: index)
cell.setSelected(true, animated: true)
cell.setSelected(false, animated: true)
cell.accessoryType = UITableViewCellAccessoryType.none
//cell.tintColor = UIColor(red: 13.0/255.0, green: 211.0/255.0, blue: 90.0/255.0, alpha: 1.00)
cell.tintColor = UIColor(red: 255.0/255.0, green: 178.0/255.0, blue: 55.0/255.0, alpha: 1.00)
//cell.backgroundColor = UIColor(red: 13.0/255.0, green: 211.0/255.0, blue: 90.0/255.0, alpha: 1.00)
//cell.tintColor = UIColor.white
} else {
//row index start from 0, weekdays index start from 1 (Sunday), so plus 1
weekdays.append(indexPath.row + 1)
cell.setSelected(true, animated: true)
cell.setSelected(false, animated: true)
cell.accessoryType = UITableViewCellAccessoryType.checkmark
//cell.tintColor = UIColor(red: 13.0/255.0, green: 211.0/255.0, blue: 90.0/255.0, alpha: 1.00)
cell.tintColor = UIColor(red: 255.0/255.0, green: 178.0/255.0, blue: 55.0/255.0, alpha: 1.00)
//cell.backgroundColor = UIColor(red: 13.0/255.0, green: 211.0/255.0, blue: 90.0/255.0, alpha: 1.00)
//cell.tintColor = UIColor.white
}
}
}
extension WeekdaysViewController {
static func repeatText( weekdays: [Int]) -> String {
if weekdays.count == 7 {
return "Every Day"
}
if weekdays.isEmpty {
return "No repeat"
}
let preferredLanguage = Locale.current.languageCode
let locale = Locale.current.regionCode
var ret = String()
var weekdaysSorted:[Int] = [Int]()
weekdaysSorted = weekdays.sorted(by: <)
if preferredLanguage == "ru" {
for day in weekdaysSorted {
switch day {
case 1:
ret += "Sun "
case 2:
ret += "Mon "
case 3:
ret += "Tue "
case 4:
ret += "Wed "
case 5:
ret += "Thu "
case 6:
ret += "Fri "
case 7:
ret += "Sat "
default:
//throw
break
}
}
} else {
for day in weekdaysSorted {
switch day{
case 1:
ret += "Sun "
case 2:
ret += "Mon "
case 3:
ret += "Tue "
case 4:
ret += "Wed "
case 5:
ret += "Thu "
case 6:
ret += "Fri "
case 7:
ret += "Sat "
default:
//throw
break
}
}
}
return ret
}
}
I've added in viewDidLoad()
weekdays = [1, 2, 3, 4, 5, 6, 7]
It's almost working but only when I'm moving to WeekdaysViewController.
How to resolve that problem?
Use this snippet to automatically select your table row index.
Swift 3
tableView.selectRow(at: IndexPath(item: 1, section: 0), animated: true, scrollPosition: .middle)
Sample Image

Translucent white covering my button in UITableView

I've set constraints and everything but there's a translucent white "screen" covering the lower part of my screen. It's not fixed to my tableview because when I scroll down the button gets pulled up and is visible but the screen stays there. At first I thought it was a rogue view but it's not so I'm not sure what's going on. Any pointers on what I should be looking at to solve this problem? Here's a picture:
Here is my code (a little untidy because this is my first project in swift):
import UIKit
class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var buttonView: UIView!
#IBOutlet weak var button: UIButton!
#IBOutlet weak var tableView: UITableView!
let manager = WorkoutDataSource()
let gradientLayer = CAGradientLayer()
var workouts = []
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
self.workouts = manager.getWorkOuts()
let borderAlpha : CGFloat = 0.7
let cornerRadius : CGFloat = 5.0
button.backgroundColor = UIColor.clearColor()
button.layer.borderWidth = 1.0
button.layer.borderColor = UIColor(white: 1.0, alpha: borderAlpha).CGColor
button.layer.cornerRadius = cornerRadius
let heightOfVisibleTableViewArea = tableView.bounds.height - topLayoutGuide.length - bottomLayoutGuide.length
let numberOfRows = tableView.numberOfRowsInSection(0)
tableView.rowHeight = heightOfVisibleTableViewArea / CGFloat(numberOfRows)
let color1 = UIColor(hue: 0.9528, saturation: 0.4, brightness: 1, alpha: 1.0) /* #ff759d */
let color2 = UIColor(hue: 0.0167, saturation: 0.25, brightness: 0.95, alpha: 1.0) /* #ffb1b1 */
let color3 = UIColor(hue: 0.2528, saturation: 0.11, brightness: 0.85, alpha: 1.0) /* #f3bbb4 */
let color4 = UIColor(hue: 0.3833, saturation: 0.21, brightness: 0.91, alpha: 1.0) /* #cedbc2 */
let color5 = UIColor(hue: 0.4417, saturation: 0.62, brightness: 0.97, alpha: 1.0) /* #b7eac7 */
let color6 = UIColor(hue: 0.4528, saturation: 0.91, brightness: 0.81, alpha: 1.0) /* #12d19e */ /* #5ef9c3 */
//let color7 = UIColor(hue: 0.5833, saturation: 0.7, brightness: 0.68, alpha: 1.0) /* #346fae */
let color7 = UIColor.flatNavyBlueColorDark()
gradientLayer.colors = [color1, color2, color3, color4, color5, color6, color7]
view.backgroundColor = UIColor.flatNavyBlueColorDark()
setTableViewBackgroundGradient(color7, bottomColor: color1)
self.navigationController?.navigationBar.backgroundColor = UIColor.flatNavyBlueColorDark()!
// Do any additional setup after loading the view, typically from a nib.
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return self.workouts.count
}
func setTableViewBackgroundGradient(topColor: UIColor, bottomColor: UIColor){
let gradientBackgroundColors = [topColor.CGColor, bottomColor.CGColor]
let gradientLocations = [0.0,1.0]
let gradientLayer = CAGradientLayer()
gradientLayer.colors = gradientBackgroundColors
gradientLayer.locations = gradientLocations
gradientLayer.frame = tableView.bounds
let backgroundView = UIView(frame: tableView.bounds)
backgroundView.layer.insertSublayer(gradientLayer, atIndex: 0)
tableView.backgroundView = backgroundView
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let workout = self.workouts[indexPath.row] as? Workout
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as? WorkoutCell
cell!.textCellLabel?.text = workout?.title
cell!.backgroundColor = workout?.color
cell!.countLabel.text = "\(indexPath.row+1)"
cell!.selectionStyle = UITableViewCellSelectionStyle.None
cell!.backgroundColor = UIColor.clearColor()
return cell!
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "detailview"){
let cell = sender as? WorkoutCell
let indexPath = tableView.indexPathForCell(cell!)
let nvc = segue.destinationViewController as? UINavigationController
if let tmp = workouts[indexPath!.row] as? Workout{
let dvc = nvc?.topViewController as! DetailViewController
dvc.workout = tmp
}
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.tableView.contentInset = UIEdgeInsetsMake(0,0,55,0)
}
}

Sigabrt when trying to display another view controller

I want to go to another view controller when pressing button my btnSignUp, If I write code like this I have error "sigabrt". What I should do?
import UIKit
import SnapKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 15/255, green: 52/255, blue: 100/255, alpha: 1)
createTop()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func createTop() {
let topView = UIView()
self.view.addSubview(topView)
topView.backgroundColor = UIColor(red: 15/255, green: 52/255, blue: 100/255, alpha: 1)
topView.snp_makeConstraints { (make) -> Void in
make.width.equalTo((self.view.frame.width/10)*8)
make.height.equalTo(self.view.frame.height/5)
make.centerX.equalTo(self.view)
make.top.equalTo(self.view).offset(self.view.frame.height/15)
}
let btnSignUp = UIButton()
self.view.addSubview(btnSignUp)
btnSignUp.backgroundColor = UIColor(red: 15/255, green: 52/255, blue: 100/255, alpha: 1)
btnSignUp.layer.borderColor = UIColor.whiteColor().CGColor
btnSignUp.layer.borderWidth = 1
btnSignUp.layer.cornerRadius = 6
btnSignUp.setTitle("Sign Up", forState: UIControlState.Normal)
btnSignUp.titleLabel?.font = UIFont(name: "AvenirNext-Regular", size: 17)
btnSignUp.snp_makeConstraints { (make) -> Void in
make.width.equalTo(((self.view.frame.width/10)*7)+40)
make.height.equalTo(self.view.frame.height/13)
make.top.equalTo(ORView.snp_bottom).offset(20)
make.centerX.equalTo(self.view)
}
btnSignUp.addTarget(self, action: "buttonAction", forControlEvents: UIControlEvents.TouchUpInside)
func buttonAction(sender:UIButton!)
{
let signUpVC = SignUpViewController()
self.presentViewController(signUpVC, animated: true, completion: nil)
}
}
}
Your action selector buttonAction doesn't match your function declaration - It takes an argument, so the selector will be buttonAction:
btnSignUp.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
Additionally, check your parentheses. It appears that your buttonAction function is declared inside func createTop()
func createTop() {
let topView = UIView()
self.view.addSubview(topView)
topView.backgroundColor = UIColor(red: 15/255, green: 52/255, blue: 100/255, alpha: 1)
topView.snp_makeConstraints { (make) -> Void in
make.width.equalTo((self.view.frame.width/10)*8)
make.height.equalTo(self.view.frame.height/5)
make.centerX.equalTo(self.view)
make.top.equalTo(self.view).offset(self.view.frame.height/15)
}
let btnSignUp = UIButton()
self.view.addSubview(btnSignUp)
btnSignUp.backgroundColor = UIColor(red: 15/255, green: 52/255, blue: 100/255, alpha: 1)
btnSignUp.layer.borderColor = UIColor.whiteColor().CGColor
btnSignUp.layer.borderWidth = 1
btnSignUp.layer.cornerRadius = 6
btnSignUp.setTitle("Sign Up", forState: UIControlState.Normal)
btnSignUp.titleLabel?.font = UIFont(name: "AvenirNext-Regular", size: 17)
btnSignUp.snp_makeConstraints { (make) -> Void in
make.width.equalTo(((self.view.frame.width/10)*7)+40)
make.height.equalTo(self.view.frame.height/13)
make.top.equalTo(ORView.snp_bottom).offset(20)
make.centerX.equalTo(self.view)
}
btnSignUp.addTarget(self, action: "buttonAction", forControlEvents: UIControlEvents.TouchUpInside)
}
func buttonAction(sender:UIButton!) {
let signUpVC = SignUpViewController()
self.presentViewController(signUpVC, animated: true, completion: nil)
}
Finally, I doubt that you want to get your new view controller by SignUpViewController() - if you are using a storyboard you want to call instantiateViewControllerWithIdentifier

Resources