I am trying to figure out how to use a progressView to show the progress of a something being downloaded using Realm. Through reading it seems that a Float called progress needs to be found, but I don't know how to find that in Realm. I have looked at the following questions, but I don't think that they are too helpful in this situation:
Swift: Realm - Update UI (Progress) while adding Data to DB
iOS-Swift How to update progressView
This is what I have at the moment:
ViewController:
import UIKit
import Realm
import RealmSwift
class ViewController: UIViewController {
var data = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."
var realm: Realm!
#IBOutlet weak var saveBtn: UIButton!
#IBOutlet weak var progressView: UIProgressView!
override func viewDidLoad() {
super.viewDidLoad()
print("Hello")
print(Realm.Configuration.defaultConfiguration.fileURL!)
realm = try! Realm()
}
#IBAction func saveBtnPressed(_ sender: Any) {
saveToRealm(id: 1, name: "One", data: data)
let progress: Float = 0
progressView.setProgress(progress, animated: true)
}
func saveToRealm(id: Int, name: String, data: String) {
let realmSave = RealmSave()
realmSave.id = id
realmSave.name = name
realmSave.data = data
try? realm!.write {
realm.add(realmSave, update: true)
}
}
}
If there is anything that I can help with, please ask. Thank you
First: defining a let constant with a value of 0 will always stay 0. You can't dynamically change that to reflect the state of your download.
As a Realm engineer pointed out in this post "Realm has no way to know the total amount of data."
Estimating the progress should be done in your code.
You could try something like this:
func estimateProgress() {
let dataString = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."
let data = dataString.data(using: .utf8)
let count = Float((data?.count)!)
let percentage: Float = count / 100
var progress: Float = 0
if progress < count {
progress += percentage
} else {
progress = count
}
progressView.setProgress(progress, animated: true)
print(progress)
}
Please note that this solution is for updating the UI and letting the user know that the saving to Realm is in progress. Since it uses the amount of bytes in the data, the larger the data, the longer it will take for the progress bar to fill. So it is good for UI, but it is not the actual state of progress.
And if you feel the progress bar is filling to slow/fast you can always tweak the percentage.
Related
I'm using bookdown to prepare some documents.
For some reasons I need to have bigger font size for headings and main text and smaller font-size for tables.
The simple minimal reproducible example is below:
---
papersize: a6
geometry: 'landscape'
site: bookdown::bookdown_site
output:
bookdown::pdf_document2:
latex_engine: xelatex
header-includes:
- \usepackage[fontsize=15pt]{scrextend}
---
Below is a table with narrow first column and wide second column:
| **Seq** | **Description** |
|:---:|-------------|
| `1` | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. |
| `2` | Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. |
Link to intermediate LaTeX file.
Is it possible to decrease font size for tables to make it smaller than now?
You can force a smaller font size for longtable by adding
\AtBeginEnvironment{longtable}{\tiny}
to your header-includes
Let's say I have some text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris\n
nisi ut aliquip ex ea commodo consequat.\n
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore\n
eu fugiat nulla pariatur.\n
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia\n
deserunt mollit anim id est laborum.\n
What is the most efficient way to cut it into chunks of x bytes, where the cut can only happen at the carriage return?
Two methods come to mind:
split the text into lines, add lines to a buffer until the buffer is full, roll back the last line that caused the overflow, and repeat.
find the offset in the text at the buffer length and walk back to the previous carriage return, with proper handling of the beginning and ending of the text
I couldn't find a solution online, but I can't believe that this problem hasn't already been solved many times, and there may be a common implementation of this.
Edit:
more information about my use case:
The code is for a Telegram bot which is used as a communication tool with an internal system.
Telegram allows up to 4kb per message and throttles the number of calls.
Right now I collect all messages, put them in a concurrent queue and then a tasks flushes the queue every second.
Messages can be a single line, can be a collection of lines and can sometimes be larger than 4kb.
I take all the messages (some being multiple lines in one block), aggregate them into a single string, then split the string by carriage return and then I can compose blocks of up to 4kb.
One additional problem I haven't tackled yet, but that's for later, is that Telegram will reject incomplete markup, so I will also need to cut the text based on that at some point.
Not very efficient, and also laboring under the assumptions
that you may want to preserve the newline separators, and
that we can assume that the end of the string is equivalent
to a single newline;
then, an implementation along the lines of your first approach is both functional and straightforward. Just split into lines and combine them unless their combined length exceeds the threshold.
// Comma-separated output of the string lengths
// (plus 1 to compensate for the absence of the EOL)
let printLengths =
Array.map (String.length >> (+) 1 >> string)
>> String.concat ", "
>> printfn "%s"
let text =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
"
text.Split '\n' |> printLengths
// prints 57, 67, 67, 41, 77, 26, 74, 37, 1, 1
let foo n (text : string) =
(text.Split '\n', [])
||> Array.foldBack (fun t -> function
| x::xs when String.length x + t.Length + 1 < n -> x+"\n"+t::xs
| xs -> t::xs )
text |> foo 108 |> List.toArray |> printLengths
// prints 57, 67, 108, 77, 100, 39
Most common stream related tasks are already implemented very efficiently in the BCL.
It's probably a good idea to stick with tried-and-tested Stream classes.
let lipsum =
"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
"""
use stream = new MemoryStream(Encoding.UTF8.GetBytes(lipsum))
use reader = new StreamReader(stream)
let readBlock blockSize =
let writer = new StringBuilder(capacity = blockSize)
let rec readNextline () =
if (not reader.EndOfStream) then do
let line = reader.ReadLine()
if writer.Capacity < line.Length + writer.Length then do
stream.Seek(int64 -line.Length, SeekOrigin.Current) |> ignore
else
writer.AppendLine(line) |> ignore
readNextline ()
readNextline ()
writer.ToString()
readBlock 300 |> printfn "%s"
You can just flush the queue, writing to the same MemoryStream. And call readBlock to keep getting new blocks of at-most your specified size.
I'm using Swift and am having some issues with making my table view cells self-sizing. From what I have read online the best way is to use:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 138.0
I have put this code in but it hasn't seemed to work. I've tried it within viewDidLoad and also the cellForRowAt function. I'm not sure if I'm putting it in the wrong place or if I've set something up wrong. I have also got my auto constraint for the bottom of my UILabel set in relation to the bottom of the container with the expectation that the cell container will grow but the bottom of the UILabel to the bottom on the container will remain constant. Here is the code I currently have in my TableViewController:
class TableViewController: UITableViewController {
var data = [TextData]()
override func viewDidLoad() {
super.viewDidLoad()
loadSampleData()
}
func loadSampleData() {
let title1 = TextData(title: "Monday", blurb: "Today is Monday and it's a sunny day", photograph: #imageLiteral(resourceName: "mondayone"), article: "Monday Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")
let title2 = TextData(title: "Tuesday", blurb: "Today is Tuesday and it's a bit rainy but will clear up later on today", photograph: #imageLiteral(resourceName: "tuesdaytwo"), article: "Tuesday Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur." )
let title3 = TextData(title: "Wednesday", blurb: "Today is Wednesday and the umbrella should be handy because it's going to be stormy", photograph: #imageLiteral(resourceName: "wednesdaythree"), article: "Wednesday Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.")
let title4 = TextData(title: "Thursday", blurb: "Today is Thursday and it's sunny again, no need for any umbrella today!", photograph: #imageLiteral(resourceName: "thursdayfour"), article: "Thursday Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.")
data += [title1, title2, title3, title4]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "TitleTextCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! TableViewCell
let realData = data[(indexPath as NSIndexPath).row]
cell.titleLabel.text = realData.title
cell.bodyText.text = realData.blurb
cell.photo.image = realData.photograph
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 138.0
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Here is what my tableview currently looks like:
Here are my current constraints:
Currently photo is preventing your cell from getting taller. Since photo is constrained to both the top and centre of the cell, making the cell taller would always make the image taller, but since the image has a height constraint, photo stops the cell from getting taller.
Remove the Photo.centerY constraint should allow the cell resize based on the label. Or, you could change the constaraint to an inequality (≤ or ≥, cant remember which). That should limit the cell from getting to small if there isn't already another constraint that does that.
Aim:
To display a multiline label on a custom cell in a UITableView using autolayout and UITableViewAutomaticDimension.
The cell should vary based on the text in each UILabel.
What I have done:
Used auto layout
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 100
label.numberOfLines = 0 (label is the new label I created)
label.setTranslatesAutoresizingMaskIntoConstraints(false)
Added UILabel to the contentView
Added constraints from the UILabel to content view
Problem:
Some text gets clipped (...) when I use a custom cell
Sometimes the scrolling is not very smooth
Tried same with UITableViewCell:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 100
textLabel.numberOfLines = 0 (textLabel already exists in UITableViewCell)
Scrolling seems smooth
No clipping, text is displayed correctly
Printed the cell.textLabel?.preferredMaxLayoutWidth and it shows 0
Question:
Why is it working fine with UITableViewCell and not my custom cell ?
In both cases the preferredMaxLayoutWidth is not being set.
Pls let me know what I am missing.
Code for my custom cell:
class MultilineLabelCell : UITableViewCell {
let label = UILabel()
//MARK: Initializers
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setup()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
//MARK: Setup Views
func setup() {
setupLabel()
setupLayout()
}
func setupLabel() {
label.setTranslatesAutoresizingMaskIntoConstraints(false)
label.numberOfLines = 0
contentView.addSubview(label)
}
func setupLayout() {
let views = ["label" : label]
let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label]-|",
options: .allZeros,
metrics: nil,
views: views)
let verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|-[label]-|",
options: .allZeros,
metrics: nil,
views: views)
contentView.addConstraints(horizontalConstraints)
contentView.addConstraints(verticalConstraints)
}
}
View Controller Code
override func loadView() {
super.loadView()
tableView.registerClass(MultilineLabelCell.self, forCellReuseIdentifier: ViewController.cellIdentifier)
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 100
}
func populateData() {
dataArray.append("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat")
dataArray.append("Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum")
dataArray.append("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,")
dataArray.append("nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?")
dataArray.append("But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?")
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(ViewController.cellIdentifier) as! MultilineLabelCell
cell.label.numberOfLines = 0
cell.label.text = dataArray[indexPath.row]
return cell
}
While giving constraints programatically views/controls in content view of UITableViewCell and want to have dynamic cell size based on your text length, you need to give padding from all four sides explicitly(provide some value). Do changes as per below. Looks like a bug
In setupLayout method
func setupLayout() {
let views = ["label" : label]
let horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|-5-[label]-5-|",
options: .allZeros,
metrics: nil,
views: views)
let verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|-5-[label]-5-|",
options: .allZeros,
metrics: nil,
views: views)
contentView.addConstraints(horizontalConstraints)
contentView.addConstraints(verticalConstraints)
}
in my application I have a UILabel with a lot of text inside. When the user performs a research I want to highlight the background under the text searched by the user.
Here an example from "Preview" in MacOSX.
The user searches silence and this word is highlighted in the text.
Any ideas ?
Thanks.
You'll need to enable the 'attributed' text of the UILabel (or UITextView/custom view). Then you'll need to find/make a nice/fast algorithm to change the color (bg/text) color of some parts of the text. You should be able to find quite a lot on 'attributed string' algorithms to mark some words/matches.
Please check also http://iphonedevelopment.blogspot.be/2011/03/attributed-strings-in-ios.html
In case of, it can maybe be easier/quicker to use a webview by making a custom HTML with the matched-words in another color/bg-color. A webview can almost look like a normal label, and offers even the option to use links/images/..., which can improve the user-experiences in some cases
Maybe this is an old question. But I think this will help to someone.
To highlight a part of text in UILabel, I have written an open source named HighlightLabel.
You can simply specify the hightlightText and highlightColor to highlight it.
_highlightLabel.text = #"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.";
_highlightLabel.highlightText = #"Lorem ipsum dolor sit er elit lamet";
_highlightLabel.highlightColor = [UIColor yellowColor];
You'll have to use NSAttributedString for this.
This might also help. It is a subclass of UILabel that draws an NSAttributedString and also provides convenience methods for setting the attributes of an NSAttributedString from UIKit classes.
Once desired letters/Characters are found, highlight that part of UIView or anything you are using there.