I try to pass data from my ViewController to TableViewPlace.swiftUse the buttons. When I am choosing button return not some thing
viViewController
class ViewController: UIViewController {
struct Country{
var id :Int
init(id:Int){
self.id = id
}
}
var CountrySelected = [Country]()
var countryArry = NSArray()
override func viewDidLoad() {
super.viewDidLoad()
// 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.
}
#IBAction func airAction(sender: AnyObject) {
}
#IBAction func viewPlaceAction(sender: AnyObject) {
getParsePlaceView()
// json viewPlace
performSegueWithIdentifier("viewPlaceSegu", sender: sender)
}
#IBAction func tourAction(sender: AnyObject) {
}
/// Open the page
// parse json
func getParsePlaceView(){
let url = NSURL(string: "http://jsonplaceholder.typicode.com/posts")
NSURLSession.sharedSession().dataTaskWithURL(url!){ [unowned self] (data , repsonse , error) in
if error != nil {
print(error!)
} else {
do {
let posts = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers) as! [[String:AnyObject]]
for post in posts {
if let id = post["userId"] as? Int{
// print(id)
let sets = Country(id: id)
self.CountrySelected.append(sets)
}
}
self.countryArry = posts
print(self.countryArry)// return data and currect
} catch let error as NSError {
print(error)
}
}
}.resume()
print(countryArry) // return nil why??
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// get a reference to the second view controller
if segue.identifier == "viewPlaceSegu" {
if let secondViewController = segue.destinationViewController as? TableViewPlace {
// set a variable in the second view controller with the String to pass
print(countryArry)
secondViewController.tnt = countryArry
}
}
}
}
when I print(countryArry) return nil why ??
Can someone help me or give me a better solution?
You are creating a Post object with this line :
let countryPlace = Post(userid: post["userId"] as! Int, title: post["title"] as! String)
And you are trying to pass to your tableview this Post object to your tnt variable which is a ViewController class, this is why you've got the first error :
secondViewController.tnt = Country
Then, if you want to add your string country to your mutable array you have to do :
if let title = tnt.title {
Country.append(title)
}
Related
I have one toggle button. Initially, it will be in off mode. So when I turn on my toggle I need to pass a set of data to collection view. And when its tun off again I need to pass a set of data to collection view.
So here is my code :
#IBAction func cateSelTap(_ sender: Any) {
isChecked = !isChecked
if isChecked {
self.subsetTheCategoryListForClientLogin(isCityLogin: false)
}else {
self.subsetTheCategoryListForClientLogin(isCityLogin: true)
}
}
func subsetTheCategoryListForClientLogin(isCityLogin: Bool) {
let cityType = "city"
print("LOG:CATE1 \(self.categoryarr)")
var objectIds = [Int]()
var subsetArray = NSMutableArray()
for i in 0..<self.categoryarr.count {
let type = (self.categoryarr.object(at:i) as AnyObject).value(forKey: "type") as! String
if isCityLogin {
if type == cityType {
subsetArray.add(self.categoryarr.object(at:i) as AnyObject)
objectIds.append(i)
}
} else {
if type != cityType {
subsetArray.add(self.categoryarr.object(at:i) as AnyObject)
objectIds.append(i)
}
}
}
self.categoryarr.removeAllObjects()
self.categoryarr = subsetArray
print("LOG:CATE2 \(self.categoryarr)")
DispatchQueue.main.async{
self.categorycollection.reloadData()
// self.categorycollection.performSelector(onMainThread: #selector(self.categorycollection.reloadData), with: nil, waitUntilDone: true)
}
}
When I run my app, and when I turn off - my collection view data is not showing exact data..still it is showing previous data. Again when I turn off its fully blank.
Any help on this?
Add a new property like categoryarr, say categoryCollectionViewSource and assign initial data to it. Use categoryCollectionViewSource in collection view delegate methods instead of categoryarr. And in the filter method
func subsetTheCategoryListForClientLogin(isCityLogin: Bool) {
let cityType = "city"
print("LOG:CATE1 \(self.categoryarr)")
var objectIds = [Int]()
var subsetArray = NSMutableArray()
for i in 0..<self.categoryarr.count {
let type = (self.categoryarr.object(at:i) as AnyObject).value(forKey: "type") as! String
if isCityLogin {
if type == cityType {
subsetArray.add(self.categoryarr.object(at:i) as AnyObject)
objectIds.append(i)
}
} else {
if type != cityType {
subsetArray.add(self.categoryarr.object(at:i) as AnyObject)
objectIds.append(i)
}
}
}
//note this line
self.categoryCollectionViewSource.removeAllObjects()
self.categoryCollectionViewSource = subsetArray
print("LOG:CATE2 \(self.categoryarr)")
DispatchQueue.main.async{
self.categorycollection.reloadData()
}
}
#IBAction func cateSelTap(_ sender: Any) {
isChecked = !isChecked
if isChecked {
self.subsetTheCategoryListForClientLogin(isCityLogin: false)
} else {
self.subsetTheCategoryListForClientLogin(isCityLogin: true)
}
}
I am trying to store randomly generated data into a second array so that I am able to press a button to go back to it. At the moment I press back and there is nothing there. I think it is due to the items not being correctly stored in the second array. I will provide the code for reference. Any help would be greatly appreciated!
var randomGeneratedQuotes = Array <String>()
var currentlyShown : String?
var randomQuote: String {
let randomNumber = Int(arc4random_uniform(UInt32(myQuotes.count)))
return myQuotes[randomNumber]
}
var previousRandom: String? {
if currentlyShown == randomQuote {
let previous = randomGeneratedQuotes.index(of: currentlyShown!)! - 1
return randomGeneratedQuotes[previous]
}
return randomGeneratedQuotes.last
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var randomQuote: String {
let randomNumber = Int(arc4random_uniform(UInt32(myQuotes.count)))
return myQuotes[randomNumber]
}
func storePrevious() {
if randomGeneratedQuotes.contains(randomQuote) {return}
randomGeneratedQuotes.append(randomQuote)
}
quotesLabel.text = randomQuote
}
//right hand button tapped
#IBAction func RHSButton(_ sender: Any) {
var randomQuote: String {
let randomNumber = Int(arc4random_uniform(UInt32(myQuotes.count)))
return myQuotes[randomNumber]
}
func storePrevious() {
if randomGeneratedQuotes.contains(randomQuote) {return}
randomGeneratedQuotes.append(randomQuote)
}
quotesLabel.text = randomQuote
}
//left hand button tapped
#IBAction func LHSButton(_ sender: Any) {
func pressedBack() {
currentlyShown = previousRandom
}
quotesLabel.text = previousRandom
}
i am trying to pass an image from one view controller to another but i am getting an error in prepare for segue function
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let post = posts[indexPath.row]
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)as? collectionViewCellBooks {
if let img = booksVC.imageCache.object(forKey: post.imageUrl as NSString) {
cell.configureCell(post: post, img: img)
return cell
}else {
cell.configureCell(post: post)
return cell
}
}
else {
return collectionViewCellBooks()
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "showImage", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "showImage"
{
let indexPaths = self.collectionView!.indexPathsForSelectedItems!
let indexPath = indexPaths[0] as IndexPath
let vc = segue.destination as! newViewController
// vc.image = self.posts[(indexPath as NSIndexPath).row]
vc.image = self.posts[indexPath.row]
}
class newViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
var image = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
self.imageView.image = self.image
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
this is my Post class
class Post {
private var _caption: String!
private var _imageUrl: String!
private var _postKey: String!
var caption: String {
return _caption
}
var imageUrl: String {
return _imageUrl
}
var postKey: String {
return _postKey
}
init(caption: String, imageUrl: String) {
self._caption = caption
self._imageUrl = imageUrl
}
init(postKey: String, postData: Dictionary<String, AnyObject>) {
self._postKey = postKey
if let caption = postData["title"] as? String {
self._caption = caption
}
if let imagesUrl = postData["imageURL"] as? String {
self._imageUrl = imagesUrl
}
}
}
title and imageURL are saved on firebase database
You are getting the error because you are not sending an image to the new viewController but an instance of your Post class, which by the way doesn't even contain an image (only an imageURL). You have to extract the image from the server first before you can parse it anywhere.
You should parse the whole post as you are doing it right now and download the image via the postID directly in the new ViewController. (in case you saved the image in Firebase storage) I always end up parseing the whole object because later in the development you maybe decide to show more properties in the newViewController. If you parsed the whole object you don't have to change your code structure anymore.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "your Identifier" {
if let vc = segue.destination as? NewViewController {
if let post = sender as? Post {
vc.post = post
}
}
}
}
in your didSelectIdemAt function you need to change the sender of the performSegue function:
performSegue(withIdentifier: "your Identifier", sender: post)
now your newViewController has a little bit more code but that is how i do it and it works stable.
let reference = FIRDatabase.database().reference()
reference.child("posts").child("<postID>").observeSingleEvent(of: FIRDataEventType.value, with: { (snapshot) in
print(snapshot.value)
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshots {
if let postsDict = snap.value as? Dictionary<String, AnyObject> {
if let imageURL = postsDict["imageURL"] as? String {
let httpsReference = FIRStorage.storage().reference(forURL: imageURL)
httpsReference.data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
if error != nil {
print("error... couldn't get picture from Server \(error.localizedDescription)")
} else {
let image = UIImage(data: data!)
self.img = image! // you need to create this variable somewhere in your viewController Class before this code
//"your UIImageVIew.image" = img AND THAT IS IT
}
}
}
}
}
}
Can you try with following change in preparefor segue method.. let me know
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
{
if segue.identifier == "showImage"
{
let indexPaths = self.collectionView!.indexPathsForSelectedItems!
let indexPath = indexPaths[0] as IndexPath
let vc = segue.destinationViewController as! newViewController
let post = posts[indexPath.row]
if let img = booksVC.imageCache.object(forKey: post.imageUrl as NSString) {
vc.image = img
}
}
}
class newViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
var image = nil
override func viewDidLoad() {
super.viewDidLoad()
if self.image {
self.imageView.image = self.image
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I was trying to get swfityjson and almo to work in Xcode 8
like in the post in this page:
Showing JSON data on TableView using SwiftyJSON and Alamofire
But I can not get the data from the self.
This helped me a little, but I am stuck with the count. Someone please help me with this, beacuse I am new to swift and have spent the day trying to understand how to get the count of rows and the data out of the almo function.
import UIKit
import Alamofire
import SwiftyJSON
class TableViewController: UITableViewController {
var names = [String]()
var rowCount = [Int]()
var tableTitle = [String]()
typealias JSONStandard = [String : AnyObject]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func callAlamo(){
let url = "http://xxxxxx/xxxx/xxxxxx.php"
//let id = UserDefaults.standard.string(forKey: "UserDefaults")
Alamofire.request(url).responseJSON{(respones)->Void in
if let value = respones.result.value{
let json = JSON(value)
let rows = json["items"].arrayValue
for anItem in rows {
let title: String? = anItem["SupplierName"].stringValue
self.tableTitle.append(title!)
//print(self.tableTitle.count)
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
// let isUserLoggedin = UserDefaults.standard.boll(forKey: "userLogIn")
let ststus = UserDefaults.standard.string(forKey: "userLogIn")
if ststus == "false" {
self.performSegue(withIdentifier: "loginView", sender: self)
}else{
callAlamo()
}
}
#IBAction func logout(_ sender: AnyObject) {
UserDefaults.standard.set(false, forKey: "userLogIn")
UserDefaults.standard.synchronize()
self.performSegue(withIdentifier: "loginView", sender: self)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print (tableTitle)
return self.tableTitle.count
}
}
I am unable to get the tableTitle.count. Thanks!
UITableView Delegate methods are called before viewDidAppear. So you need to reload the UITableView after got the response from server
DispatchQueue.main.async {
self.tableView.reloadData()
}
After the for loop.
import UIKit
import Alamofire
import SwiftyJSON
class TableViewController: UITableViewController {
var names = [String]()
var rowCount = [Int]()
var tableTitle = [String]()
typealias JSONStandard = [String : AnyObject]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func callAlamo(){
let url = "http://pos1.dermedia.co.il/iphone/getLasttransactions.php?cardid="
//let id = UserDefaults.standard.string(forKey: "UserDefaults")
Alamofire.request(url).responseJSON{(respones)->Void in
if let value = respones.result.value{
let json = JSON(value)
// print (json["items"].arrayValue)
let rows = json["items"].arrayValue
// print (rows)
for anItem in rows {
let title: String? = anItem["SupplierName"].stringValue
self.tableTitle.append(title!)
print(self.tableTitle.count)
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
// let isUserLoggedin = UserDefaults.standard.boll(forKey: "userLogIn")
let ststus = UserDefaults.standard.string(forKey: "userLogIn")
if ststus == "false" {
self.performSegue(withIdentifier: "loginView", sender: self)
}else{
callAlamo()
print ("gggggg")
print(self.tableTitle.count)
}
}
#IBAction func logout(_ sender: AnyObject) {
UserDefaults.standard.set(false, forKey: "userLogIn")
UserDefaults.standard.synchronize()
self.performSegue(withIdentifier: "loginView", sender: self)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print (self.tableTitle)
print("hhh")
return tableTitle.count
}
}
I have this app that I made with Swift, for fun and because I'm a beginner. Basically what it does is you can enter an artist name and song name and it fetches lyrics from AZLyrics.com based on the artist and song name you entered. For some reason most of the time when I try and load lyrics the first time when I open the app it doesn't load (it loads the 2nd, 3rd, 4th etc time). Here is my code could someone please tell me how I could fix this?
First View controller
import UIKit
var lyricsWithQuotes = ""
var urlError = false
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var songName: UITextField!
#IBOutlet var artistName: UITextField!
#IBAction func search(sender: AnyObject) {
var url = NSURL(string: "http://www.azlyrics.com/lyrics/" + artistName.text.stringByReplacingOccurrencesOfString(" ", withString: "").stringByReplacingOccurrencesOfString("'", withString: "").stringByReplacingOccurrencesOfString(",", withString: "").stringByReplacingOccurrencesOfString(".", withString: "").lowercaseString + "/" + songName.text.stringByReplacingOccurrencesOfString(" ", withString: "").stringByReplacingOccurrencesOfString("'", withString: "").stringByReplacingOccurrencesOfString(",", withString: "").stringByReplacingOccurrencesOfString(".", withString: "").lowercaseString + ".html")
if url != nil {
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
if error == nil {
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as NSString!
var urlContentArray = urlContent.componentsSeparatedByString("<!-- Usage of azlyrics.com content by any third-party lyrics provider is prohibited by our licensing agreement. Sorry about that. -->")
if urlContent.containsString("It's a place where all searches end!") {
urlError = true
} else {
var lyricsArray = urlContentArray[1].componentsSeparatedByString("<br><br>")
var lyrics = lyricsArray[0] as! String
var lyricsWithoutBR = lyrics.stringByReplacingOccurrencesOfString("<br>", withString: "")
var lyricsWithoutSlashDiv = lyricsWithoutBR.stringByReplacingOccurrencesOfString("</div>", withString: "")
var lyricsWithoutI = lyricsWithoutSlashDiv.stringByReplacingOccurrencesOfString("<i>", withString: "")
var lyricsWithoutSlashI = lyricsWithoutI.stringByReplacingOccurrencesOfString("</i>", withString: "")
lyricsWithQuotes = lyricsWithoutSlashI.stringByReplacingOccurrencesOfString(""", withString: "\"")
}
} else {
urlError = true
}
})
task.resume()
} else {
urlError = true
}
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
view.endEditing(true)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
override func viewDidLoad() {
super.viewDidLoad()
artistName.delegate = self
songName.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Second View Controller
import UIKit
var lyricsComplete = ""
class ViewController2: UIViewController {
#IBOutlet var lyricsDisplay: UITextView!
override func viewDidAppear(animated: Bool) {
if urlError == true {
urlError = false
lyricsDisplay.text = "Couldn't find that song!"
} else {
lyricsComplete = lyricsWithQuotes
lyricsDisplay.text = lyricsComplete
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
After your NSURLSession has completed - basically this line:
lyricsWithQuotes = lyricsWithoutSlashI.stringByReplacingOccurrencesOfString(""", withString: "\"")
You have two options:
Option One - Programatically launch the view:
let storyboard = UIStoryboard(name: "STORYBOARD NAME HERE", bundle: nil)
let newVC = storyboard.instantiateViewControllerWithIdentifier("VIEW CONTROLLER IDENTIFIER HERE") as! ViewController2
newVC.lyricsComplete = lyricsWithQuotes
If you have a navigation controller:
self.navigationController?.pushViewController(newVC, animated: true)
If you don't have a navigation controller:
self.showViewController(newVC, sender: self)
Options 2 - Trigger the Segue:
performSegueWithIdentifier("SEGUE NAME HERE", sender: nil)
Then intercept the Segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if(segue.identifier == "SEGUE NAME HERE"){
let newVC = segue.destinationViewController as! ViewController2
newVC.lyricsComplete = lyricsWithQuotes
}
}
If you use option 2, make sure the Segue is between the View Controllers and not attached to your button:
Like this:
Not like this: