I'm not that much of a pro in using swift..but i've been trying to create an social media app using firebase as backend. But I am stuck in this one part where the data gets stored in an Array..but when . i call the array I keep getting the "Ambiguous reference to member 'count' " error and I have tried many ways to fix this but end up unsuccessful every time
var posts = [AnyObject?]()
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: HomeViewTableViewCell = tableView.dequeueReusableCell(withIdentifier: "HomeViewTableViewCell", for: indexPath) as! HomeViewTableViewCell
let post = (posts[(self.posts.count - 1) - indexPath.row] as AnyObject).value["text"] as! String //**Ambiguous reference to member 'count'
cell.configure(nil,NameText:self.loggedInUserData!.value["NameText"] as! String, TitleText:self.loggedInUserData!.value["TitleText"] as! String, post:post)
return cell
}
Please help!
Actually trying this tutorial out in Youtube...So if full code required, This is the YouTube link:
https://www.youtube.com/watch?v=BeZ3i7-gaok&list=PLy9JCsy2u97kro0jXbXrPFmT-DQVAmNW0&index=4
you might want to use value(forKey:) here
let post = (posts[(self.posts.count - 1) - indexPath.row] as AnyObject).value(forKey: "text")
Related
Recently in my app I have been using Firebase to store information for my app and it has worked well. Now I am using it to stream videos with a web view being used in the tableview to display Youtube videos. When trying to link the WebView to the database, I get an error that says:
Type 'video' has no subscript members
What would be causing this?
Here is the code:
import UIKit
import Firebase
class videoController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var ref = DatabaseReference()
var video = [UIWebView]()
var databaseHandle:DatabaseHandle = 0
#IBOutlet var videoController: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
databaseHandle = ref.child("Videos").observe(.childAdded) { (snapshot) in
let post = snapshot.value as? UIWebView
if let actualPost = post {
self.video.append(actualPost)
self.videoController.reloadData()
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return video.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let video = tableView.dequeueReusableCell(withIdentifier: "video") as! video
video.videos.allowsInlineMediaPlayback = video[indexPath.row]
return(video)
}
}
This line:
let video = tableView.dequeueReusableCell(withIdentifier: "video") as! video
is your problem. This creates a new, local variable named video and it hides your video array property. Change it to:
let videoCell = tableView.dequeueReusableCell(withIdentifier: "video") as! video
Here's the whole method:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let videoCell = tableView.dequeueReusableCell(withIdentifier: "video") as! video
videoCell.videos.allowsInlineMediaPlayback = video[indexPath.row]
return videoCell
}
But on top of all of that, why do you have an array of web views? You certainly are not getting web views from Firebase.
And please fix your naming conventions. Class, struct, and enum names should start with uppercase letters. Variable, function, and case names start with lowercase letters. And use descriptive names. Naming everything simply video is confusing.
And change your video array to videos.
I developing news app. I using RSS feed with XML Parsing. I want RSS feed add images. I have defined the necessary function for images. But I do not know how to use a variable when I get the photo in RSS. My application is currently receiving the photo from the URL. All photos are the same. How can I do that? Sorry for my bad English.
//UItableView Data source
internal func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return haberler.count
}
internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
var cell:EmojiTableViewCell = tableView.dequeueReusableCell(withIdentifier: "myCell")! as UITableViewCell as! EmojiTableViewCell
if (cell.isEqual(NSNull.self))
{
cell = Bundle.main.loadNibNamed("myCell", owner: self, options: nil)?[0] as! UITableViewCell as! EmojiTableViewCell
}
let emojiTitle = (haberler.object(at: indexPath.row) as AnyObject).value(forKey: "title") as! NSString as String
cell.emojiTitleLabel.text = emojiTitle.trimmingCharacters(in: .whitespaces)
cell.emojiImageView.downloadFrom(link: "http://teknolojix.net/wp-content/uploads/2014/10/Below-is-a-rendering-of-the-page-up-to-the-first-error-hatası.jpg", contentMode: UIViewContentMode.scaleAspectFill)
return cell
}
Your problem is very simple. you have pass the same link on the "downloadFrom" function. Please use "haberler" array to get the different image photo url. For example I used you above mentioned code to give you proper understanding.
CODE:
cell.emojiImageView.downloadFrom(link:haberler[indexPath.row].YOUR_PHOTO_URL_KEY_NAME, contentMode: UIViewContentMode.scaleAspectFill)
If you are not understand, please provide me "haberler" array so that I can give you proper solution with code.
Actually you are using hard-coded 'URL' to download image every time. You need to show image for every cell by getting different 'URL' from your data source same like you are getting 'title' for every cell. For example:
let emojiImageURL = (haberler.object(at: indexPath.row) as AnyObject).value(forKey: "url") as! NSString as String
cell.emojiImageView.downloadFrom(link: emojiImageURL, contentMode: UIViewContentMode.scaleAspectFill)
I have a UITableViewController with UITableViewCell dynamically generated there. Each cell contains an imageView that I'm filling with images fetched from my server. I'm using alamofire_images to do so. My code looks as follows:
func tableView(testDetailsPanel: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = testDetailsPanel.dequeueReusableCellWithIdentifier("cell") as! TestDetailsCell
let test:SingleTest = self.items[indexPath.row] as! SingleTest
if(test.photo != "") {
cell.myPhoto.af_setImageWithURL(NSURL(string: test.photo)!)
} else {
cell.myPhoto.image = UIImage(named: "clusterLarge")
}
return cell
}
I thought that since I'm downloading images while displaying the table, there is no need to download it again on the other screen (which is accessible through clicking each cell).
So my idea was to pass the image from specific cell to the other screen through segue. But the problem is that from the method prepareForSegue I don't have access to the specific cell that user clicks. So my other choice was to use protocols. I created a very simple one:
protocol HandlePhoto: class {
func setUpBackgroundPhoto(miniature: UIImage)
}
and then in my native class I wanted to use it in didSelectRowAtIndexPath method:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let test:SingleTest = self.items[indexPath.row] as! SingleTest
let cell = testDetailsPanel.dequeueReusableCellWithIdentifier("cell") as! TestDetailsCell
if(test.photo != "") {
handlePhoto.setUpBackgroundPhoto(cell.testPhoto.image!)
self.performSegueWithIdentifier("testPhotoDetailsSegue", sender: test)
}
} else {
self.performSegueWithIdentifier("testTextDetailsSegue", sender: test)
}
}
But this line:
handlePhoto.setUpBackgroundPhoto(cell.testPhoto.image!)
throws error:
fatal error: unexpectedly found nil while unwrapping an Optional value
So my final question is: how can I access photo from the specific cell that user chooses and pass it to other view (without downloading it there for the 2nd time)?
Your didSelectRowAtIndexPath implementation is wrong, with dequeueReusableCellWithIdentifier you are obtaining a new cell, not the selected cell.
Try this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let selectedCell = tableView.cellForRow(at: indexPath) as! TestDetailsCell
//this will return downloaded image or "clusterLarge"
let image = selectedCell.myPhoto.image
//
//Make your check on image and extra setup
//
self.performSegueWithIdentifier("testPhotoDetailsSegue", sender: test)
}
Why are you using dequeueReusableCellWithIdentifier in your didSelectRowAtIndexPath?; instead, you should get the cell directly using:
let cell = yourTableView.cellForRowAtIndexPath(indexPath) as! TestDetailsCell
if let image = cell.testPhoto.image {
print(image)//this is what you want.
}
Latest Xcode upgrade 7.3 broke the following block of code in a tableview:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("GameCell", forIndexPath: indexPath) as! GameViewCell
if PFUser.currentUser()!.objectId == self.user1.objectId{
let user = gameResults[indexPath.row]["user2"] as! PFUser
cell.userName.text = user["first_name"] as! String
self.viewUser = user
}
The line let user = gameResults[indexPath.row]["user2"] as! PFUser returns error ambiguous subscript. I looked at other answers here about this issue so I tried to change it to let user = )(gameResults[indexPath.row]["user2"] as NSArray) as! PFUser but that didn't work.
How can I get this to work? Thanks!!
UPDATE:
I added an exclamation mark after the subscript and it seemed to get rid of the error. Like this:
let user = gameResults[indexPath.row]["user2"]! as! PFUser
Is this an acceptable way of fixing this?
I'm trying to use Realm in my UITableViewController and I'm running into issues whenever I try to find the object at a row index if I cast the object to its class (forgive me if I'm using the wrong terminology, I'm still pretty new to Swift, Realm ans iOS dev!)...
I have a Site class which looks like this, and the database has a few thousand entries:
class Site: RLMObject {
var id: String = ""
var name: String = ""
}
In my table view controller, when I try to fetch a Site based on its index in the result set to load into a cell, if I try to cast it to a Site object it's always nil! If I let it be set using AnyObject, then I can see that the correct site at that index has indeed been found.
I'm guessing the .name call on AnyObject is only working because AnyObject responds to .name, but it helps me to see that the index is correct and that the site does exist...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()
var any: AnyObject = allSites.objectAtIndex(UInt(indexPath.row))
var site = allSites.objectAtIndex(UInt(indexPath.row)) as? Site
println("With AnyObject: \(any.name)")
println("With casting: \(site?.name)")
return cell
}
The result of the print statements above look like this (for example on a site which is named 'Addeboda'):
With AnyObject: Addeboda
With casting: Optional("")
Am I doing something wrong? I've googled around a bit, and all the tutorials and answers I can find along similar lines suggest that results.objectAtIndex(index) as Class should be the right approach.
No cast needed
It seems that casting to Site is not needed. This works fine:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()
let site: AnyObject! = allSites[UInt(indexPath.row)]
cell.textLabel!.text = site.name
println("Site is: \(site.id)")
return cell
}
Seems to be a bug with either Swift or Realm. I'm guessing one of them gets confused when downcasting AnyObject! to something.
Initializing a new instance with correct type
However, if you really need to use the Site model class you can initialize a new RLMObject from the result:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()
let site = Site(object: allSites[UInt(indexPath.row)])
cell.textLabel!.text = site.name
println("Site is: \(site.id)")
return cell
}
First try
It is unfortunate to hear that you are having issues with Realm and Swift. I am by no means a Swift pro, but it looks like you are casting site to an optional, and the result of using the optional cast operator site?.name is also an optional. Hence getting Optional("").
Can you try to see if you have any better luck with the following?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()
if var site = allSites[UInt(indexPath.row)] as? Site {
println("Site is: \(site.name)")
} else {
println("it not castable to Site. It is: \(toString(allSites[UInt(indexPath.row)].dynamicType))")
}
return cell
}
Also, you can use yourObject.dynamicType to get a reference to the objects real class type.
Best of luck
Here is some code from the tableview sample project:
class TableViewController: UITableViewController {
var array = DemoObject.allObjects().sortedResultsUsingProperty("date", ascending: true)
...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as Cell
let object = array[UInt(indexPath.row)] as DemoObject
cell.textLabel?.text = object.title
cell.detailTextLabel?.text = object.date.description
return cell
}
}
You should be able to cast on the line you are storing that indexPath.row object