Search Bar Controller with Table view in swift - ios

I am new to Swift programming
SearchBar controller with tableview. I want display the multiple students in table view its working fine. I can add the search bar controller to table view and display the particular students data. table view cell contains the student information and image I want display particular student after search
this is the code
#IBOutlet var SearchBarDisp:UISearchBar!
override func viewDidLoad()
{
super.viewDidLoad()
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = false
tableView.tableHeaderView = searchController.searchBar
}
func updateSearchResults(for searchController: UISearchController) {
//todo
}
I can get student data from json
func getKids(url : String) {
UIApplication.shared.beginIgnoringInteractionEvents()
var errorCode = "1"
var msg = "Failed"
var request = URLRequest(url: URL(string: "getstaffstudents",
relativeTo: URL(string: serverURL+"/rkapi/api/"))!)
let session = URLSession.shared
request.httpMethod = "POST"
let bodyData = "staffId=\(staffId)"
request.httpBody = bodyData.data(using: String.Encoding.utf8);
let task = session.dataTask(with:request,completionHandler:{(d,response,error)in
do{
if let data = d {
if let jsonData = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {
errorCode = String(describing: jsonData["errorCode"]!)
msg = jsonData["msg"] as! String
print("msg values",msg)
if errorCode == "0" {
if let kid_list = jsonData["students"] as? NSArray {
for i in 0 ..< kid_list.count {
if let kid = kid_list[i] as? NSDictionary {
kidHoleData.removeAll()
let imageURL = url+"/images/" + String(describing: kid["photo"]!)
self.kidsData.append(Kids(
studentId: kid["studentId"] as? String,
name:kid["name"] as? String,
classId : kid["classId"] as? String,
standard: ((kid["standard"] as? String)! + " " + (kid["section"] as? String)!),
photo : (imageURL),
school: kid["schoolName"] as? String,
schoolId : "1",
url : url)
)
}
}
self.loopCount += 1
self.do_table_refresh()
}
} else {
self.displayAlert("Kids", message: msg)
}
} else {
self.displayAlert("Kids", message: "Data Not Available. Please try again")
}
}else {
self.displayAlert("Kids", message: "Please try again")
}
} catch let err as NSError {
print("JSON Error \(err)")
}
})
task.resume()
}
Table view
func numberOfSections(in tableView: UITableView) -> Int {
return (kidsData.count == 0) ? 0 : 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return kidsData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell =
tableView.dequeueReusableCell(
withIdentifier: "Kidscell", for: indexPath) as! KidsTableViewCell
let maskLayer = CAShapeLayer()
let bounds = cell.bounds
maskLayer.path = UIBezierPath(roundedRect: CGRect(x: 3, y: 3, width: bounds.width-15, height: bounds.height-15), cornerRadius: 2).cgPath
cell.layer.mask = maskLayer
let row = (indexPath as NSIndexPath).row
if(kidsData.count>0){
let kid = kidsData\[row\] as Kids
cell.kidNameLabel.text = kid.name
cell.classLabel.text = kid.standard
cell.kidNameLabel.lineBreakMode = .byWordWrapping
cell.kidNameLabel.numberOfLines = 0
cell.kidImageView.image = UIImage(named: "profile_pic")
cell.kidImageView.downloadImageFrom(link: kid.photo!, contentMode: UIViewContentMode.scaleAspectFit) //set your image from link array.
}
return cell
}
I want display particular student in table view(like if I can search student name as vani it's display the student vani in table view) pls help me

copy the hole data in to the attendanceInfoDupilicate
var attendanceInfoDupilicate = [AttendanceInfo]()
Inside of the Json service call at end
self.attendanceInfoDupilicate = self.attendanceInfo
updater the search controller
func updateSearchResults(for searchController: UISearchController)
{
let searchToSeatch = AttendanceSearchBarController.searchBar.text
if(searchToSeatch == "")
{
self.attendanceInfo = self.attendanceInfoDupilicate
}
else{
self.attendanceInfo.removeAll()
let AttedanceData = self.attendanceInfoDupilicate
var kidsArray = [String]()
for AttendanceInfo in AttedanceData
{
kidsArray.append(AttendanceInfo.name)
if(AttendanceInfo.name.range(of: searchToSeatch!, options: .caseInsensitive) != nil)
{
self.attendanceInfo.append(AttendanceInfo)
}
}
}
self.TableView.reloadData()
}

Related

Swift Firebase UITableViewCell loads before Data to populate cell is available

I am pushing data which is an array of strings to a tableview controller. These strings are "uid's" which are users in my database. With this array I make a call to firebase to extract all users and then do a match to the uid's. I am getting the correct data, yet I print out everything to make sure when the data is available and the data is available only after the tableview cell loads which causes the data to be nil causing a crash or just empty data. How can I make the data load first and then the cell so the data is available for display?
I've created functions for the data and now I have it in my viewDidLoad. Also, you'll see I have tried adding the firebase call into the Cell setup but of course that does not work.
Array of strings
var data = [String]()
viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
Database.database().reference().child("Businesses").observe(.value, with: { snapshot in
if snapshot.exists() {
self.businessUID = snapshot.value as? NSDictionary
if let dict = snapshot.value as? NSDictionary {
for item in dict {
let json = JSON(item.value)
let businessUid = json["uid"].stringValue
for uid in self.data {
if uid == businessUid {
let customerValue = self.businessUID?[uid]
self.businessDictionary = customerValue as! NSDictionary
print(self.businessDictionary)
print("Just printed the business dictionary")
}
}
}
}
} else {
print("does not exist")
}
})
}
Tableview Cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomerViewsSelectedBusinessesCell
print(self.businessDictionary)
print("Print the dictionary here to check the values")
let businessValues = self.businessDictionary
let uid = self.data.description
print(businessValues)
print("printed the business values")
if let dict = businessValues {
for item in dict {
let json = JSON(item.value)
let businessUid = json["uid"].stringValue
for uid in self.data {
if uid == businessUid {
let customerValue = self.businessUID?[uid]
self.businessData = customerValue as? NSDictionary
print(self.businessData)
print("Printing matching the uid values")
}
}
}
}
cell.businessName.text = businessData?["businessName"] as? String
cell.businessStreet.text = businessData?["businessStreet"] as? String
cell.businessCity.text = businessData?["businessCity"] as? String
cell.businessState.text = businessData?["businessState"] as? String
let businessProfilePicture = businessData?["profPicString"] as? String
if (businessProfilePicture!.characters.count) > 0 {
let url = URL(string: (businessProfilePicture!))
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
cell.profileImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.profileImage.image = image
}
}
} else {
let image = UIImage(named: "default")?.potter_circle
cell.profileImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.profileImage.image = image
}
return cell
}
Here is my solution. Got it to work. Appened and used "usersArray" to get and display the data.
var data = [String]()
var usersArray = [NSDictionary?]()
override func viewDidLoad() {
super.viewDidLoad()
Database.database().reference().child("Businesses").observe(.value, with: { snapshot in
if snapshot.exists() {
self.businessUID = snapshot.value as? NSDictionary
if let dict = snapshot.value as? NSDictionary {
for item in dict {
let json = JSON(item.value)
let businessUid = json["uid"].stringValue
for uid in self.data {
if uid == businessUid {
let customerValue = self.businessUID?[uid]
self.usersArray.append(customerValue as! NSDictionary)
self.followUsersTableView.reloadData()
}
}
}
}
} else {
print("does not exist")
}
})
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.usersArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomerViewsSelectedBusinessesCell
let user : NSDictionary?
user = self.usersArray[indexPath.row]
cell.businessName.text = String(user?["businessName"] as! String)
cell.businessStreet.text = String(user?["businessStreet"] as! String)
cell.businessCity.text = String(user?["businessCity"] as! String)
cell.businessState.text = String(user?["businessState"] as! String)
let businessProfilePicture = String(user?["profPicString"] as! String)
if (businessProfilePicture.characters.count) > 0 {
let url = URL(string: (businessProfilePicture))
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
cell.profileImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.profileImage.image = image
}
}
} else {
let image = UIImage(named: "default")?.potter_circle
cell.profileImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.profileImage.image = image
}
return cell
}

Swift4: Want to use the variable of UIViewController with UIButton custom class

Currently, I am applying custom class SAFavoriteBtn to UIButton.
I wrote the code to get the API when the button was pressed within that class, I assigned the parameters to get the API data to the variables of UIViewController, I want to use the variable in SAFavoriteBtn. In this case, how should pass the value?
And this pattern is using segue?
UIViewController
class StoreViewController: UIViewController,UICollectionViewDataSource,UICollectionViewDelegate, UICollectionViewDelegateFlowLayout,UITableViewDelegate, UITableViewDataSource {
var store_id = ""
var instaId = ""
var store = [Store]()
var photoPath = [Store.photos]()
var tag = [Store.tags]()
var selectedImage : UIImage?
let defaultValues = UserDefaults.standard
#IBOutlet weak var imageCollectionView: UICollectionView!
#IBOutlet weak var mainImage: UIImageView!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var locationLabel: UILabel!
#IBOutlet weak var UIView: UIView!
#IBOutlet weak var tagCollectionView: UICollectionView!
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//Collectiopn DetaSources
imageCollectionView.dataSource = self
imageCollectionView.delegate = self
tagCollectionView.dataSource = self
tagCollectionView.delegate = self
tableView.dataSource = self
tableView.delegate = self
//Navigation Color
self.navigationController!.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController!.navigationBar.shadowImage = UIImage()
navigationController!.navigationBar.topItem!.title = ""
navigationController!.navigationBar.tintColor = UIColor.white
//UIView Shadow
let shadowPath = UIBezierPath(rect: UIView.bounds)
UIView.layer.masksToBounds = false
UIView.layer.shadowColor = UIColor.black.cgColor
UIView.layer.shadowOffset = .zero
UIView.layer.shadowOpacity = 0.2
UIView.layer.shadowPath = shadowPath.cgPath
//Request API
let url = URL(string: "http://example.com/store/api?store_id=" + store_id)
let request = URLRequest(url: url!)
let session = URLSession.shared
let encoder: JSONEncoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
encoder.outputFormatting = .prettyPrinted
session.dataTask(with: request){(data, response, error)in if error == nil,
let data = data,
let response = response as? HTTPURLResponse{
let decoder: JSONDecoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
do {
let json = try decoder.decode(Store.self, from: data)
self.store = [json]
self.photoPath = json.photos
self.tag = json.tags
if let imageURL = URL(string: "http://example.com/photos/" + json.photos[0].path){
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
self.mainImage.image = image
}
}
}
}else if let imageURL = URL(string: "http://example.com/photos/" + json.photos[0].path.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!){
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
self.mainImage.image = image
}
}
}
}
DispatchQueue.main.async {
self.nameLabel.text = json.name
self.locationLabel.text = json.location
self.tableView.reloadData()
self.imageCollectionView.reloadData()
self.tagCollectionView.reloadData()
}
} catch {
print("error:", error.localizedDescription)
}
}
}.resume()
print(store)
//print(defaultValues.string(forKey: "id"))
// Image Collection view Layout
let itemSize = UIScreen.main.bounds.width/3.62 - 3.62
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0)
layout.itemSize = CGSize(width: itemSize, height: itemSize)
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
imageCollectionView.collectionViewLayout = layout
// Tag Collection View
let tagLayout = UICollectionViewFlowLayout()
tagLayout.minimumLineSpacing = 1
tagLayout.minimumInteritemSpacing = 1
tagLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0)
tagLayout.itemSize = CGSize(width: 80, height: 24)
tagCollectionView.collectionViewLayout = tagLayout
//status bar color
self.setNeedsStatusBarAppearanceUpdate()
}
override var prefersStatusBarHidden: Bool {
return false
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return UIStatusBarStyle.lightContent
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// UI coner redius
let uiViewPath = UIBezierPath(roundedRect: UIView.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 8, height: 8))
let uiViewMask = CAShapeLayer()
uiViewMask.path = uiViewPath.cgPath
UIView.layer.mask = uiViewMask
navigationController!.navigationBar.topItem!.title = " "
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//Collection
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == self.imageCollectionView{
let imageCell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell",for: indexPath)
let imageView = imageCell.contentView.viewWithTag(1) as! UIImageView
let textLabel = imageCell.contentView.viewWithTag(2) as! UILabel
let instaBtn = imageCell.contentView.viewWithTag(3) as! UIButton
instaBtn.tag = indexPath.row
if photoPath.count > indexPath.row{
if collectionView == self.imageCollectionView{
let url : String = "http://example.com/photos/" + photoPath[indexPath.row].path
let imageURL = URL(string: url)
print(url)
if imageURL != nil {
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL!)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
imageCell.layer.masksToBounds = true;
imageCell.layer.cornerRadius = 3
imageView.image = image
textLabel.text = self.photoPath[indexPath.row].username
print(self.photoPath[indexPath.row].username)
}
}
}
}else{
let encodeURL : String = "http://example.com/photos/" + photoPath[indexPath.row].path
let url = URL(string: encodeURL.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!)
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
imageCell.layer.masksToBounds = true;
imageCell.layer.cornerRadius = 3
imageView.image = image
textLabel.text = self.photoPath[indexPath.row].username
print(self.photoPath[indexPath.row].username)
}
}
}
}
}
}
instaBtn.addTarget(self, action: #selector(self.instaBtnTapped), for: UIControlEvents.touchUpInside)
imageCell.addSubview(instaBtn)
return imageCell
//Tag collection view
}else if collectionView == self.tagCollectionView{
let tagCell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "TagCell",for: indexPath)
let tagLabel = tagCell.contentView.viewWithTag(2) as! UILabel
if tag.count > indexPath.row{
tagLabel.text = tag[indexPath.row].name
}
tagCell.layer.cornerRadius = 12
return tagCell
}else{
return UICollectionViewCell()
}
}
//tapped instaBtn jump insta user page function
#objc func instaBtnTapped(sender: UIButton){
instaId = photoPath[sender.tag].username
let url = URL(string: "https://www.instagram.com/"+instaId+"/")
UIApplication.shared.open(url!, options: [ : ], completionHandler: nil)
print (sender.tag)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return photoPath.count > 0 ? 3 : 0
}
func tagcollectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tag.count > 0 ? tag.count : 0
}
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return store.count > 0 ? 1 : 0
case 1 :
return store.count > 0 ? 1 : 0
case 2 :
return store.count > 0 ? 1 : 0
default:
return 0
}
}
//Collection view tap
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == self.imageCollectionView{
let url : String = "http://example.com/photos/" + photoPath[indexPath.row].path
let imageURL = URL(string: url)
print(url)
if imageURL != nil {
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL!)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
self.mainImage.image = image
}
}
}
}else{
let encodeURL : String = "http://example.com/photos/" + photoPath[indexPath.row].path
let url = URL(string: encodeURL.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!)
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
self.mainImage.image = image
}
}
}
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
switch indexPath.section {
case 0 :
//Price Cell
guard let priceCell = tableView.dequeueReusableCell(withIdentifier: "priceCell", for: indexPath) as? priceTableViewCell else { return UITableViewCell()}
if let price:String = store[indexPath.row].price{
priceCell.priceLabel.text! = price
}else{
priceCell.priceLabel.text! = "-"
}
return priceCell
case 1 :
//timeCell
guard let timeCell = tableView.dequeueReusableCell(withIdentifier: "timeCell", for: indexPath) as? timeTableViewCell else{return UITableViewCell()}
if let time:String = store[indexPath.row].open_time{
timeCell.timeLabel.text! = time
}else{
timeCell.timeLabel.text! = "-"
}
return timeCell
case 2 :
//closedayCell
guard let closedayCell = tableView.dequeueReusableCell(withIdentifier: "closedayCell", for: indexPath) as? closedayTableViewCell else { return UITableViewCell() }
if let closeday:String = store[indexPath.row].closed_day{
closedayCell.closedayLabel.text! = closeday
}else{
closedayCell.closedayLabel.text! = "-"
}
return closedayCell
default :
print("Default Selected")
}
return cell
}
#IBAction func moreImageBtn(_ sender: Any) {
let store_id = self.store_id
self.performSegue(withIdentifier: "toStorePhotoViewController", sender: store_id)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toStorePhotoViewController"{
let storePhotoViewController = segue.destination as! StorePhotoViewController
storePhotoViewController.store_id = sender as! String
}
}
//This is SAFavoriteBtn
//Bookmark Button
#IBAction func bookmarkBtn(_ sender: SAFavoriteBtn) {
}
#IBAction func locationBtn(_ sender: Any) {
let lat = store[0].lat
let lng = store[0].lng
if UIApplication.shared.canOpenURL(URL(string:"comgooglemaps://")!){
let urlStr : String = "comgooglemaps://?daddr=\(lat),\(lng)&directionsmode=walking&zoom=14"
UIApplication.shared.open(URL(string:urlStr)!,options: [:], completionHandler: nil)
}else{
let daddr = String(format: "%f,%f", lat, lng)
let urlString = "http://maps.apple.com/?daddr=\(daddr)&dirflg=w"
let encodeUrl = urlString.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)!
let url = URL(string: encodeUrl)!
UIApplication.shared.open(url,options: [:], completionHandler: nil)
}
}
}
SAFavoriteBtn
import UIKit
class SAFavoriteBtn: UIButton {
var isOn = false
let defaultValues = UserDefaults.standard
//Want to use the variable of UIViewController with UIButton custom class in this part
var storeId = ""
override init(frame: CGRect) {
super.init(frame:frame)
initButton()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initButton()
}
func initButton() {
setImage(UIImage(named:"bookmark.png"), for: UIControlState.normal)
addTarget(self, action: #selector(SAFavoriteBtn.buttonPressed), for: .touchUpInside)
}
#objc func buttonPressed() {
activateBtn(bool: !isOn)
}
func activateBtn(bool : Bool){
isOn = bool
//UI
let image = bool ? "bookmark_after.png" : "bookmark.png"
setImage(UIImage(named: image), for: UIControlState.normal)
//API
bool ? favorite() : deleteFavorite()
}
func favorite(){
let user_id = defaultValues.string(forKey: "userId")
let url = URL(string: "http://example.com/api/store/favorite?")
var request = URLRequest(url: url!)
request.httpMethod = "POST"
let postParameters = "user_id=" + user_id! + "&store_id=" + storeId
request.httpBody = postParameters.data(using: .utf8)
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if error == nil, let data = data, let response = response as? HTTPURLResponse {
print("Content-Type: \(response.allHeaderFields["Content-Type"] ?? "")")
print("statusCode: \(response.statusCode)")
print(String(data: data, encoding: .utf8) ?? "")
}
}.resume()
print("favorite")
}
func deleteFavorite(){
let user_id = defaultValues.string(forKey: "userId")
let url = URL(string: "http://example.com/api/store/favorite?")
var request = URLRequest(url: url!)
request.httpMethod = "POST"
let postParameters = "user_id=" + user_id! + "&store_id=" + storeId
request.httpBody = postParameters.data(using: .utf8)
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if error == nil, let data = data, let response = response as? HTTPURLResponse {
print("Content-Type: \(response.allHeaderFields["Content-Type"] ?? "")")
print("statusCode: \(response.statusCode)")
print(String(data: data, encoding: .utf8) ?? "")
}
}.resume()
print("delete")
}
}

TableView doesnot show the data?

My tableView does not show the data. I am fetching the data through api and save it into separate class with initializers. But it does not the show on the tableView. How to resolve this issue. I am new to iOS. I know there is only one line of code problem somewhere.
I call api in viewDidLoad method.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
//fetch all expected visitor data
self.apiExpectedVisitor(strURL: urlViewExpectedVisitors)
self.expectedTableView.reloadData()
}
Function of API Method
func apiExpectedVisitor(strURL: String)
{
fetchedExpectedData = []
//URL
let myURL = URL(string: strURL)
//URL Request
let request = NSMutableURLRequest(url: myURL!)
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Accept")
let token = "Bearer " + strToken
request.addValue(token, forHTTPHeaderField: "Authorization")
let postTask = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
print(response!)
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: [Any]] {
print("POST Method :\(json)")
DispatchQueue.main.async {
for expectedVisitors in json["expected_visitors"]!
{
let eachData = expectedVisitors as! [String: Any]
let id = eachData["id"] as! Int
let name = "\(String(describing: eachData["name"]))"
let email = "\(String(describing: eachData["email"]))"
let phone = eachData["phone"] as! String
let verification_code = "\(String(describing: eachData["expected_visitor_verification_code"]))"
let qr_code = eachData["expected_visitor_qr_code"] as? String
let isVisited = eachData["is_visited"] as! Int
let company_id = eachData["company_id"] as! Int
let purpose = "\(String(describing: eachData["purpose"]))"
let meeting_date = eachData["meeting_date"] as! String
let meeting_time = eachData["meeting_time"] as! String
let created_at = eachData["created_at"] as! String
let updated_at = eachData["updated_at"] as! String
//Date.formatter(createdDate: createdDate)
if let department_id = eachData["department_id"] as? Int, let employee_id = eachData["employee_id"] as? Int, let location_id = eachData["location_id"] as? Int, let image = eachData["image"] as? String, let duration = eachData["duration"] as? String {
fetchedExpectedData.append(FetchedAllExpectedVisitors.init(id: id, name: name, email: email, phone: phone, department_id: department_id, employee_id: employee_id, location_id: location_id, image: image, verification_code: verification_code, qr_code: qr_code!, isVisited: isVisited, company_id: company_id, purpose: purpose, meeting_date: meeting_date, meeting_time: meeting_time, duration: duration, created_at: created_at, updated_at: updated_at))
self.expectedTableView.reloadData()
}
}
}
}
} catch let error {
print(error.localizedDescription)
}
}
postTask.resume()
}
TableView DataSource and Delegate Methods
func numberOfSections(in tableView: UITableView) -> Int {
return fetchedExpectedData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ShowExpectedCell", for: indexPath) as! ShowExpectedTVCell
cell.lblDate.text = fetchedExpectedData[indexPath.section].created_at
cell.lblVisName.text = fetchedExpectedData[indexPath.section].name
print(fetchedExpectedData[indexPath.section].name)
for i in 0..<fetchedDepttData.count {
let department_id = fetchedDepttData[i].depttID
if fetchedExpectedData[indexPath.section].department_id == department_id
{
cell.lblDeptt.text = fetchedDepttData[i].depttName
}
}
for i in 0..<fetchedEmployeeData.count {
let employee_id = fetchedEmployeeData[i].empID
if fetchedExpectedData[indexPath.section].employee_id == employee_id
{
cell.lblEmpName.text = fetchedEmployeeData[i].name
}
}
return cell
}
Check below points:-
Make sure you registered tableview cell nib and added dataSource and Delegate.
You are reloading tableview after your fetchedExpectedData array filled
Just add the below code in viewDidLoad
expectedTableView.delegate = self
expectedTableView.datasource = self
also check if you have set UITableViewDelegate , UITableViewDataSource in starting of the controller
class Yourviewcontrollername: UIViewController,UITableViewDelegate,UITableViewDataSource
{
//Rest of the code
}
Also put breakpoint in all delegate methods and see if anything hits.

How to display JSON file in sections and rows in TableView in Swift

I am new to Xcode and Swift. I need help displaying a data from JSON file into TableView with sections and rows. I need to display different restaurants in each neighborhood. I think I need to make changes in my JSON file but I can't figure it out. I really will appreciate any help. Cheers.
This is my JSON file:
{
"hoods": {
"neighborhoodNames": {
"marina":[
{
"name": "MARINA-1",
"dob": "December 18, 1963",
"image": "http://microblogging.wingnity.com/JSONParsingTutorial/brad.jpg"
},
{
"name": "MARINA-2",
"description": "Tom Cruise, is an American film actor and producer. He has been nominated for three Academy Awards and has won three Golden Globe Awards. He started his career at age 19 in the 1981 film Endless Love.",
"dob": "July 3, 1962",
"image": "http://microblogging.wingnity.com/JSONParsingTutorial/cruise.jpg"
},
{
"name": "MARINA-3",
"description": "John Christopher 'Johnny' Depp II is an American actor, film producer, and musician. He has won the Golden Globe Award and Screen Actors Guild award for Best Actor.",
"dob": "June 9, 1963",
"image": "http://microblogging.wingnity.com/JSONParsingTutorial/johnny.jpg"
}
],
"MISSION":[
{
"name": "MISSION-1",
"dob": "December 18, 1963",
"image": "http://microblogging.wingnity.com/JSONParsingTutorial/brad.jpg"
},
{
"name": "MISSION-2",
"dob": "July 3, 1962",
"image": "http://microblogging.wingnity.com/JSONParsingTutorial/cruise.jpg"
},
{
"name": "MISSION-3",
"dob": "June 9, 1963",
"image": "http://microblogging.wingnity.com/JSONParsingTutorial/johnny.jpg"
},
{
"name": "MISSION-4",
"dob": "June 9, 1963",
"image": "http://microblogging.wingnity.com/JSONParsingTutorial/johnny.jpg"
}
]}
}
}
This is a link to the JSON file: http://barhoppersf.com/json/hoods.json
This my Xcode:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let urlString = "http://barhoppersf.com/json/hoods.json"
#IBOutlet weak var tableView: UITableView!
var nameArray:[[String]] = []
var dobArray:[[String]] = []
var imgURLArray:[[String]] = []
var neighborhoodNames = [String]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
self.downloadJsonWithURL()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func downloadJsonWithURL() {
let url = NSURL(string: urlString)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
if let actorArray = jsonObj!.value(forKey: "hoods") as? NSArray {
for actor in actorArray{
if let actorDict = actor as? NSDictionary {
if let name = actorDict.value(forKey: "neighborhoodNames") {
self.neighborhoodNames.append(name as! String)
}
if let name = actorDict.value(forKey: "name") {
self.nameArray.append([name as! String])
}
if let name = actorDict.value(forKey: "dob") {
self.dobArray.append([name as! String])
}
if let name = actorDict.value(forKey: "image") {
self.imgURLArray.append([name as! String])
}
}
}
}
// self.nameArray = self.nameArray.sorted()
OperationQueue.main.addOperation({
self.tableView.reloadData()
})
}
}).resume()
}
func downloadJsonWithTask() {
let url = NSURL(string: urlString)
var downloadTask = URLRequest(url: (url as URL?)!, cachePolicy: URLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 15)
downloadTask.httpMethod = "GET"
URLSession.shared.dataTask(with: downloadTask, completionHandler: {(data, response, error) -> Void in
let jsonData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments)
print(jsonData as Any)
}).resume()
}
// MARK: - changing the color, background and position of the header
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = UIColor.self.init(red: 254/255, green: 170/255, blue: 25/255, alpha: 1.0)
let headerLabel = UILabel(frame: CGRect(x: 8, y: 5, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
headerLabel.font = UIFont(name: "Trebuchet MS", size: 15)
headerLabel.textColor = UIColor.darkGray
headerLabel.text = self.tableView(self.tableView, titleForHeaderInSection: section)
headerLabel.sizeToFit()
headerView.addSubview(headerLabel)
return headerView
}
// MARK: - changing the size of the header cell
// func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
// return 40
// }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (nameArray[section].count)
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return neighborhoodNames[section]
}
func numberOfSections(in tableView: UITableView) -> Int {
return neighborhoodNames.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
// cell.nameLabel.text = nameArray[indexPath.row]
cell.nameLabel?.text = nameArray[indexPath.section][indexPath.row]
return cell
}
// set up A_Z index
// func sectionIndexTitles(for tableView: UITableView) -> [String]? {
// return indexName
// }
// call correct section when index is tapped
func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
guard let index = indexName.index(of: title) else {
return -1
}
return index
}
///for showing next detailed screen with the downloaded info
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
vc.imageString = imgURLArray[indexPath.section][indexPath.row]
vc.nameString = nameArray[indexPath.section][indexPath.row]
vc.dobString = dobArray[indexPath.section][indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
}
}
Thanks a lot in advance!!!
Dian.
Your JSON above and the JSON from that URL are different, so what I have here can work for both.
import UIKit
struct Actor {
var children: String
var country: String
var description: String
var dob: String
var height: String
var image: String
var name: String
var spouse: String
init?(dict:Dictionary<String,String>) {
guard
let children = dict["children"],
let country = dict["country"],
let description = dict["description"],
let dob = dict["dob"],
let height = dict["height"],
let image = dict["image"],
let name = dict["name"],
let spouse = dict["spouse"]
else {
return nil
}
self.children = children
self.country = country
self.description = description
self.dob = dob
self.height = height
self.image = image
self.name = name
self.spouse = spouse
}
}
struct Restaurant {
var name: String
var dob: String
var image: String
init?(dict:Dictionary<String,String>) {
guard
let name = dict["name"],
let dob = dict["dob"],
let image = dict["image"]
else {
return nil
}
self.name = name
self.dob = dob
self.image = image
}
}
struct NeighborhoodActors {
var name: String
var actors: Array<Actor>
init(name:String, data:Array<Dictionary<String,String>>) {
self.name = name
self.actors = Array<Actor>()
for dict in data {
if let actor = Actor(dict: dict) {
self.actors.append(actor)
}
}
}
}
struct NeighborhoodRestaurants {
var name: String
var restaurants: Array<Restaurant>
init(name:String, data:Array<Dictionary<String,String>>) {
self.name = name
self.restaurants = Array<Restaurant>()
for dict in data {
if let restaurant = Restaurant(dict: dict) {
self.restaurants.append(restaurant)
}
}
}
}
class ViewController: UITableViewController {
let urlString = "http://barhoppersf.com/json/hoods.json"
var tableData = Array<NeighborhoodRestaurants>()
override func viewDidLoad() {
super.viewDidLoad()
self.downloadJsonWithURL() // This loads tableview with data from url
load(file: "document") // This loads tableview with the json in your question, which I put in a json file to test
}
func load(file:String) {
guard let path = Bundle.main.path(forResource: file, ofType: "json") else { return }
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else { return }
guard let json = try? JSONSerialization.jsonObject(with: data) else { return }
guard let dict = json as? Dictionary<String,Dictionary<String,Dictionary<String,Array<Dictionary<String,String>>>>> else { return }
guard let hoods = dict["hoods"] else { return }
guard let names = hoods["neighborhoodNames"] else { return }
for (key, value) in names {
let neighborhood = NeighborhoodRestaurants(name: key, data: value)
self.tableData.append(neighborhood)
}
self.tableData.sort { $0.name > $1.name } // This will arrange the restaurants alphabetically
self.tableView.reloadData()
}
func downloadJsonWithURL() {
let url = NSURL(string: urlString)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let error = error {
print(error.localizedDescription)
return
}
if let data = data {
guard let json = try? JSONSerialization.jsonObject(with: data) else { return }
guard let dict = json as? Dictionary<String,Dictionary<String,Dictionary<String,Array<Dictionary<String,String>>>>> else { return }
guard let hoods = dict["hoods"] else { return }
guard let names = hoods["neighborhoodNames"] else { return }
for (key, value) in names {
let neighborhood = NeighborhoodActors(name: key, data: value)
// self.tableData.append(neighborhood)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}).resume()
}
// MARK: - changing the color, background and position of the header
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = UIColor.self.init(red: 254/255, green: 170/255, blue: 25/255, alpha: 1.0)
let headerLabel = UILabel(frame: CGRect(x: 8, y: 5, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
headerLabel.font = UIFont(name: "Trebuchet MS", size: 15)
headerLabel.textColor = UIColor.darkGray
headerLabel.text = self.tableView(self.tableView, titleForHeaderInSection: section)
headerLabel.sizeToFit()
headerView.addSubview(headerLabel)
return headerView
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData[section].restaurants.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.tableData[section].name
}
override func numberOfSections(in tableView: UITableView) -> Int {
return self.tableData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = self.tableData[indexPath.section].restaurants[indexPath.row].name
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
vc.restaurant = self.tableData[indexPath.section].restaurants[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
}
}
class DetailViewController: UIViewController {
#IBOutlet var imageView: UIImageView!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var dobLabel: UILabel!
var restaurant: Restaurant!
override func viewDidLoad() {
super.viewDidLoad()
self.nameLabel.text = self.restaurant.name
self.dobLabel.text = self.restaurant.dob
if let url = URL(string: self.restaurant.image) {
let task = URLSession.shared.dataTask(with: url) { data, resonse, error in
if let error = error {
print(error.localizedDescription)
return
}
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
self.imageView.image = image
}
}
}
task.resume()
}
}
}
This is how to open a URL, open apple maps, and ring a phone number.
func telephone(phoneNumber:String) {
let application = UIApplication.shared
if application.openURL(URL(string: "tel://\(phoneNumber)")!) {
print("Ringing")
} else {
print("Something has gone wrong.")
}
}
func directions(address:String) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { (placemarks, error) in
if let description = error?.localizedDescription {
print(description)
return
}
if let placemark = placemarks?.first {
let pin = MKPlacemark(placemark: placemark)
let item = MKMapItem(placemark: pin)
let region = MKCoordinateRegionMakeWithDistance(pin.coordinate, 1000, 1000)
let options: Dictionary<String,Any> = {
var dict = Dictionary<String,Any>()
dict[MKLaunchOptionsMapCenterKey] = NSValue(mkCoordinate: region.center)
dict[MKLaunchOptionsMapSpanKey] = NSValue(mkCoordinateSpan: region.span)
return dict
}()
item.openInMaps(launchOptions: options)
return
}
print("An unknown error has occured.")
}
}
func website(url:String) {
if let url = URL(string: url) {
let application = UIApplication.shared
application.openURL(url)
return
}
print("The URL is invalid.")
}

App crash on iPhone 6, but work on iPhone 6 simulator

I don't understand why my application works well on the Simulator but instead when I run on iPhone crashes. What can be?
import UIKit
import CoreData
class HomeTableViewController: UITableViewController{
var arrayEntity : [Questions] = []
override func viewDidLoad(){
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
if (CoreDataController.shared.checkIfIsEmpty() == true) { getJSON() }
else { arrayEntity = CoreDataController.shared.loadQuestion()!
//reload della tableview quando l'array si modifica
self.tableView.reloadData()
}
}
struct ProvaREST{
var userId: Int = 0
var id: Int = 0
var title: String = ""
var body: String = ""
static func parsereviewJSONData(data: Data) -> [ProvaREST] {
var provaREST = [ProvaREST]()
do {
let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
// Parse JSON data
if let reviews = jsonResult as? [Dictionary<String, Any>] {
for review in reviews {
var newReview = ProvaREST()
newReview.userId = review["userId"] as! Int
newReview.id = review["id"] as! Int
newReview.title = review["title"] as! String
newReview.body = review["body"] as! String
provaREST.append(newReview)
}
}
} catch let err {
print(err)
}
return provaREST
}
}
func getJSON(){
var reviews = [ProvaREST]()
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
guard let URL = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return }
var request = URLRequest(url: URL)
request.httpMethod = "GET"
let task = session.dataTask(with: request, completionHandler: {(data, response, error) in
if (error == nil) {
// Parse JSON Data
if let data = data {
reviews = ProvaREST.parsereviewJSONData(data: data)
//Core data saving
for i in 0 ..< reviews.count{
CoreDataController.shared.addQuestion(userID: reviews[i].userId, id: reviews[i].id, title: reviews[i].title, body: reviews[i].body)
}
//quando finisco di aggiungere, tengo in memoria (per zone fuori copertura) ed estraggo i dati per la tableview
self.arrayEntity = CoreDataController.shared.loadQuestion()!
self.tableView.reloadData()
}
} else {
// Failure connection
print("Nessuna connessione")
}
})
task.resume()
session.finishTasksAndInvalidate()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayEntity.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = arrayEntity[indexPath.row].body
cell.detailTextLabel?.text = String(arrayEntity[indexPath.row].id)
return cell
}
}
and
import Foundation
import UIKit
import CoreData
class CoreDataController {
static let shared = CoreDataController()
private var context: NSManagedObjectContext
private init() {
let application = UIApplication.shared.delegate as! AppDelegate
self.context = application.persistentContainer.viewContext
}
func addQuestion(userID: Int, id: Int, title: String, body: String) {
let entity = NSEntityDescription.entity(forEntityName: "Questions", in: self.context)
let newQuestion = Questions(entity: entity!, insertInto: self.context)
newQuestion.userid = Int32(userID)
newQuestion.id = Int32(id)
newQuestion.title = title
newQuestion.body = body
do {
try self.context.save()
} catch{
print("Errore")
}
}
func loadQuestion() -> [Questions]? {
print("Recupero libri:")
let fetchRequest: NSFetchRequest<Questions> = Questions.fetchRequest()
do {
let array = try self.context.fetch(fetchRequest) as [Questions]
guard array.count > 0 else {print("[EHY!] Non ci sono elementi da leggere "); return array}
return array
}catch let err{
print(err)
return nil
}
}
func checkIfIsEmpty() -> Bool{
let fetchRequest: NSFetchRequest<Questions> = Questions.fetchRequest()
do {
let array = try self.context.fetch(fetchRequest)
guard array.count > 0 else { return true }
return false
}catch{
print("Errore nella fetchRequest")
return false
}
}
}
The coredatacontroller class is the class that handles database operationsThe coredatacontroller class is the class that handles database operationsThe coredatacontroller class is the class that handles database operations

Resources