I am building my app in Swift 3 with Alamofire. I have JSON data coming into a list view. Every time I pull to refresh the content, instead of refreshing the content, it just adds more items to the bottom of the list in list view, instead of refreshing the visible list. I don't know what I could be doing wrong, my code so far is:
import UIKit
import Alamofire
import SVProgressHUD
struct postinput {
let mainImage : UIImage!
let name : String!
let author : String!
let summary : String!
let content : String!
}
class TableViewController: UITableViewController {
//var activityIndicatorView: UIActivityIndicatorView!
var postsinput = [postinput]()
var refresh = UIRefreshControl()
var mainURL = "https://www.example.com/api"
typealias JSONstandard = [String : AnyObject]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.separatorStyle = UITableViewCellSeparatorStyle.none
self.tableView.addSubview(refresh)
//;refresh.attributedTitle = NSAttributedString(string: "Refreshing...", attributes:[NSForegroundColorAttributeName : UIColor.black])
refresh.backgroundColor = UIColor(red:0.93, green:0.93, blue:0.93, alpha:1.0)
//refresh.tintColor = UIColor.white
refresh.addTarget(self, action: #selector(self.refreshData), for: UIControlEvents.valueChanged)
//refresh.addTarget(self, action: #selector(getter: TableViewController.refresh), for: UIControlEvents.valueChanged)
refresh.attributedTitle = NSAttributedString(string: "Updated: \(NSDate())")
//activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
//tableView.backgroundView = activityIndicatorView
callAlamo(url: mainURL)
}
func refreshData() {
Alamofire.request("https://www.example.com/api").responseJSON(completionHandler: {
response in
self.parseData(JSONData: response.data!)
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.singleLine
DispatchQueue.main.async {
self.tableView.reloadData()
self.refresh.endRefreshing()
}
})
}
func callAlamo(url : String){
//activityIndicatorView.startAnimating()
SVProgressHUD.show(withStatus: "Loading...")
SVProgressHUD.setDefaultStyle(SVProgressHUDStyle.dark)
SVProgressHUD.setDefaultAnimationType(SVProgressHUDAnimationType.native)
SVProgressHUD.setDefaultMaskType(SVProgressHUDMaskType.black)
Alamofire.request(url).responseJSON(completionHandler: {
response in
self.parseData(JSONData: response.data!)
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.singleLine
//self.activityIndicatorView.stopAnimating()
SVProgressHUD.dismiss()
})
}
func parseData(JSONData : Data) {
do {
var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONstandard
// print(readableJSON)
if let posts = readableJSON["posts"] as? [JSONstandard] {
for post in posts {
let title = post["title"] as! String
let author = post["author"] as! String
guard let dic = post["summary"] as? [String: Any], let summary = dic["value"] as? String else {
return
}
let str = summary.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)
print(str)
guard let dic1 = post["content"] as? [String: Any], let content = dic1["value"] as? String else {
return
}
let str1 = content.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)
print(str1)
//print(author)
if let imageUrl = post["image"] as? String {
let mainImageURL = URL(string: imageUrl )
let mainImageData = NSData(contentsOf: mainImageURL!)
let mainImage = UIImage(data: mainImageData as! Data)
postsinput.append(postinput.init(mainImage: mainImage, name: title, author: author, summary: summary, content: content))
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
catch {
print(error)
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return postsinput.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
// cell?.textLabel?.text = titles[indexPath.row]
let mainImageView = cell?.viewWithTag(2) as! UIImageView
mainImageView.image = postsinput[indexPath.row].mainImage
mainImageView.layer.cornerRadius = 5.0
mainImageView.clipsToBounds = true
//(cell?.viewWithTag(2) as! UIImageView).image = postsinput[indexPath.row].mainImage
let mainLabel = cell?.viewWithTag(1) as! UILabel
mainLabel.text = postsinput[indexPath.row].name
mainLabel.font = UIFont.boldSystemFont(ofSize: 18)
mainLabel.sizeToFit()
mainLabel.numberOfLines = 0;
let autLabel = cell?.viewWithTag(3) as! UILabel
autLabel.text = postsinput[indexPath.row].author
autLabel.font = UIFont(name: "Helvetica", size:16)
autLabel.textColor = UIColor(red: 0.8784, green: 0, blue: 0.1373, alpha: 1.0) /* #e00023 */
let sumLabel = cell?.viewWithTag(4) as! UILabel
sumLabel.text = (postsinput[indexPath.row].summary).replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)
sumLabel.font = UIFont(name: "Helvetica", size:16)
sumLabel.textColor = UIColor(red:0.27, green:0.27, blue:0.27, alpha:1.0)
//let contentLabel = cell?.viewWithTag(0) as! UILabel
//contentLabel.text = (postsinput[indexPath.row].content).replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)
//(cell?.viewWithTag(3) as! UILabel).text = postsinput[indexPath.row].author
return cell!
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
SVProgressHUD.show()
let indexPath = self.tableView.indexPathForSelectedRow?.row
let vc = segue.destination as! nextVC
vc.articleImage = postsinput[indexPath!].mainImage
vc.articleMainTitle = postsinput[indexPath!].name
vc.articleContent = postsinput[indexPath!].content
SVProgressHUD.dismiss()
let backItem = UIBarButtonItem()
backItem.title = "Back"
navigationItem.backBarButtonItem = backItem // This will show in the next view controller being pushed
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
postsinput.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Your issue is here:
postsinput.append(postinput.init(mainImage: mainImage, name: title, author: author, summary: summary, content: content))
You keep appending new data to the old data. If you want to completely clear out the old data before adding new data, just remove all of the elements from the postsinput array.
Your task here in pull to refresh is to just refresh the data existing in your list and also add the new items if any. So what you have to do is instead of keep on adding the items to your list everytime you pull-to-refresh, you just provide a new list coming from server to your tableView. Which you have the array aleready postsinput so make sure to remove all the items before you add it. Below is your code where you can do the changes.
func parseData(JSONData : Data) {
postsinput.removeAll()
do {
...
...
if let imageUrl = post["image"] as? String {
let mainImageURL = URL(string: imageUrl )
let mainImageData = NSData(contentsOf: mainImageURL!)
let mainImage = UIImage(data: mainImageData as! Data)
postsinput.append(postinput.init(mainImage: mainImage, name: title, author: author, summary: summary, content: content))
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
...
...
}
Related
I'm having a problem regarding a feature where You can delete a cell and so delete and event using an Alamofire JSON request.
When I swipe the cell and click delete, the app crashes, but the event get deleted successfully and with no errors, in facts on Laravel side I get the event deleted.
I tried everything, but I really can't figure out how to fix the crash.
Can someone help me please?
here is my .Swift code:
import UIKit
import Alamofire
class EventViewController: UITableViewController {
#objc var transition = ElasticTransition()
#objc let lgr = UIScreenEdgePanGestureRecognizer()
#objc let rgr = UIScreenEdgePanGestureRecognizer()
let rc = UIRefreshControl()
#IBOutlet weak var myTableView: UITableView!
var myTableViewDataSource = [NewInfo]()
let url = URL(string: "http://ns7records.com/staffapp/api/events/index")
override func viewDidLoad() {
super.viewDidLoad()
loadList()
// Add Refresh Control to Table View
if #available(iOS 10.0, *) {
tableView.refreshControl = rc
} else {
tableView.addSubview(rc)
}
// Configure Refresh Control
rc.addTarget(self, action: #selector(refreshTableData(_:)), for: .valueChanged)
let attributesRefresh = [kCTForegroundColorAttributeName: UIColor.white]
rc.attributedTitle = NSAttributedString(string: "Caricamento ...", attributes: attributesRefresh as [NSAttributedStringKey : Any])
DispatchQueue.main.async {
}
// MENU Core
// customization
transition.sticky = true
transition.showShadow = true
transition.panThreshold = 0.3
transition.transformType = .translateMid
// menu// gesture recognizer
lgr.addTarget(self, action: #selector(MyProfileViewController.handlePan(_:)))
rgr.addTarget(self, action: #selector(MyProfileViewController.handleRightPan(_:)))
lgr.edges = .left
rgr.edges = .right
view.addGestureRecognizer(lgr)
view.addGestureRecognizer(rgr)
}
#objc private func refreshTableData(_ sender: Any) {
// Fetch Table Data
//myTableViewDataSource.removeAll()
tableView.reloadData()
loadList()
}
func loadList(){
var myNews = NewInfo()
// URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
//
// })
let task = URLSession.shared.dataTask(with:url!) {
(data, response, error) in
if error != nil
{
print("ERROR HERE..")
}else
{
do
{
if let content = data
{
let myJson = try JSONSerialization.jsonObject(with: content, options: .mutableContainers)
//print(myJson)
if let jsonData = myJson as? [String : Any]
{
if let myResults = jsonData["data"] as? [[String : Any]]
{
//dump(myResults)
for value in myResults
{
if let myTitle = value["title"] as? String
{
//print(myTitle)
myNews.displayTitle = myTitle
}
if let myLocation = value["local"] as? String
{
myNews.location = myLocation
}
if let myDate = value["date"] as? String
{
myNews.date = myDate
}
if let myDescription = value["description"] as? String
{
myNews.description = myDescription
}
if let myCost = value["cost"] as? String
{
myNews.cost = myCost
}
if let myNumMembers = value["num_members"] as? String
{
myNews.num_members = myNumMembers
}
if let myNumMembers_conf = value["num_members_confirmed"] as? String
{
myNews.num_members_confirmed = myNumMembers_conf
}
if let myStartEvent = value["time_start"] as? String
{
myNews.startEvent = myStartEvent
}
if let myEndEvent = value["time_end"] as? String
{
myNews.endEvent = myEndEvent
}
if let myId = value["id"] as? Int
{
myNews.idEvent = myId
}
//x img
// if let myMultimedia = value["data"] as? [String : Any]
// {
if let mySrc = value["event_photo"] as? String
{
myNews.event_photo = mySrc
print(mySrc)
}
self.myTableViewDataSource.append(myNews)
}//end loop
dump(self.myTableViewDataSource)
DispatchQueue.main.async
{
self.tableView.reloadData()
self.rc.endRefreshing()
}
}
}
}
}
catch{
}
}
}
task.resume()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath)->CGFloat {
return 150
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myTableViewDataSource.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCell(withIdentifier: "reuseCell", for: indexPath)
let myImageView = myCell.viewWithTag(11) as! UIImageView
let myTitleLabel = myCell.viewWithTag(12) as! UILabel
let myLocation = myCell.viewWithTag(13) as! UILabel
let DateLabelCell = myCell.viewWithTag(14) as! UILabel
let numMembLabel = myCell.viewWithTag(15) as! UILabel
let numMembConfLabel = myCell.viewWithTag(16) as! UILabel
myTitleLabel.text = myTableViewDataSource[indexPath.row].displayTitle
myLocation.text = myTableViewDataSource[indexPath.row].location
DateLabelCell.text = myTableViewDataSource[indexPath.row].date
numMembLabel.text = myTableViewDataSource[indexPath.row].num_members
numMembConfLabel.text = myTableViewDataSource[indexPath.row].num_members_confirmed
if let imageURLString = myTableViewDataSource[indexPath.row].event_photo,
let imageURL = URL(string: AppConfig.public_server + imageURLString) {
myImageView.af_setImage(withURL: imageURL)
}
return myCell
}
//per passare da un viewcontroller a detailviewcontroller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? EventDetailViewController {
destination.model = myTableViewDataSource[(tableView.indexPathForSelectedRow?.row)!]
// Effetto onda
let vc = segue.destination
vc.transitioningDelegate = transition
vc.modalPresentationStyle = .custom
}
//menu
if let vc = segue.destination as? MenuViewController{
vc.transitioningDelegate = transition
vc.modalPresentationStyle = .custom
//endmenu
}
}
//menu slide
#objc func handlePan(_ pan:UIPanGestureRecognizer){
if pan.state == .began{
transition.edge = .left
transition.startInteractiveTransition(self, segueIdentifier: "menu", gestureRecognizer: pan)
}else{
_ = transition.updateInteractiveTransition(gestureRecognizer: pan)
}
}
//endmenuslide
////ximg
func loadImage(url: String, to imageView: UIImageView)
{
let url = URL(string: url )
URLSession.shared.dataTask(with: url!) { (data, response, error) in
guard let data = data else
{
return
}
DispatchQueue.main.async
{
imageView.image = UIImage(data: data)
}
}.resume()
}
/// star to: (x eliminare row e x muove row)
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let movedObjTemp = myTableViewDataSource[sourceIndexPath.item]
myTableViewDataSource.remove(at: sourceIndexPath.item)
myTableViewDataSource.insert(movedObjTemp, at: destinationIndexPath.item)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete){
// print(parameters)
let idEvent = (myTableViewDataSource[indexPath.item].idEvent)
let parameters = [
// "id": UserDefaults.standard.object(forKey: "userid")! ,
"id" : idEvent,
] as [String : Any]
let url = "http://www.ns7records.com/staffapp/public/api/deleteevent"
print(url)
Alamofire.request(url, method:.post, parameters:parameters,encoding: JSONEncoding.default).responseJSON { response in
switch response.result {
case .success:
print(response)
let JSON = response.result.value as? [String : Any]
//self.myTableView.reloadData()
let alert = UIAlertController(title: "Yeah!", message: "Evento modificato con successo!", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.destructive, handler: nil))
self.present(alert, animated: true, completion: nil)
// let data = JSON! ["data"] as! NSDictionary
if let jsonData = JSON as? [String : Any]
{
print(jsonData)
self.myTableViewDataSource.remove(at : indexPath.item)
self.myTableView.deleteRows(at: [indexPath], with: .automatic)
let indexPath = IndexPath(item: 0, section: 0)
//self.myTableView.deleteRows(at: [indexPath], with: .fade)
//self.myTableView.reloadData()
// }
// }
//}
}
case .failure(let error):
print(error)
let alert = UIAlertController(title: "Aia", message: "Non puoi cancellare questo evento!", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.destructive, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}
}
#IBAction func EditButtonTableView(_ sender: UIBarButtonItem) {
self.myTableView.isEditing = !self.myTableView.isEditing
sender.title = (self.myTableView.isEditing) ? "Done" : "Edit"
}
/// end to: (x eliminare row e x muove row)
}
// MARK: -
// MARK: UITableView Delegate
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
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()
}
I am working on a project to shows news feeds to the user.
I am calling a function getNewsFeeds() to get news feeds.
I will generate new newsfeeds every one hour
ViewDidLoad(){
get current time in "HH" format and store it in currentTime
Store this currentTime in to a HoursVar variable using UserDefaults
}
ViewDidAppear(){
if( currentTime - HoursVar >= 1){
getNewsFeeds
}else{
}
retreiveStoredValuesFromUserDeafults()
}
I dont know where exactly to setup my tableViewDataSOurce and Delegate methods and reloadData to populate the tableView when getting data from the saved Userdefaults retreiveStoredValuesFromUserDeafults()
override func viewDidLoad() {
super.viewDidLoad()
hoursFormatter.dateFormat = "HH"
hoursVar = Int(hoursFormatter.string(from: hours))!
if hoursVar > 12 {
hoursVar = hoursVar - 12
}
self.defaults.set(self.hoursVar, forKey: "hoursVar")
customNavBar()
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
feedsArray = ["Reliance","Economy"]
}
override func viewDidAppear(_ animated: Bool) {
//getRssFeeds()
if((hoursVar - myHoursVar) == 1 && (hoursVar - myHoursVar) > 1){
getRssFeeds()
}else{
feedsTable.register(UITableViewCell.self, forCellReuseIdentifier: "newsFeeds")
self.feedsTable.delegate = self
self.feedsTable.dataSource = self
retreiveMyArrayData()
feedsTableView.reloadData()
}
}
func getRssFeeds(){
for i in 0..<feedsArray.count{
let url = URL(string: "https://api.cognitive.microsoft.com/bing/v5.0/news/search?q=\(feedsArray[i])&count=3&mkt=en-in")
var request = URLRequest(url: url!)
request.setValue("My Subscription Key", forHTTPHeaderField: "Ocp-Apim-Subscription-Key")
Alamofire.request(request as URLRequest).responseJSON{response in
if let json = response.result.value as? [String:AnyObject]{
if let value = json["value"]{
//
print("json \(json)")
for j in 0..<value.count{
let items = value[j] as! [String:AnyObject]
let name = items["name"] as! String
let url = items["url"] as! String
let description = items["description"] as! String
let datePublished = items["datePublished"] as! String
let dateAndTime = datePublished.replacingOccurrences(of: "T", with: " ")
self.feedsName.append(name)
self.feedsUrl.append(url)
self.feedsDescription.append(description)
self.feedsDatePublished.append(dateAndTime)
if let image = items["image"] as? [String:AnyObject]{
if let thumbnail = image["thumbnail"] as? [String:AnyObject]{
let contentUrl = thumbnail["contentUrl"] as! String
self.feedsContentUrl.append(contentUrl)
}
}else{
self.feedsContentUrl.append(self.errorImage)
}
if let provider = items["provider"]{
for i in 0..<provider.count{
let items = provider[i] as! [String:AnyObject]
let providerName = items["name"] as! String
self.feedsProvider.append(providerName)
}
}
self.feedsTable.delegate = self
self.feedsTable.dataSource = self
self.feedsTable.reloadData()
self.defaults.set(self.feedsUrl, forKey: "feedsUrl")
self.defaults.set(self.feedsDescription, forKey: "feedsDescription")
self.defaults.set(self.feedsName, forKey: "feedsName")
self.defaults.set(self.feedsProvider, forKey: "feedsProvider")
self.defaults.set(self.feedsContentUrl, forKey: "feedsContentUrl")
self.defaults.set(self.feedsDatePublished, forKey: "feedsDatePublished")
print("All Counts \(self.feedsName.count)")
}
}
}
}
}
}
func slideOpen(){
self.revealViewController().revealToggle(animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return feedsName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "newsFeeds") as! newsFeeds
randomNumberArray = randomNumber()
//self.feedsRandomArray.append(self.feedsRandom)
print("feedsRandom \(feedsRandom)")
selectedRow = randomNumberArray[indexPath.row]
let url = URL(string: feedsContentUrl[randomNumberArray[indexPath.row]])
do{
let data = try Data(contentsOf: url!)
cell.feedsImage.image = UIImage(data: data )
}catch{
print(error)
}
let tap = UITapGestureRecognizer(target: self, action: #selector(HomeViewController.tapFunction))
let titleAttributes = [NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline), NSForegroundColorAttributeName: UIColor.purple]
let titleString = NSAttributedString(string: feedsName[randomNumberArray[indexPath.row]] , attributes: titleAttributes)
cell.feedsHeadlines.isUserInteractionEnabled = true
cell.feedsHeadlines.addGestureRecognizer(tap)
cell.feedsHeadlines.attributedText = titleString
cell.feedsDescription.text = feedsDescription[randomNumberArray[indexPath.row]]
cell.feedsPublisherName.text = feedsProvider[randomNumberArray[indexPath.row]]
cell.publishedOn.text = feedsDatePublished[randomNumberArray[indexPath.row]]
//print("All Counts \(myFeedsName.count) \(myFeedsProvider.count) \(myFeedsContentUrl.count) \(myFeedsUrl.count) \(myFeedsDescription.count) \(myFeedsDescription.count)")
return cell
}
func tapFunction(sender:UITapGestureRecognizer) {
let safariVC = SFSafariViewController(url: NSURL(string: feedsUrl[selectedRow]) as! URL)
self.present(safariVC, animated: true, completion: nil)
safariVC.delegate = self
}
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
controller.dismiss(animated: true, completion: nil)
}
func randomNumber() -> [Int] {
let feedsIndex = feedsName.count - 1
var randomNumber = Int(arc4random_uniform(UInt32(feedsIndex)))
print("Randome number \(randomNumber) \(randomNumberArray)")
for k in 0..<randomNumberArray.count{
while randomNumber == randomNumberArray[k] {
randomNumber = Int(arc4random_uniform(UInt32(feedsIndex)))
}
}
randomNumberArray.append(randomNumber)
self.defaults.set(self.randomNumberArray, forKey: "randomNumberArray")
return randomNumberArray
}
func retreiveMyArrayData(){
myFeedsUrl = defaults.stringArray(forKey: "feedsUrl") ?? [String]()
myFeedsDescription = defaults.stringArray(forKey: "feedsDescription") ?? [String]()
myFeedsName = defaults.stringArray(forKey: "feedsName") ?? [String]()
myFeedsProvider = defaults.stringArray(forKey: "feedsProvider") ?? [String]()
myFeedsContentUrl = defaults.stringArray(forKey: "feedsContentUrl") ?? [String]()
myFeedsDatePublished = defaults.stringArray(forKey: "feedsDatePublished") ?? [String]()
myHoursVar = defaults.integer(forKey: "hoursVar")
myFeedsRandom = defaults.array(forKey: "randomNumberArray") as! [Int]
print("Values \(myHoursVar) \(myFeedsProvider) \(myFeedsUrl.count)")
}
You can set UITableViewDataSourceand UITableViewDelegate into .xib
//Setting datasource & delegate for tableview inside viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.feedsTableView.delegate = self
self.feedsTableView.datasource = self
}
Now, you need to reload the tableview when you setValue & retrieve the value to the userDefaults. self.feedsTableView.reloadData()
If this didn't helped you, please let me know. I'll work more to provide you with a complete workflow for the above project.
I have an app that is using Swift 3 and Alamofire. The data is connected to two cell?.viewWithTag(2) and cell?.viewWithTag(1) which is an image (from url) and text. So when I run the project nothing is showing in my App. I have tested the JSON with print(readableJSON) and the JSON is getting printed into the console. So I am a little confused really. My swift looks like this:
SWIFT
import UIKit
import Alamofire
struct postinput {
let mainImage : UIImage!
let name : String!
}
class TableViewController: UITableViewController {
var postsinput = [postinput]()
var mainURL = "https://www.example.api.com"
typealias JSONstandard = [String : AnyObject]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
callAlamo(url: mainURL)
}
func callAlamo(url : String){
Alamofire.request(url).responseJSON(completionHandler: {
response in
self.parseData(JSONData: response.data!)
})
}
func parseData(JSONData : Data) {
do {
var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONstandard
print(readableJSON)
if let posts = readableJSON["posts"] as? [JSONstandard] {
for post in posts {
let title = post["title"] as! String
print(title)
if let imageUrl = post["image"] as? JSONstandard {
let mainImageURL = URL(string: imageUrl["url"] as! String)
let mainImageData = NSData(contentsOf: mainImageURL!)
let mainImage = UIImage(data: mainImageData as! Data)
postsinput.append(postinput.init(mainImage: mainImage, name: title))
self.tableView.reloadData()
}
}
}
}
catch {
print(error)
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return postsinput.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
// cell?.textLabel?.text = titles[indexPath.row]
let mainImageView = cell?.viewWithTag(2) as! UIImageView
mainImageView.image = postsinput[indexPath.row].mainImage
let mainLabel = cell?.viewWithTag(1) as! UILabel
mainLabel.text = postsinput[indexPath.row].name
return cell!
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
JSON
{
"posts" : [{
"id": "000000",
"url": "/content/interview2",
"date": "2016-11-03 09:01:41",
"modified": "2016-11-03 09:03:47",
"title": "An interview",
"image": "https://www.example.com/sites/default/files/oregood.jpeg",
"summary": {
"value": "<p>Latin text here</p>",
"format": "filtered_html"
}
}]
}
From your JSON response image key contains String not Dictionary also you need to reload your tableView outside for loop not every time inside the loop, so try like this.
if let posts = readableJSON["posts"] as? [JSONstandard] {
for post in posts {
let title = post["title"] as! String
if let imageUrl = post["image"] as? String {
let mainImageURL = URL(string: imageUrl as! String)
let mainImageData = NSData(contentsOf: mainImageURL!)
let mainImage = UIImage(data: mainImageData as! Data)
postsinput.append(postinput.init(mainImage: mainImage, name: title))
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
Suggestion : Instead of downloading image using NSData(contentsOf:) on main thread batter to use library like SDWebImages or you can create your own async image downloader.
because you are not displaying your JSON in table cells. You crate a copied object called "mainImageView" and never assign it as actual imageView of table cell, instead try:
(cell?.viewWithTag(2) as? UIImageView).image = postsinput[indexPath.row].mainImage
postsinput contains image strings or images?
EDIT:
so it would be:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
// cell?.textLabel?.text = titles[indexPath.row]
//let mainImageView = cell?.viewWithTag(2) as! UIImageView
//mainImageView.image = postsinput[indexPath.row].mainImage
(cell?.viewWithTag(2) as? UIImageView).image = postsinput[indexPath.row].mainImage
//let mainLabel = cell?.viewWithTag(1) as! UILabel
//mainLabel.text = postsinput[indexPath.row].name
(cell?.viewWithTag(1) as? UILabel).text = postsinput[indexPath.row].name
return cell!
}
I have a project which is trying to bring in data from a web url using alamofire. I am trying to bring in image and text but keep getting build failed. I am trying to add the data (image and text) to tags = 1 and 2. My code is below any help would be appreciated. I am fairly new to Swift. Thanks
SWIFT
import UIKit
import Alamofire
struct postinput {
let mainImage : UIImage!
let name : String!
}
class TableViewController: UITableViewController {
var postsinput = [postinput]()
var mainURL = "https://www.testJSON.com"
typealias JSONstandard = [String : AnyObject]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
callAlamo(url: mainURL)
}
func callAlamo(url : String){
Alamofire.request(url).responseJSON(completionHandler: {
response in
self.parseData(JSONData: response.data!)
})
}
func parseData(JSONData : Data) {
do {
var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONstandard
if let posts = readableJSON["posts"] as? [JSONstandard] {
for post in posts {
let title = post["title"] as! String
if let images = post["image"] as? JSONstandard {
let mainImageURL = URL(string: imageData["url"] as! String)
let mainImageData = NSData(contentsOf: mainImageURL!)
let mainImage = UIImage(data: mainImageData as! Data)
}
postsinput.append(postinput.init(mainImage: mainImage, name: name))
}
self.tableView.reloadData()
}
}
catch {
print(error)
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return postsinput.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
// cell?.textLabel?.text = titles[indexPath.row]
let mainImageView = cell?.viewWithTag(2) as! UIImageView
mainImageView.image = postsinput[indexPath.row].mainImage
let mainLabel = cell?.viewWithTag(1) as! UILabel
mainLabel.text = postsinput[indexPath.row].name
return cell!
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
JSON
{ posts: [ { id: “000000”, url: "/content/interview2”, date: "2016-11-03 09:01:41", modified: "2016-11-03 09:03:47", title: "An interview", image: "https://www.example.com/sites/default/files/oregood.jpeg", summary: { value: "<p>Latin text here</p> ", format: "filtered_html" } ]}
The following are the reasons for your build error are the following:
you added this line postsinput.append(postinput.init(mainImage: mainImage, name: name))
outside the context where mainImage is obtained. Based on the json, I believe that you are supposed to rewrite it like this.
if let imageUrl = post["image"] as? JSONstandard {
let mainImageURL = URL(string: imageUrl)
let mainImageData = NSData(contentsOf: mainImageURL!)
let mainImage = UIImage(data: mainImageData as! Data)
postsinput.append(postinput.init(mainImage: mainImage, name: title))
}
Even if you do that, the variables imageData and name are undefined. You should look into that.
Just a suggestion, do not force unwrap optionals. Use optional binding wherever possible.