How to bold first word of array? - arrays

var userComment = ["Time these make me.jenny is ","I can't she did it.", "Hey! what a great play made by brad", "I can't she .", "Time like make is a badass", "I can't it.", "She is a mean chose to place","Time me a badass", "Wow! I am just like jenny.I would shit", "I can't did it."]
first word of array in capital ex [TIME,I,HEY,WOW] other is same as written
var attributeCommentArray:[NSAttributedString] = []
override func viewDidLoad() {
super.viewDidLoad()
for comment in userComment {
if comment.contains("") {
let firstCharacter = comment.components(separatedBy: "").first ?? ""
let myString:NSMutableAttributedString = NSMutableAttributedString.init(string:comment)
myString.addAttribute(NSAttributedString.Key.font,
value: UIFont(
name: "HelveticaNeue-Bold",
size: 18.0)!,
range: NSRange(
location:0,
length:firstCharacter.count))
attributeCommentArray.append(myString)
} else {
attributeCommentArray.append(NSMutableAttributedString.init(string:comment))
}
}
// self.navTitleWithImageAndText(titleText: "oneTwoThree", imageName: "")
self.navigationController?.navigationBar.isHidden = false
// chatView.makeCornerRadius(self.chatView.layer.bounds.height / 2)
chatView.layer.borderWidth = 1
chatView.setCorner(borderWidth: 1, borderColor: UIColor.darkGray.cgColor, cornerRadius: 25, clip: true)
self.tblView.rowHeight = UITableView.automaticDimension
self.tblView.estimatedRowHeight = 60
tblView.delegate = self
tblView.dataSource = self
self.loadXib()
}
private func loadXib() {
tblView.loadXibForCellResuse(LiveCell.identifier)
}
}
extension LiveChatVC:UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.userName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tblView.dequeueReusableCell(withIdentifier: "LiveCell", for: indexPath) as! LiveCell
// cell.userName.text = self.userComment[indexPath.row]
// cell.userName.attributedText = myMutableString
cell.userName.attributedText = attributeCommentArray[indexPath.row]
return cell
}
}
[This is the implementation of code which is given by you please help it will not working in my controller it will print exactly the same text which is on the label,This is the implementation of code which is given by you please help it will not working in my controller it will print exactly the same text which is on the label]

Try the following code
var userComment = ["Time these make me.jenny is ","I can't she did it.", "Hey! what a great play made by brad", "I can't she .", "Time like make is a badass", "I can't it.", "She is a mean chose to place","Time me a badass", "Wow! I am just like jenny.I would shit", "I can't did it."]
var attributeCommentArray:[NSAttributedString] = []
for comment in userComment
{
if comment.contains(" ")
{
let firstWord = comment.components(separatedBy: " ").first ?? ""
let myString:NSMutableAttributedString = NSMutableAttributedString.init(string: comment)
myString.addAttribute(NSAttributedString.Key.font,
value: UIFont(
name: "HelveticaNeue-Bold",
size: 18.0)!,
range: NSRange(
location:0,
length:firstWord.count))
attributeCommentArray.append(myString)
}
else
{
attributeCommentArray.append(NSAttributedString.init(string: comment))
}
}
Create Attrinbuted String array and use that array in uitableview cell label
cellForRowMethod
lable.attributedText = attributeCommentArray[indexPath.row];

Related

Issue building proper array from tableview selections

Essentially I am adding or removing the cell values to an array that is built up based on which cells are selected/deselected.
I need my array to look like this:
[{"value":"One","id":"1"},{"value":"two","id":"4"}]
Currently it looks like this:
["One", "two"]
Currently the array does not include the struct titles (id and value) and does not include the curly brackets. The values for the id and values are coming from the array populating the tableview. How can this be done?
My code so far:
var structure = [Struct]()
var selectionArray: [String] = []
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell!.accessoryType = .checkmark
let item = structure[indexPath.row]
let cellvalue = item.value
selectionArray.append(cellvalue)
}
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell!.accessoryType = .none
let item = structure[indexPath.row]
let cellvalue = item.value
if let index = selectionArray.index(of: cellvalue) {
selectionArray.remove(at: index)
}
}
struct Struct: Decodable {
let id: Int
let value: String
}
You don't need to store the selectionArray array as a property at all. You can use indexPathsForSelectedRows to get all the selected rows. So you can generate the array whenever you need it.
let selectedIndexPaths = tableView.indexPathsForSelectedRows ?? []
// this contains the selected structs
let selectedStructs = selectedIndexPaths.map { structure[$0.row] }
Now you can encode it to JSON:
// remember to conform Struct to Codable!
let encoder = JSONEncoder()
do {
let jsonData = try encoder.encode(selectedStructs)
// if you want to see the encoded JSON string:
print(String(data: jsonData, encoding: .utf8)!)
} catch {
print(error)
}

How to pull out Data Array from CoreData TableView array, put it into a new Array and export it as csv?

I have an app that takes user inputs in an alertController, and then this values will be stored in CoreData which is then displayed in a tableview. I concatenated all the strings to gather with a comma as separator to make it easier for me to export a csv. However, when I print out the CoreData entity, I get an array that is quite complicated. The array looks like this:
[ (entity: AlarmItems; id: 0xc2bccd37cb753acb ; data: {
alarmAttributes = "Example Name, 24/11/2019, 1500, True, NIL";
}), (entity: AlarmItems; id: 0xc2bccd37cb653acb ; data: {
alarmAttributes = "Example , 12/12/2019, 24/11/2019, True, NIL";
})]
I would like to pull out just that parts after alarmAttributes to be exported into a CSV for further use.
I looked at NSEntityMapping but that did not help me. I'm quite stuck right now. I do not know how to approach the problem. Is my approach even correct in the first place? Is it even possible to export a csv using a an array that I create? The idea is to have the csv be stored in the iOS Device which can then be emailed elsewhere.
My ViewController:
class ViewController: UITableViewController {
var alarmItems: [NSManagedObject] = []
let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "AlarmItems")
do {
alarmItems = try managedContext.fetch(fetchRequest)
} catch let err as NSError {
print("Failed to fetch items", err)
}
}
#objc func addAlarmItem(_ sender: AnyObject) {
print("this works")
let alertController = UIAlertController(title: "Add New Item", message: "Please fill in the blanks", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
//combined string of attributes
let myStrings: [String] = alertController.textFields!.compactMap { $0.text }
let myText = myStrings.joined(separator: ", ")
self.save(myText)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
alertController.addTextField { (textField) in
textField.placeholder = "Enter Name of Engineer"
}
alertController.addTextField { (textField) in
textField.placeholder = "Enter Date of Alarm in DD/MM/YYYY"
}
alertController.addTextField { (textField) in
textField.placeholder = "Enter Time of Alarm in 24h (eg: 2300)"
}
alertController.addTextField { (textField) in
textField.placeholder = "Please indicate True/False (type True or False)"
}
alertController.addTextField { (textField) in
textField.placeholder = "Insert comments (if any), or NIL"
}
alertController.addAction(saveAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
func save(_ itemName: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "AlarmItems", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
item.setValue(itemName, forKey: "alarmAttributes")
do {
try managedContext.save()
alarmItems.append(item)
} catch let err as NSError {
print("Failed to save an item", err)
}
}
#objc func exportCSV(_ sender: AnyObject) {
//will work on exporting csv in the future
return
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return alarmItems.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let alarmItem = alarmItems[indexPath.row]
cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
return cell
}
}

how to append something to array correctly?

I'm going to make a custom cell, already have some labels on it, then I create a cell object and array, try to append that object to array then show on table, but after append, there's no content in my array's properties
I've tried to find out solutions but likely no one has these problems
//tableview implement
var recordCell : [RecordCell] = []
let note = RecordCell()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.recordCell.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "recordCell",for: indexPath) as! RecordCell
let indexPath = indexPath.row
cell.recordFileName?.text = self.recordCell[indexPath].recordFileName?.text
cell.recordDate?.text = self.recordCell[indexPath].recordDate?.text
cell.delegate = self
cell.playBtn.tag = indexPath
return cell
}
//append to array
let alertController = UIAlertController(title: "請輸入錄音名稱", message: "錄音名稱", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default) { (_) in
var name : String = ""
if(alertController.textFields![0].text == ""){
name = "record"
}else{
name = alertController.textFields![0].text!
}
guard self.audioRecorder == nil else{return}
self.recordNumber += 1
self.record.isEnabled = false
self.pause.isEnabled = true
self.stop.isEnabled = true
let destinationUrl = self.getFileURL().appendingPathComponent("\(name).m4a")
let settings = [AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 2,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
do {
self.audioRecorder = try AVAudioRecorder(url: destinationUrl, settings: settings)
self.audioRecorder.record()
self.note.recordFileName?.text = name
self.note.recordDate?.text = self.getDate()
self.recordCell.append(self.note)
} catch {
print("Record error:", error.localizedDescription)
}
}
let cancelAction = UIAlertAction(title: "取消", style: .cancel) { (_) in
self.dismiss(animated: true, completion: {
self.audioRecorder.stop()
})
}
alertController.addTextField { (textField) in
textField.placeholder = "輸入名稱"
textField.keyboardType = .default
}
alertController.addAction(okAction)
alertController.addAction(cancelAction)
self.present(alertController,animated: true,completion: nil)
}
I expect when I append something, there's something in array
After appending a new value to the array, call insertRows method like this
self.recordCell.append(self.note)
self.tableView.insertRows(at: [IndexPath(row: recordCell.count-1, section: 0)], with: .automatic)
I didnt see anything wrong.
Are you sure your code is called? Try giving a print() right before adding and see if it's called.
Maybe it's not called because of guard self.audioRecorder == nil else{return}

ping through host array and show results in table

I am trying to ping an array containing different hosts. In each loop, I am saving an image depending on whether the ping was successful or not (checkImg, errorImg). Afterwards, I want to present the information (hostname and img) in a table.
The following code does work somehow but it is not stable. Sometimes I receive the following warning:
Thread 1: Fatal error: Index out of range In line: imgServer.image =
UIImage(named: statusImagesMain[indexPath.row])
So I suppose the ping loop for the different hosts did not get completed before serverStatusTable.reloadData() is executed.
Do you have any idea what I can do to overcome this problem?
swift 4
import UIKit
class ServerVC: SimplePingDelegate, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var serverStatusTable: UITableView!
let imageError = UIImage(named: "error")
let imageCheck = UIImage(named: "check")
var pings = ["www.apple.com", "www.appleidontknowwhy.de", "www.apple.com", "www.apple.com"]
var hosts = [String]() // hostnames which get pinged
var componentTextArray = [String]() // project names
var statusImagesTemporary = [String]() // temporary store images
var statusImagesMain = [String]() // array filled with temporary stored images
var serverStatusMain = [String]() // server status string (connected, error)
var serverStatusTemporary = [String]() // temporary server status
override func viewDidLoad() {
super.viewDidLoad()
serverStatusTable.dataSource = self
serverStatusTable.delegate = self
statusImagesMain = ["error", "error", "error", "error"]
componentTextArray = ["Project 1", "Project 2", "Project 3", "Project 4"]
serverStatusMain = ["no data", "no data", "no data", "no data"]
hosts = pings
pingNext()
serverStatusTable.reloadData()
}
override func viewDidAppear(_ animated: Bool) {
// initial ping host process when loading the view
startHostRequest()
}
#IBAction func refreshBtnAction(_ sender: Any) {
// manual ping host process when clicking the button "refresh"
startHostRequest()
}
func startHostRequest () {
print("refresh server status")
pingNext()
// clear array before each host ping process in order for the array to keep only four items
statusImagesMain.removeAll()
serverStatusMain.removeAll()
for statusImageTemporary in statusImagesTemporary {
statusImagesMain.append(statusImageTemporary)
}
for i in serverStatusTemporary {
serverStatusMain.append(i)
}
serverStatusTable.reloadData()
}
func pingNext() {
guard pings.count > 0 else {
return
}
let ping = pings.removeFirst()
PlainPing.ping(ping, withTimeout: 1.0, completionBlock: { (timeElapsed:Double?, error:Error?) in
if let latency = timeElapsed {
print("\(ping) latency (ms): \(latency)")
// fill temporary arrays with img and serverStatus text for successful connection
self.statusImagesTemporary.append("check")
self.serverStatusTemporary.append("Running ")
}
if let error = error {
print("error: \(error.localizedDescription)")
// fill temporary arrays with img and serverStatus text for failed connection attempt
self.statusImagesTemporary.append("error")
self.serverStatusTemporary.append("Error ")
}
self.pingNext()
})
}
// fill table with host data
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return componentTextArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = serverStatusTable.dequeueReusableCell(withIdentifier: "serverStatusCell", for: indexPath)
let lblServerStatus : UILabel = cell.contentView.viewWithTag(8) as! UILabel
let imgServer : UIImageView = cell.contentView.viewWithTag(7) as! UIImageView
imgServer.image = UIImage(named: statusImagesMain[indexPath.row])
lblServerStatus.text = serverStatusMain[indexPath.row]
return cell
}
}
Your bug lies in startHostRequest() and tableView(_ tableView: UITableView, numberOfRowsInSection section: Int).
In startHostRequest() you copy statusImagesTemporary to statusImagesMain, and statusImageTemporary is empty at the start, and it finishes with .reloadData(). tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) returns componentTextArray.count which is always 4. When these two are put together once startHostRequest() is called the table is reloaded, instructed to have 4 rows, but there are 0 rows of data to fill in the rows.
Managing your UITableView can be simplified by using ALTableViewHelper [commercial - available on here
]. The UITableView’s cells are maintained for you - matched, in your case, to the contents of statusImagesTemporary:
class ServerVC: UIViewController, UITableViewDelegate {
#IBOutlet weak var serverStatusTable: UITableView!
#objc let imageError = UIImage(named: "error")
#objc let imageCheck = UIImage(named: "check")
var pings = ["www.apple.com", "www.appleidontknowwhy.de", "www.apple.com", "www.apple.com"]
var hosts = [String]() // hostnames which get pinged
#objc var componentTextArray = [String]() // project names
#objc var serverStatusMain = NSMutableArray() // not [String]() to allow changes to be observed
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// do not set dataSource, but instead:
serverStatusTable.setHelperString(
"section\n" +
" body\n" +
" serverStatusCell * serverStatusMain\n" +
" $.viewWithTag:(8).text <~ #[1] == 'error' ? 'Error ' : 'Running '\n" +
" $.viewWithTag:(7).image <~ #[1] == 'error' ? imageError : imageCheck \n" +
" $.viewWithTag:(2).text <~ componentTextArray[#[0]]\n" +
"", context:self)
// # is the value from the array (serverStatusMain), and $ is the serverStatusCell for #
// The selector for UIView.viewWithTag() is 'viewWithTag:', which is why you see that in the helper string
// Short arrays were added below as the values in serverStatusMain. In each short array:
// [0] is the index into hosts[] and componentTextArray[]
// [1] is the result of the ping, ie "check" or "error"
// so #[0] is the index and #[1] is the result of the ping
serverStatusTable.delegate = self
componentTextArray = ["Project 1", "Project 2", "Project 3", "Project 4"]
hosts = pings
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
// initial ping host process when loading the view
startHostRequest()
}
#IBAction func refreshBtnAction(_ sender: Any) {
// manual ping host process when clicking the button "refresh"
startHostRequest()
}
func startHostRequest () {
// I thought you might need this here so that the 2nd and later ‘starts’ do the whole list
pings = hosts
// This will empty your UITableView
serverStatusMain.removeAllObjects()
print("refresh server status")
pingNext()
}
func pingNext() {
guard pings.count > 0 else {
return
}
let ping = pings.removeFirst()
PlainPing.ping(ping, withTimeout: 1.0, completionBlock: { [weak self](timeElapsed:Double?, error:Error?) in
if let me = self {
if let latency = timeElapsed {
print("\(ping) latency (ms): \(latency)")
me.serverStatusMain.add([me.serverStatusMain.count, "check"])
}
if let error = error {
print("error: \(error.localizedDescription)")
me.serverStatusMain.add([me.serverStatusMain.count, "error"])
}
me.pingNext()
}
})
}
}
You can see the complete demo project including this code here.

Rearranging cells between sections

I know how to swap cells if they are underneath one section because internet is full of that but I'm struggling with the same having two sections. I cannot move every cell because obviously index is out of range. I thought it would be unnecessary to post the whole code so I'll paste only the important bits
I have declared:
let sections: [String] = ["Box", "Inventory"]
var s1Data: [UIImage] = [] //
var s2Data: [UIImage] = [] //these are filled by other function
let sectionsImages: [UIImage] = [#imageLiteral(resourceName: "blackBox"), #imageLiteral(resourceName: "blackBag")]
var sectionData: [[UIImage]] = []
In viewDidLoad():
tableView.isEditing = true
tableView.delegate = self
tableView.dataSource = self
sectionData = [s1Data, s2Data]
Then quite a number of tableView functions, but the one I cannot go through and the one I'm talking about:
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)
{
let item = sectionData[sourceIndexPath.row]
sectionData.remove(at: sourceIndexPath.row)
sectionData.insert(item, at: destinationIndexPath.row)
}
And so, swapping goes fine until I try to swap the last image cell because of mentioned 'out of bounds' failure. I know I should declare item as something like:
let item = sectionData[sourceIndexPath.section][sourceIndexPath.row]
but what about "remove" and "insert"?
I would be thankful for your help
EDIT:
I did it, although I don't know if it is one of the simpler way. Anyway:
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)
{
if sourceIndexPath.section == 0 && destinationIndexPath.section == 0
{
let item = sectionData[0][sourceIndexPath.row]
sectionData[0].remove(at: sourceIndexPath.row)
sectionData[0].insert(item, at: destinationIndexPath.row)
}
else if sourceIndexPath.section == 0 && destinationIndexPath.section == 1
{
let item = sectionData[0][sourceIndexPath.row]
sectionData[0].remove(at: sourceIndexPath.row)
sectionData[1].insert(item, at: destinationIndexPath.row)
}
else if sourceIndexPath.section == 1 && destinationIndexPath.section == 0
{
let item = sectionData[1][sourceIndexPath.row]
sectionData[1].remove(at: sourceIndexPath.row)
sectionData[0].insert(item, at: destinationIndexPath.row)
}
else if sourceIndexPath.section == 1 && destinationIndexPath.section == 1
{
let item = sectionData[1][sourceIndexPath.row]
sectionData[1].remove(at: sourceIndexPath.row)
sectionData[1].insert(item, at: destinationIndexPath.row)
}
else
{
print("ERROR - SWAP MALFUNCTION")
}
}
This is how I did it, the insert uses the destinationIndexPath.section:
groupItems[sourceIndexPath.section].remove(at: sourceIndexPath.row)
groupItems[destinationIndexPath.section].insert(movedObject, at: destinationIndexPath.row)

Resources