I've been trying to display a plist file in NSTableView for days. I've read a lot, but so far only found instructions for iOS. My problem is that the individual values are not displayed individually in the NStableView. Only the whole plist file in a cell is always displayed.
I hope someone can help me, because I just can not get any further. I'm still a freshman in Swift.
I uploaded my Plist, if someone can explain me where the error lies.
https://www.dropbox.com/s/1t8c4uldwdtp3wk/Archiv.zip?dl=0
import Cocoa
class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
#IBOutlet weak var tableView: NSTableView!
#IBOutlet weak var ntext: NSTextField!
#IBOutlet weak var schwarztext: NSTextField!
#IBOutlet weak var cyantext: NSTextField!
#IBOutlet weak var magentatext: NSTextField!
#IBOutlet weak var gelbtext: NSTextField!
#IBOutlet weak var lightcyantext: NSTextField!
#IBOutlet weak var lightmtext: NSTextField!
var n : String? = nil; // n
var schwarz : String? = nil; // Schwarz
var cyan : String? = nil; // Cyan
var magenta : String? = nil; // Magenta
var gelb : String? = nil; // Gelb
var lightc : String? = nil; // Light Cyan
var lightm : String? = nil; // Light Magenta
let AUTO_PLIST_JOBS_PATH = Bundle.main.path(forResource: "Jobs", ofType: "plist")
let AUTO_PLIST_JOBS_KEY_N = "n" // n
let AUTO_PLIST_JOBS_KEY_SCHWARZ = "schwarz" // Schwarz
let AUTO_PLIST_JOBS_KEY_CYAN = "cyan" // Cyan
let AUTO_PLIST_JOBS_KEY_MAGENTA = "magenta" // Magenta
let AUTO_PLIST_JOBS_KEY_GELB = "gelb" // Gelb
let AUTO_PLIST_JOBS_KEY_LIGHTC = "lightc" // Light Cyan
let AUTO_PLIST_JOBS_KEY_LIGHTM = "lightm" // Light Magenta
var _jobss = [Jobs]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view.
}
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
//let path = Bundle.main.path(forResource: "Jobs", ofType: "plist")
//let myJobs100 = NSArray(contentsOfFile: path!)
//return myJobs100
let path = Bundle.main.path(forResource: "Jobs", ofType: "plist")
let url = URL(fileURLWithPath: path!)
let data = try! Data(contentsOf: url)
let plist = try! PropertyListSerialization.propertyList(from: data, options: .mutableContainers, format: nil)
let dictArray = plist as! [[String:String]]
return dictArray
}
func allJobss() -> [Jobs]{
if _jobss.count > 0 {
return _jobss
}
if let allDatas = NSArray(contentsOfFile: AUTO_PLIST_JOBS_PATH!) {
for dict in allDatas {
guard let dict = dict as? [String: AnyObject] else {continue}
let jobs = Jobs()
jobs.n = dict[AUTO_PLIST_JOBS_KEY_N] as? String // n
jobs.schwarz = dict[AUTO_PLIST_JOBS_KEY_SCHWARZ] as? String // Schwarz
jobs.cyan = dict[AUTO_PLIST_JOBS_KEY_CYAN] as? String // Cyan
jobs.magenta = dict[AUTO_PLIST_JOBS_KEY_MAGENTA] as? String // Magenta
jobs.gelb = dict[AUTO_PLIST_JOBS_KEY_GELB] as? String // Gelb
jobs.lightc = dict[AUTO_PLIST_JOBS_KEY_LIGHTC] as? String // Light Cyan
jobs.lightm = dict[AUTO_PLIST_JOBS_KEY_LIGHTM] as? String // Light Magenta
_jobss.append(jobs)
}
}
return _jobss
}
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
return 80
}
func numberOfRows(in tableView: NSTableView) -> Int {
return allJobss().count
}
func tableViewSelectionDidChange(_ notification: Notification) {
print(tableView.selectedRow)
let path = Bundle.main.path(forResource: "Jobs", ofType: "plist")
let url = URL(fileURLWithPath: path!)
let data = try! Data(contentsOf: url)
let plist = try! PropertyListSerialization.propertyList(from: data, options: .mutableContainers, format: nil)
let dictArray = plist as! [[String:String]]
// [[String:String]] is equivalent to Array< Dictionary<String, String> >
print(dictArray[tableView.selectedRow]["n"] as Any)
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
NSTableview
Plist
I hope someone can help me.
First of all this is Swift. Variable names including underscore characters are ugly and objective-c-ish.
Your workflow is wrong. objectValueFor is called very often (once for each row) and is supposed to return just the object for the given row/column. Reading the same data again and again is horrible.
Load the data once in viewDidLoad and decode the Plist directly into a class. A class is required to be able to bind the values
#objcMembers
class Job : NSObject, Decodable {
dynamic var n, schwarz, cyan, magenta, gelb, lightc, lightm : String
}
#objc dynamic var jobs = [Job]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view.
let url = Bundle.main.url(forResource: "Jobs", withExtension: "plist")!
let data = try! Data(contentsOf: url)
jobs = try! PropertyListDecoder().decode([Job].self, from: data)
tableView.reloadData()
}
In objectValueFor just return the item for the row
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
return jobs[row]
}
the other delegate methods are
func numberOfRows(in tableView: NSTableView) -> Int {
return jobs.count
}
func tableViewSelectionDidChange(_ notification: Notification) {
let selectedRow = tableView.selectedRow
if selectedRow == -1 {
print("Nothing selected")
} else {
print("Row \(selectedRow) selected")
}
}
You have to bind the values to text fields. Open Interface Builder, ⌃⇧-click on the left-most text field (Table View Cell) in the table view, select Table View Cell, press ⌥⌘7 to open the Bindings Inspector, click on the disclosure triangle below Value, Check the checkbox Bind to Table Cell View, in the Model Key Path text field write objectValue.n. Bind the other text fields in the row to the corresponding properties (objectValue.schwarz etc.).
You can delete
var n : String? = nil; // n
var schwarz : String? = nil; // Schwarz
var cyan : String? = nil; // Cyan
var magenta : String? = nil; // Magenta
var gelb : String? = nil; // Gelb
var lightc : String? = nil; // Light Cyan
var lightm : String? = nil; // Light Magenta
let AUTO_PLIST_JOBS_PATH = Bundle.main.path(forResource: "Jobs", ofType: "plist")
let AUTO_PLIST_JOBS_KEY_N = "n" // n
let AUTO_PLIST_JOBS_KEY_SCHWARZ = "schwarz" // Schwarz
let AUTO_PLIST_JOBS_KEY_CYAN = "cyan" // Cyan
let AUTO_PLIST_JOBS_KEY_MAGENTA = "magenta" // Magenta
let AUTO_PLIST_JOBS_KEY_GELB = "gelb" // Gelb
let AUTO_PLIST_JOBS_KEY_LIGHTC = "lightc" // Light Cyan
let AUTO_PLIST_JOBS_KEY_LIGHTM = "lightm" // Light Magenta
func allJobss() -> [Jobs]{
if _jobss.count > 0 {
return _jobss
}
if let allDatas = NSArray(contentsOfFile: AUTO_PLIST_JOBS_PATH!) {
for dict in allDatas {
guard let dict = dict as? [String: AnyObject] else {continue}
let jobs = Jobs()
jobs.n = dict[AUTO_PLIST_JOBS_KEY_N] as? String // n
jobs.schwarz = dict[AUTO_PLIST_JOBS_KEY_SCHWARZ] as? String // Schwarz
jobs.cyan = dict[AUTO_PLIST_JOBS_KEY_CYAN] as? String // Cyan
jobs.magenta = dict[AUTO_PLIST_JOBS_KEY_MAGENTA] as? String // Magenta
jobs.gelb = dict[AUTO_PLIST_JOBS_KEY_GELB] as? String // Gelb
jobs.lightc = dict[AUTO_PLIST_JOBS_KEY_LIGHTC] as? String // Light Cyan
jobs.lightm = dict[AUTO_PLIST_JOBS_KEY_LIGHTM] as? String // Light Magenta
_jobss.append(jobs)
}
}
return _jobss
}
Related
I am currently building a table view and I noticed that after my table view is populated I am getting two search bar fields. My original intention was to have only one search bar field appear (shown on my interface) I can't seem to figure out what this happens. When I try to delete the search bar from my interface then my table view will not load and populate data.
Here is a screenshot of the interface storyboard:
Here is the screenshot of when I run the app:
Here is some code including my viewDidLoad:
EDIT: Added TableView Code
class AddHarvestPlanViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var AddHarvestPlanPluCodeTable: UITableView!
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
findPluCodeParents(searchTextField: "apple")
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Find your Commodity"
navigationItem.searchController = searchController
definesPresentationContext = true
AddHarvestPlanPluCodeTable.delegate = self
AddHarvestPlanPluCodeTable.dataSource = self
AddHarvestPlanPluCodeTable.reloadData()
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count = harvestCommodities.count
return count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "AddPluCodeCustomCell", for: indexPath) as! AddPluCodeCustomCell
do{
let item = harvestCommodities[indexPath.row]
cell.commodity?.text = item.plu_code_commodity
cell.package?.text = "Cases"
return cell
}
}
func findPluCodeParents(searchTextField:String){
let searchText = searchTextField
print("Searching for....",searchTextField)
let aggriEndpoint: String = "https://xxxx.xxxx.com/xxxx/xxxxx"
let url = URL(string:aggriEndpoint)
var urlRequest = URLRequest(url:url!)
urlRequest.httpMethod = "GET"
let session = URLSession.shared
print("running task")
let task = session.dataTask(with: urlRequest, completionHandler: {data,response,error -> Void in
do{
print("All finiished")
print(data)
if let json = try JSONSerialization.jsonObject(with: data!) as? [[String:Any?]]{
// print(json)
for item in json{
print(item as? [String:Any?])
var active = item["active"] as? Bool
let cases_per_week = (item["cases_per_week"] as! NSString).doubleValue
var cases_per_palette = item["cases_per_pallette"] as? Int
var lbs_per_week = (item["lbs_per_week"] as! NSString).doubleValue
var cases_per_week_avg = item["cases_per_week_avg"] as? Int
var pounds_per_case = item["pounds_per_case"] as? Int
var repeat_harvest = item["repeat_harvest"] as? Bool
var harvest_week_count = item["harvest_week_count"] as? Int
var plant_days = item["plant_days"] as? Int
var pounds_per_acre = item["pounds_per_acre"] as? Int
var options = item["options"] as? Int
var plu_code_variety = item["plu_code_variety"] as? String
var plu_code_commodity = item["plu_code_commodity"] as? String
var id = item["id"] as? Int
var plu_code = item["plu_code"] as? Int
var acres = item["acres"] as? Int
self.harvestCommodities.append(PluCode(id: id!, commodity: plu_code_commodity!, cases_per_week_avg: cases_per_week_avg!, repeat_harvest: repeat_harvest!, cases_per_week: cases_per_week, lbs_per_week: lbs_per_week, acres: acres!, plu_code: plu_code!, active: active!, options: options!, plant_days: plant_days!, plu_code_commodity: plu_code_commodity!, plu_code_variety: plu_code_variety!, cases_per_palette: cases_per_palette!, harvest_week_count: harvest_week_count!, pounds_per_acre: pounds_per_acre!))
}
}
DispatchQueue.main.async {
self.AddHarvestPlanPluCodeTable.reloadData()
}
} catch let error{
print("error")
}
})
task.resume()
}
Either remove the code where you create the upper Search Bar, ("let searchController = UISearchController(searchResultsController: nil)") and then connect an IBOutlet to the one you have created on the interface to your swift file, or remove the one on the storyboard and use the one you have created in your code, and connect the results to your table view
I have a chat feature on my app that updates the table instantly when a user enters new text. Unfortunately when a user enters the text it shows any empty row in the uitableview. When I exit out of the screen and return that new value is now there at the end of the table. So even though it's showing an empty row in the uitableview it's submitting the actual value to the database.
class ConversationViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate {
//var user = NSDictionary()
var messages = NSDictionary()
var hhmessages = [AnyObject]()
//var messages: [Message] = []
var pictures = [UIImage]()
var avas = [UIImage]()
var avaURL = [String]()
var isLoading = false
var skip = 0
var limit = 50
var images = [UIImage]()
var incoming: [Int] = []
var comments = [String]()
var ids = [String]()
#IBOutlet var replyTxt: UITextView!
#IBOutlet var replyTxt_height: NSLayoutConstraint!
#IBOutlet var replyTxt_bottom: NSLayoutConstraint!
#IBOutlet var replyBtn: UIButton!
var commentsTextView_bottom_identity = CGFloat()
#IBOutlet var tableView: UITableView!
// Table View here + basic configuration
override func viewDidLoad() {
super.viewDidLoad()
// dynamic cell height
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 200
loadPosts()
replyTxt.layer.cornerRadius = replyTxt.bounds.width / 50
replyTxt.backgroundColor = UIColor.clear
replyTxt.layer.borderColor = UIColor.gray.cgColor
replyTxt.layer.borderWidth = 1.0
let username = messages["sender"] as? String
self.navigationItem.title = username
}
// TABLEVIEW
// Number os cells
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return hhmessages.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let colorSmoothGray = UIColor(red: 229/255, green: 229/255, blue: 234/255, alpha: 1)
let colorBrandBlue = UIColor(red: 148 / 255, green: 33 / 255, blue: 147 / 255, alpha: 1)
let pictureURL = hhmessages[indexPath.row]["uploadpath"] as? String
// no picture in the post
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ConversationCell
cell.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
// shortcuts
let hhpost = hhmessages[indexPath.row]
let text = hhpost["messagetext"] as? String
cell.messageLbl.text = text
return cell
}
// func of loading posts from server
#objc func loadPosts() {
//isLoading = true
let me = user!["username"] as! String
let meid = user!["id"] as! String
print(meid)
print(me)
//print(username)
let uuid = messages["uuid"] as! String
print(uuid)
// accessing php file via url path
let url = URL(string: "http://localhost/message.php")!
// pass information to php file
let body = "username=\(me)&uuid=\(uuid)&recipient_id=\(meid)"
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = body.data(using: String.Encoding.utf8)
tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));
// launch session
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
// no error of accessing php file
// error occured
if error != nil {
Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
//self.isLoading = false
return
}
do {
// access data - safe mode
guard let data = data else {
Helper().showAlert(title: "Data Error", message: error!.localizedDescription, in: self)
//self.isLoading = false
return
}
// getting content of $returnArray variable of php file
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? NSDictionary
// accessing json data - safe mode
guard let posts = json?["messages"] as? [NSDictionary] else {
//self.isLoading = false
return
}
// assigning all successfully loaded posts to our Class Var - posts (after it got loaded successfully)
self.hhmessages = posts
self.tableView.reloadData()
// scroll to the latest index (latest cell -> bottom)
let indexPath = IndexPath(row: self.hhmessages.count - 1, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
// self.isLoading = false
} catch {
Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
//self.isLoading = false
return
}
}
}.resume()
}
// function sending requset to PHP to uplaod a file
func uploadPost() {
// validating vars before sending to the server
guard let user_id = user?["id"] as? String, let username = user?["username"] as? String, let avaPath = user?["ava"] else {
// converting url string to the valid URL
if let url = URL(string: user?["ava"] as! String) {
// downloading all data from the URL
guard let data = try? Data(contentsOf: url) else {
return
}
// converting donwloaded data to the image
guard let image = UIImage(data: data) else {
return
}
// assigning image to the global var
let currentUser_ava = image
}
return
}
let user_id_int = Int(user_id)!
let messagetext = replyTxt.text.trimmingCharacters(in: .whitespacesAndNewlines)
hhmessages.insert(messagetext as AnyObject, at: hhmessages.endIndex)
let indexPath = IndexPath(row: hhmessages.count - 1, section: 0)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));
tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
replyTxt.text = ""
textViewDidChange(replyTxt)
let recipient = messages["username"] as! String
let rid = String(describing: messages["recipient_id"]!)
let uuid = messages["uuid"] as! String
puuid = UUID().uuidString
// prepare request
let url = URL(string: "http://localhost/messagepost.php")!
let body = "sender_id=\(user_id)&sender=\(username)&text=\(messagetext)&recipient_id=\(rid)&recipient=\(recipient)&uuid=\(uuid)&puuid=\(puuid)"
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = body.data(using: .utf8)
// send request
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
// error happened
if error != nil {
Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
return
}
do {
// converting received data from the server into json format
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
// safe mode of casting json
guard let parsedJSON = json else {
return
}
// if the status of JSON is 200 - success
if parsedJSON["status"] as! String == "200" {
} else {
Helper().showAlert(title: "400", message: parsedJSON["status"] as! String, in: self)
return
}
// json error
} catch {
Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
return
}
}
}.resume()
}
#IBAction func replyBtn_clicked(_ sender: Any) {
if replyTxt.text.isEmpty == false && replyTxt.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false {
uploadPost()
//tableView.reloadData()
}
}
While appending a new message you are adding a String to the hhmessages array
let messagetext = replyTxt.text.trimmingCharacters(in: .whitespacesAndNewlines)
hhmessages.insert(messagetext as AnyObject, at: hhmessages.endIndex)
But in cellForRowAt method you are trying to get the String from hhmessages array using "messagetext" key
let pictureURL = hhmessages[indexPath.row]["uploadpath"] as? String
let hhpost = hhmessages[indexPath.row]
let text = hhpost["messagetext"] as? String
Change
hhmessages.insert(messagetext as AnyObject, at: hhmessages.endIndex)
to
hhmessages.insert(["messagetext": messagetext] as AnyObject, at: hhmessages.endIndex)
Instead of using array of AnyObject, use a struct
var hhmessages = AnyObject
struct Message {
var uploadpath: URL?
var messagetext: String?
}
var hhmessages = [Message]()
No cell of UITableView is displayed.
Probably the cause seems to be part of the setting of delegate and dataSource of UITableView, but I do not know the specific point.
So paste all the code.
If you do not understand the intention of the question, please do not hesitate to tell me.
I will tell you sincerity sincerity.
import UIKit
import Firebase
import FirebaseStorage
import FirebaseFirestore
import SDWebImage
struct CellData {
var date: Date
var time: String
var title: String
var name: String
var image: URL
}
struct TableSection<SectionItem: Comparable&Hashable, RowItem>: Comparable {
var sectionItem: SectionItem
var rowItems: [RowItem]
static func < (lhs: TableSection, rhs: TableSection) -> Bool {
return lhs.sectionItem > rhs.sectionItem
}
static func == (lhs: TableSection, rhs: TableSection) -> Bool {
return lhs.sectionItem == rhs.sectionItem
}
static func group(rowItems : [RowItem], by criteria : (RowItem) -> SectionItem ) -> [TableSection<SectionItem, RowItem>] {
let groups = Dictionary(grouping: rowItems, by: criteria)
return groups.map(TableSection.init(sectionItem:rowItems:)).sorted()
}
}
fileprivate func parseDate(_ str: String) -> Date {
let dateFormat = DateFormatter()
dateFormat.dateFormat = "yyyy年MM月dd日"
return dateFormat.date(from: str)!
}
fileprivate func firstDayOfMonth(date: Date) -> Date {
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day], from: date)
return calendar.date(from: components)!
}
class timelineViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
var arr = [CellData]()
let db = Firestore.firestore()
var sections = [TableSection<Date, CellData>]()
var teamIDFromFirebase: String = ""
var fireAuthUID = (Auth.auth().currentUser?.uid ?? "no data")
var dataImageFromFirestore = [Any]()
var dataTitleFromFireStore = [Any]()
var dataTimeFromFirestore = [Any]()
var dataNameFromFireStore = [Any]()
var dataDateFromFiewstore = [Any]()
var timelineDocumentIdArr = [Any]()
var draftDocumentIdArr = [Any]()
var submitDocumentIdArr = [Any]()
var selectedNum = 0
#IBOutlet weak var circleButton: UIButton!
#IBOutlet weak var userTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
circleButton = Circle()
if arr != nil {
self.arr = []
self.dataNameFromFireStore = [Any]()
self.dataTimeFromFirestore = [Any]()
self.dataTitleFromFireStore = [Any]()
self.dataImageFromFirestore = [Any]()
self.submitDocumentIdArr = [Any]()
self.selectedNum = 1
userTable.delegate = self
userTable.dataSource = self
userTable.register(UINib(nibName: "userTableViewCell", bundle: nil), forCellReuseIdentifier: "cellName")
self.db.collection("users").document(self.fireAuthUID).addSnapshotListener { (snapshot3, error) in
guard let document3 = snapshot3 else {
print("erorr2 \(String(describing: error))")
return
}
guard let data = document3.data() else { return }
self.teamIDFromFirebase = data["teamID"] as? String ?? ""
self.db.collection("diary").document(self.teamIDFromFirebase).collection("diaries").whereField("submit", isEqualTo: true).getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
return self.arr = [CellData(date: parseDate(""), time: "", title: "", name: "", image:URL(string: "")!)]
} else {
var i = 0
for document in querySnapshot!.documents {
self.timelineDocumentIdArr.append(document.documentID)
guard let documentData: [String: Any] = document.data() else { return }
self.dataTitleFromFireStore.append((documentData["今日のタイトル"] as? String)!)
self.dataTimeFromFirestore.append((documentData["time"] as? String)!)
self.dataNameFromFireStore.append((documentData["userName"] as? String)!)
self.dataImageFromFirestore.append((documentData["image"] as? String)!)
self.dataDateFromFiewstore.append((documentData["date"] as? String)!)
self.arr.append(CellData(date: parseDate(self.dataDateFromFiewstore[i] as! String), time: self.dataTimeFromFirestore[i] as? String ?? "", title: self.dataTitleFromFireStore[i] as? String ?? "", name: self.dataNameFromFireStore[i] as? String ?? "", image: URL(string: self.dataImageFromFirestore[i] as! String)!))
i += 1
}
self.userTable.reloadData()
}
}
}
}
self.sections = TableSection.group(rowItems: self.arr, by: { (headline) in
firstDayOfMonth(date: headline.date)
})
}
func numberOfSections(in tableView: UITableView) -> Int {
return self.sections.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let section = self.sections[section]
let date = section.sectionItem
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy年MM月dd日"
return dateFormatter.string(from: date)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let section = self.sections[section]
return section.rowItems.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = userTable.dequeueReusableCell(withIdentifier: "cellName", for: indexPath) as! userTableViewCell
let section = self.sections[indexPath.section]
let cellDetail = section.rowItems[indexPath.row]
cell.userTitle.text = cellDetail.title
cell.userName.text = cellDetail.name
cell.userTime.text = cellDetail.time
cell.userImage.sd_setImage(with: cellDetail.image)
return cell
}
}
You should assign the sections property inside the closure. This is corrected the viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
circleButton = Circle()
if arr != nil {
self.arr = []
self.dataNameFromFireStore = [Any]()
self.dataTimeFromFirestore = [Any]()
self.dataTitleFromFireStore = [Any]()
self.dataImageFromFirestore = [Any]()
self.submitDocumentIdArr = [Any]()
self.selectedNum = 1
userTable.delegate = self
userTable.dataSource = self
userTable.register(UINib(nibName: "userTableViewCell", bundle: nil), forCellReuseIdentifier: "cellName")
self.db.collection("users").document(self.fireAuthUID).addSnapshotListener { (snapshot3, error) in
guard let document3 = snapshot3 else {
print("erorr2 \(String(describing: error))")
return
}
guard let data = document3.data() else { return }
self.teamIDFromFirebase = data["teamID"] as? String ?? ""
self.db.collection("diary").document(self.teamIDFromFirebase).collection("diaries").whereField("submit", isEqualTo: true).getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
return self.arr = [CellData(date: parseDate(""), time: "", title: "", name: "", image:URL(string: "")!)]
} else {
var i = 0
for document in querySnapshot!.documents {
self.timelineDocumentIdArr.append(document.documentID)
guard let documentData: [String: Any] = document.data() else { return }
self.dataTitleFromFireStore.append((documentData["今日のタイトル"] as? String)!)
self.dataTimeFromFirestore.append((documentData["time"] as? String)!)
self.dataNameFromFireStore.append((documentData["userName"] as? String)!)
self.dataImageFromFirestore.append((documentData["image"] as? String)!)
self.dataDateFromFiewstore.append((documentData["date"] as? String)!)
self.arr.append(CellData(date: parseDate(self.dataDateFromFiewstore[i] as! String), time: self.dataTimeFromFirestore[i] as? String ?? "", title: self.dataTitleFromFireStore[i] as? String ?? "", name: self.dataNameFromFireStore[i] as? String ?? "", image: URL(string: self.dataImageFromFirestore[i] as! String)!))
i += 1
}
self.sections = TableSection.group(rowItems: self.arr, by: { (headline) in
firstDayOfMonth(date: headline.date)
})
self.userTable.reloadData()
}
}
}
}
}
I'm a newbie in SWIFT and I do some examples application.
The only thing that I can not get worked is to get my Image displayed on Detail Scene (DetailViewController).
On my MasterViewController file I have this to get my multiData file:
...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showData" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = self.multiData[indexPath.section][indexPath.row]
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// Here I get my multiData
func createData() {
var first: [Dictionary<String,String>] = []
var second: [Dictionary<String,String>] = []
dataSections = ["First Data", "Second Data"]
first.append(["name": "someName", "image": "somePngFile", "someData": "someText"])
second.append(["name": "someName", "image": "somePngFile", "someData": "someText"])
multiData = [first, second]
}
DetailViewController:
...
#IBOutlet weak var label: UILabel!
#IBOutlet weak var text: UITextView!
#IBOutlet weak var image: UIImageView!
...
func configureView() {
if let detail = self.detailItem {
if let labelTitle = label {
labelTitle.text = detail["name"] as! String!
}
if let textData = text {
textData.text = detail["someData"] as! String!
}
// This obvious doesn't work
if let imageFile = image {
imageFile.image = detail["image"] as! UIImage!
}
}
}
So, my question is how can I get the Image from detail["image"]?
I assume that the image contained in detail["image"] is in your application Bundle (i.e.: not an image from an HTTP URL). So, you should use the init(named:) constructor from UIImage to load your image. Something like that:
if let myImage = UIImage(named: detail["image"]) {
myImageView.image = myImage
}
Edit:
Here is, also, your code with a better management of optionals and casts in configureView:
func configureView() {
if let detail = self.detailItem {
if let labelTitle = detail["name"] as? String {
myLabel.text = labelTitle
}
if let textViewContent = detail["someData"] as? String {
myTextView.text = textViewContent
}
if let myImageName = detail["image"] as? String {
if let myImage = UIImage(named: myImageName) {
myImageView.image = myImage
}
}
}
}
class DropTvViewController: UIViewController , UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var dataTransfer = DataTransfer()
var responseString : String = ""
let storeData = StoreData()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
let pfod = PostForData()
pfod.forData
{ jsonString in
self.responseString = jsonString as String
var dict = self.dataTransfer.jsonToArray(self.responseString)!
if let x: AnyObject = dict.valueForKey("readlist")
{
println( dict.count )
println("X + \(x)")
for var i = 0 ; i < dict.count-1 ; i+=2
{
println("i : \(i)")
let y: AnyObject = x.objectAtIndex(i)
let z: AnyObject? = y.objectForKey("epipic")
let title : AnyObject? = y.objectForKey("epititle")
let time : AnyObject? = y.objectForKey("droptagcreatetime")
let pg : AnyObject? = y.objectForKey("pgname")
var imagessss = UIImage (data : pfod.forPicture())
self.storeData.add(title as! String, aFs: pg as! String, aTs: time as! String, ph: imagessss! , field1s: z as! String, field2s: z as! String, field3s: z as! String, field4s: z as! String )
// I do reload in here,but it will delay about ten seconds.
// I am sure the data is ready to read
self.tableView.reloadData()
}
}
}
}
You can use self.tableView.reloadData() which you are doing, but just in the wrong part of the loop. Just move it outside and you should be fine :)
If you're looking to reload a specific table cell then try: self.tableView.reloadRowsAtIndexPaths(paths, withRowAnimation: UITableViewRowAnimation.None)
Answer taken from here: https://stackoverflow.com/a/26709571/4891259