Laggy UITableViewController - ios

I have UITableViewController with 1000 row. Each cell contains label that fill with attributed string. Cell are self sizing cell and estimation is not correct in estimatedHeightForRowAtIndexPath so I did not use it (I don't no why my estimation cause to lag, I use NSSting.boundingRectWithSize for estimation). I have UISlider as SeekBar in bottom of my view, when I seek too middle of page main thread become busy with cellForRowAtIndexPath and even I could not show waiting progress bar like HUD progress.
Here is my cellForRowAtIndexPath:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Aya Cell") as! AyaCell
let detail = API.readingDetail[indexPath.row % API.readingDetail.count]
cell.backgroundColor = backgroundColor
switch detail {
case .Persian:
let text = translations.suras[self.sura.index-1].ayas[indexPath.row / API.readingDetail.count].text
var textBackground = UIColor.clearColor()
if translations.suras[self.sura.index-1].ayas[indexPath.row / API.readingDetail.count].shouldSelected == true {
textBackground = UIColor.yellowColor()
}
let attributedText = NSMutableAttributedString(string: text, attributes: [NSForegroundColorAttributeName: persianTextColor, NSFontAttributeName: AyaPersianFont!, NSBackgroundColorAttributeName: backgroundColor])
attributedText.appendAttributedString(NSAttributedString(string: " (\((indexPath.row / API.readingDetail.count+1).toArabicDigit()))", attributes: [NSForegroundColorAttributeName: MojezeRedColor, NSFontAttributeName:UIFont(name: "XNazanin", size: AyaFont!.pointSize*0.65)!, NSParagraphStyleAttributeName: AyaParagraphStyle]))
cell.ayaTextLabel.attributedText = attributedText
case .Arabic:
let text = self.sura.ayas[indexPath.row / API.readingDetail.count].text
var textBackground = UIColor.clearColor()
if self.sura.ayas[indexPath.row / API.readingDetail.count].shouldSelected == true {
textBackground = UIColor.yellowColor()
}
let attributedText = NSMutableAttributedString(string: text, attributes: [NSForegroundColorAttributeName: arabicTextColor, NSFontAttributeName: AyaFont!, NSBackgroundColorAttributeName: textBackground])
attributedText.appendAttributedString(NSAttributedString(string: " ﴿\((indexPath.row / API.readingDetail.count+1).toArabicDigit())﴾", attributes: [NSForegroundColorAttributeName: MojezeRedColor, NSFontAttributeName:UIFont(name: "XNazanin", size: AyaFont!.pointSize*0.65)!, NSParagraphStyleAttributeName: AyaParagraphStyle]))
cell.ayaTextLabel.attributedText = attributedText
}
return cell
}
Is there any solution for this?

Related

swift i want to change search bar background colour white with black border

here the screenshot that I want output please check
I want the result like this search bar with background color white and black border
here my code is
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
for subView in searchBar.subviews {
if !subView.subviews.contains(where: { $0 as? UITextField != nil }) { continue }
guard let textField = subView.subviews.first(where: { $0 as? UITextField != nil }) as? UITextField else { return }
let placeholder = NSMutableAttributedString(
string: "Search",
attributes: [.font: UIFont(name: "Helvetica", size: 15.0)!,
.foregroundColor: UIColor.gray
])
textField.attributedPlaceholder = placeholder
textField.layer.cornerRadius = textField.frame.size.height / 2
textField.layer.masksToBounds = true
textField.textColor = .black
textField.backgroundColor = .white
}
this is my output screenshot please check it
I am unable to set search bar, please suggest me
Good day! If I understand you correctly, then this may solve your problem. Extension for UISearchBar (Swift 5):
import UIKit
extension UISearchBar {
func setupSearchBar(background: UIColor = .white, inputText: UIColor = .black, placeholderText: UIColor = .gray, image: UIColor = .black) {
self.searchBarStyle = .minimal
self.barStyle = .default
// IOS 12 and lower:
for view in self.subviews {
for subview in view.subviews {
if subview is UITextField {
if let textField: UITextField = subview as? UITextField {
// Background Color
textField.backgroundColor = background
// Text Color
textField.textColor = inputText
// Placeholder Color
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : placeholderText])
// Default Image Color
if let leftView = textField.leftView as? UIImageView {
leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
leftView.tintColor = image
}
let backgroundView = textField.subviews.first
backgroundView?.backgroundColor = background
backgroundView?.layer.cornerRadius = 10.5
backgroundView?.layer.masksToBounds = true
}
}
}
}
// IOS 13 only:
if let textField = self.value(forKey: "searchField") as? UITextField {
// Background Color
textField.backgroundColor = background
// Text Color
textField.textColor = inputText
// Placeholder Color
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : placeholderText])
// Default Image Color
if let leftView = textField.leftView as? UIImageView {
leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
leftView.tintColor = image
}
}
}
}
Also, you can try to do it with an image.
The way to do this only using Apple APIs is to create an image and use setSearchFieldBackgroundImage:
self.searchBar.setSearchFieldBackgroundImage(UIImage(named: "SearchFieldBackground"), for: UIControlState.normal)
Source: Cannot change search bar background color

Clickable Link on tableview controller

Hey guys how do I make a link clickable in a table view cell as shown in the image link above ?
The information is from a Json File.
func tableView( tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "albumID", for: indexPath)
let album :[String:Any] = albums[indexPath.row]
cell.textLabel?.text = album["collectionName"] as? String
cell.detailTextLabel?.text = album["artistName"] as? String
return cell
}
You need to have UITextView as detailTextLabel
attributedString.addAttribute(.link, value: "https://developer.apple.com", range: NSRange(location: 30, length: 50))
cell.detailTextLabel?.attributedText = attributedString
and then implement this method
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
UIApplication.shared.open(URL)
return false
}
You can use the below-mentioned statements to make a link of textView or label either inside tableView, collection view, or using them separately inside viewController.
If you are using textView then you can use this code mentioned below:-
let attributedString = NSMutableAttributedString(string: "Just click here to `register")
let url = URL(string: "https://www.apple.com")!
// Set the 'click here' substring to be the link
attributedString.setAttributes([.link: url], range: NSMakeRange(5, 10))
self.textView.attributedText = attributedString
self.textView.isUserInteractionEnabled = true
self.textView.isEditable = false
// Set how links should appear: blue and underlined
self.textView.linkTextAttributes = [
.foregroundColor: UIColor.blue,
.underlineStyle: NSUnderlineStyle.single.rawValue
]
or
if you are using labels then you can use this code mentioned below:-
var attributedString = NSMutableAttributedString(string: "String with a link", ``attributes: nil)
let linkRange = NSRange(location: 14, length: 4) // for the word "link" in the string above
let linkAttributes = [
NSAttributedString.Key.foregroundColor: UIColor(red: 0.05, green: 0.4, blue: 0.65, alpha: 1.0),
NSAttributedString.Key.underlineStyle: NSNumber(value: NSUnderlineStyle.single.rawValue)
]
attributedString.setAttributes(linkAttributes, range: linkRange)
// Assign attributedText to UILabel
label.attributedText = attributedString```

Strikethrough UITableView cell text after cell containing String

I'd like to strikethrough all cell text in UITableView after a specific line of text.
Example (after "+")
I think I'm close, but the strikethrough isn't applied in the Simulator. (build is successful)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "Cell")
if indexPath.row > dailyTasks.index(of: "+")! {
let attributeString: NSMutableAttributedString = NSMutableAttributedString(string: dailyTasks[indexPath.row])
attributeString.addAttribute(NSAttributedStringKey.strikethroughStyle, value: 1, range: NSMakeRange(0, attributeString.length))
cell.textLabel?.attributedText = attributeString
} else {
cell.textLabel?.text = dailyTasks[indexPath.row]
}
cell.textLabel?.font = UIFont(name: "GillSans-Light", size: 17)
cell.indentationLevel = 1
cell.textLabel?.addCharactersSpacing(1.2)
cell.backgroundColor = UIColor(red:0.99, green:0.97, blue:0.91, alpha:1.0)
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}
Don't set the font on the label if you are using an attributed string; instead set the font as an attribute. Here is a playground that shows how to do it:
import UIKit
import PlaygroundSupport
let label = UILabel()
let text = "sample text"
let view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
let attributes: [NSAttributedStringKey: Any] =
[NSAttributedStringKey.font: UIFont(name: "GillSans-Light", size: 17)!,
NSAttributedStringKey.foregroundColor : UIColor.white,
NSAttributedStringKey.strikethroughStyle: 1]
label.attributedText = NSAttributedString(string: text, attributes: attributes)
view.addSubview(label)
label.sizeToFit()
PlaygroundPage.current.liveView = view

Attributed text with two text alignments

Does anyone know how to achieve two different text alignments in one string?
This is what I want the textView to show:
label value
My code:
let txtView = cell.viewWithTag(77) as! UITextView
let leftStyle = NSMutableParagraphStyle()
leftStyle.alignment = NSTextAlignment.Left
let rightStyle = NSMutableParagraphStyle()
rightStyle.alignment = NSTextAlignment.Right
let attText = NSMutableAttributedString(string: "label", attributes: [NSParagraphStyleAttributeName: leftStyle])
attText.appendAttributedString(NSAttributedString(string: " "))
attText.appendAttributedString(NSAttributedString(string: "value", attributes: [NSParagraphStyleAttributeName: rightStyle]))
txtView.attributedText = attText
What I get instead:
label value
Using NSMutableParagraphStyle with NSTextTab:
let paragraph = NSMutableParagraphStyle()
paragraph.tabStops = [
NSTextTab(textAlignment: .Right, location: 100, options: [:]),
]
let str = "Label\tValue\n"
+ "foo\tbar\n"
let attributed = NSAttributedString(
string: str,
attributes: [NSParagraphStyleAttributeName: paragraph]
)
let view = UITextView(frame: CGRectMake(0, 0, 120, 120))
view.textContainer.lineFragmentPadding = 10
view.attributedText = attributed
Of course, this aligns to "tabstop", but not to the edge of UITextView. When you modify the size of the view, you have to also modify the location of NSTextTab.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
let cell = Placestableview.dequeueReusableCell(withIdentifier: "cell", for: indexPath);
//first text
let attributestitle = [NSAttributedStringKey.font:
UIFont(name: "Helvetica-Bold", size: 15.0)!,
NSAttributedStringKey.foregroundColor: UIColor.black] as [NSAttributedStringKey: Any]
//second text
let attributedString = NSMutableAttributedString(string: "\t"+String(places[indexPath.row].distance!)+" miles", attributes: [NSAttributedStringKey.font: UIFont(name: "Helvetica-Bold", size: 8.0)!,NSAttributedStringKey.foregroundColor: UIColor.black])
let myParagraphStyle = NSMutableParagraphStyle()
myParagraphStyle.alignment = .right
myParagraphStyle.tabStops = [
NSTextTab(textAlignment: .right, location: 300, options: [:]),
]
let attributedStringtitle = NSMutableAttributedString(string: places[indexPath.row].title!, attributes: attributestitle)
//adding the right alignment to the second text alone
attributedString.addAttributes([.paragraphStyle: myParagraphStyle], range: NSRange(location: 0, length: attributedString.length))
//combining two texts with different alignments.
let combination = NSMutableAttributedString()
combination.append(attributedStringtitle)
combination.append(attributedString)
cell.textLabel?.attributedText = combination
return cell;
}

Swift - UIButton with two lines of text

I was wondering if it is possible to create a UIButton with two lines of text. I need each line to have a different font size. The first line will be 17 point and the second will be 11 point. I've tried messing with putting two labels inside of a UIButton, but I can't get them to stay inside the bounds of the button.
I'm attempting to do all of this in the ui builder, and not programmatically.
Thanks
There are two questions.
I was wondering if it is possible to create a UIButton with two lines
of text
This is possible through using the storyboard or programmatically.
Storyboard:
Change the 'Line Break Mode' to Character Wrap or Word Wrap and use Alt/Option + Enter key to enter a new line in the UIButton's Title field.
Programmatically:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
btnTwoLine?.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping;
}
I need each line to have a different font size
1
The worst case is, you can use a custom UIButton class and add two labels within it.
The better way is, make use of NSMutableAttributedString. Note that,this can be achieved through only programmatically.
Swift 5:
#IBOutlet weak var btnTwoLine: UIButton?
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
//applying the line break mode
textResponseButton?.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping;
let buttonText: NSString = "hello\nthere"
//getting the range to separate the button title strings
let newlineRange: NSRange = buttonText.range(of: "\n")
//getting both substrings
var substring1 = ""
var substring2 = ""
if(newlineRange.location != NSNotFound) {
substring1 = buttonText.substring(to: newlineRange.location)
substring2 = buttonText.substring(from: newlineRange.location)
}
//assigning diffrent fonts to both substrings
let font1: UIFont = UIFont(name: "Arial", size: 17.0)!
let attributes1 = [NSMutableAttributedString.Key.font: font1]
let attrString1 = NSMutableAttributedString(string: substring1, attributes: attributes1)
let font2: UIFont = UIFont(name: "Arial", size: 11.0)!
let attributes2 = [NSMutableAttributedString.Key.font: font2]
let attrString2 = NSMutableAttributedString(string: substring2, attributes: attributes2)
//appending both attributed strings
attrString1.append(attrString2)
//assigning the resultant attributed strings to the button
textResponseButton?.setAttributedTitle(attrString1, for: [])
}
Older Swift
#IBOutlet weak var btnTwoLine: UIButton?
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
//applying the line break mode
btnTwoLine?.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping;
var buttonText: NSString = "hello\nthere"
//getting the range to separate the button title strings
var newlineRange: NSRange = buttonText.rangeOfString("\n")
//getting both substrings
var substring1: NSString = ""
var substring2: NSString = ""
if(newlineRange.location != NSNotFound) {
substring1 = buttonText.substringToIndex(newlineRange.location)
substring2 = buttonText.substringFromIndex(newlineRange.location)
}
//assigning diffrent fonts to both substrings
let font:UIFont? = UIFont(name: "Arial", size: 17.0)
let attrString = NSMutableAttributedString(
string: substring1 as String,
attributes: NSDictionary(
object: font!,
forKey: NSFontAttributeName) as [NSObject : AnyObject])
let font1:UIFont? = UIFont(name: "Arial", size: 11.0)
let attrString1 = NSMutableAttributedString(
string: substring2 as String,
attributes: NSDictionary(
object: font1!,
forKey: NSFontAttributeName) as [NSObject : AnyObject])
//appending both attributed strings
attrString.appendAttributedString(attrString1)
//assigning the resultant attributed strings to the button
btnTwoLine?.setAttributedTitle(attrString, forState: UIControlState.Normal)
}
Output
I was looking for nearly the same topic, except that I don't need two different font sizes. In case someone is looking for a simple solution:
let button = UIButton()
button.titleLabel?.numberOfLines = 0
button.titleLabel?.lineBreakMode = .byWordWrapping
button.setTitle("Foo\nBar", for: .normal)
button.titleLabel?.textAlignment = .center
button.sizeToFit()
button.addTarget(self, action: #selector(rightBarButtonTapped), for: .allEvents)
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
I have notice an issue in most of the solutions which is while making line break mode to "Character Wrap" the second line will be left aligned to the first line
To make all the lines centered.
just change the title From Plain to Attributed and then you can make each line centered
change line break to character wrap , select your button and in attribute inspector go to line break and change it to character wrap
SWIFT 3 Syntax
let str = NSMutableAttributedString(string: "First line\nSecond Line")
str.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: 17), range: NSMakeRange(0, 10))
str.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: 12), range: NSMakeRange(11, 11))
button.setAttributedTitle(str, for: .normal)
I have fixed this and my solution it was only in the Storyboard.
Changes:
It added in Identity Inspector -> User Defined Runtime Attributes (these KeyPaths):
numberOfLines = 2
titleLabel.textAlignment = 1
User Defined Runtime Attributes
I added this in attributes inspector:
line break = word wrap
Word wrap
You need to do some of this in code. you can't set 2 different fonts in IB. In addition to changing the line break mode to character wrap, you need something like this to set the title,
override func viewDidLoad() {
super.viewDidLoad()
var str = NSMutableAttributedString(string: "First line\nSecond Line")
str.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(17), range: NSMakeRange(0, 10))
str.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(12), range: NSMakeRange(11, 11))
button.setAttributedTitle(str, forState: .Normal)
}
New with Xcode 13 (iOS 15)
Starting with Xcode 13, the button's title and subtitle may have their attributes set separately.
Using Storyboard:
In the Attribute Inspector for the button, select "Attributed" by Title. Then change font size of the title and the subtitle.
Or Programmatically:
// Create Title
let titleSettings = AttributeContainer.font( UIFont(name: "HelveticaNeue-Italic", size: 17)! )
yourButton.configuration?.attributedTitle = AttributedString("Button's Title", attributes: titleSettings)
// Create Subtitle
let subtitleSettings = AttributeContainer.font( UIFont(name: "HelveticaNeue-Italic", size: 11)! )
yourButton.configuration?.attributedSubtitle = AttributedString("Button's Subtitle", attributes: subtitleSettings)
One way to do it is with labels, I guess. I did this, and it seems to work ok. I could create this as a UIButton and then expose the labels, I guess. I don't know if this makes any sense.
let firstLabel = UILabel()
firstLabel.backgroundColor = UIColor.lightGrayColor()
firstLabel.text = "Hi"
firstLabel.textColor = UIColor.blueColor()
firstLabel.textAlignment = NSTextAlignment.Center
firstLabel.frame = CGRectMake(0, testButton.frame.height * 0.25, testButton.frame.width, testButton.frame.height * 0.2)
testButton.addSubview(firstLabel)
let secondLabel = UILabel()
secondLabel.backgroundColor = UIColor.lightGrayColor()
secondLabel.textColor = UIColor.blueColor()
secondLabel.font = UIFont(name: "Arial", size: 12)
secondLabel.text = "There"
secondLabel.textAlignment = NSTextAlignment.Center
secondLabel.frame = CGRectMake(0, testButton.frame.height * 0.5, testButton.frame.width, testButton.frame.height * 0.2)
testButton.addSubview(secondLabel)
The suggested solutions unfortunately did not work out for me when I wanted to have a mutliline button inside a CollectionView. Then a colleague showed me a workaround which I wanted to share in case someone has the same problem - hope this helps! Create a class which inherits from UIControl and extend it with a label, which will then behave similar like a button.
class MultilineButton: UIControl {
let label: UILabel = {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.numberOfLines = 0
$0.textAlignment = .center
return $0
}(UILabel())
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(label)
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
label.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
label.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor),
label.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor)
])
}
override var isHighlighted: Bool {
didSet {
backgroundColor = backgroundColor?.withAlphaComponent(isHighlighted ? 0.7 : 1.0)
label.textColor = label.textColor.withAlphaComponent(isHighlighted ? 0.7 : 1.0)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
my way:
func setButtonTitle(title: String, subtitle: String, button: UIButton){
//applying the line break mode
button.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping;
let title = NSMutableAttributedString(string: title, attributes: Attributes.biggestLabel)
let subtitle = NSMutableAttributedString(string: subtitle, attributes: Attributes.label)
let char = NSMutableAttributedString(string: "\n", attributes: Attributes.biggestLabel)
title.append(char)
title.append(subtitle)
button.setAttributedTitle(title, for: .normal)
}

Resources