I am new to swift and am looking for some help with this particular function I am trying to write.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
switch identifier {
case "Show Album":
let albumViewController = segue.destination as! AlbumViewController
let albumImageView = (sender as AnyObject).view as! UIImageView
if let index = index(of: covers, albumImageView) {
let album = Album(index: index)
albumViewController.album = album
}
On the line:
let albumImageView = (sender as AnyObject).view as! UIImageView
Getting the error:
ambiguous use of 'view'
Any help is appreciated.
sender as AnyObject casts sender to type AnyObject. AnyObject does not have a property with the name view, so calling .view on it does not make sense.
Related
I'm trying to do some of the project Euler problems in swift.
I originally tried using the Playground, but found that to be incredibly slow, so I've instead made a simple single view app that will run them for me in the simulator. See below for my example:
The way I did this was I made a customer class called ProblemClass and then I make a new class for each problem that inherits from that class. After that, all I have to do is override the functions in ProblemClass and then the View Controller just loads all the information from the Problem1 Class that inherited from ProblemClass.
When it segue's to the view that loads from Problem1 (or any other problem), it gets the details by me setting the currentProblem variable during the segue. see below
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destination = segue.destination as! ProblemVC
let cell = sender as! ProblemsTVCell
let label = cell.label!
switch label.text! {
case "Problem 1":
destination.currentProblem = Problem1()
case "Problem 2":
destination.currentProblem = Problem2()
case "Problem 3":
destination.currentProblem = Problem3()
case "Problem 4":
destination.currentProblem = Problem4()
default:
break
}
}
Is there a way to assign the Problem#() with a string, so I don't have to make hundreds of these cases? I have no idea what it would look like, and trying to google kept returning answers about #selectors. I don't know what it really would look like, but in my mind I'm thinking something like this.
destination.currentProblem = Class(name: "Problem4")
Let me know if what I'm asking isn't clear and I'll try to explain better.
Thank you in advance!
---EDIT---
Adding in my solution from the selected answer below.
So I changed the prepare function to this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destination = segue.destination as! ProblemVC
let cell = sender as! ProblemsTVCell
let label = cell.label!
let problemName = label.text!.replacingOccurrences(of: " ", with: "")
let problemClass = NSClassFromString("Project_Euler.\(problemName)")! as! ProblemClass.Type
destination.currentProblem = problemClass.init()
}
And to get the init() in my ProblemClass I made my class look like this:
class ProblemClass {
required init() {
return
}
func title() -> String {
return "Title"
}
func problem() -> String {
return "Problem #"
}
func question() -> [String] {
return ["No Question Yet"]
}
func answer() -> [String] {
return ["No Answer Code Entered Yet"]
}
}
Perhaps:
let problemNumber: Int = 1
var className = "AppName.Problem\(problemNumber)"
let problemClass = NSClassFromString(className) as! Problem.Type
destination.currentProblem = problemClass
I have been having some issues with my prepareForSegue call. Whenever I try to segue to the next view controller. It gets an error and crashes at the point where I am passing the tripLikes to the next view controller.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "toDetailScene") {
//Hooking up places-holder values
let viewController = segue.destinationViewController as! DetailViewController
let cell = sender as! CustomPFTableViewCell
viewController.tripName = cell.nameTextLabel.text!
viewController.tripAuthor = cell.authorTextLabel.text!
viewController.tripLikes = Int(cell.numLikes.text!)!
viewController.tripDescrip = cell.descriptionHolder
}
}
Each of the values that we are passing to are values in the destination view controller.
You're doing a lot of force-unwrapping with Int(cell.numLikes.text!)!. If any of those values are nil, your program will crash.
Why not try something safer, such as an if-let flow:
if let text = cell.numLikes.text {
if let textInt = Int(text) {
viewController.tripLikes = textInt
} else { // Int cannot be constructed from input
viewController.tripLikes = 0
}
} else { // cell.numLikes.text was nil
viewController.tripLikes = 0
}
This code is from the locations tableView view controller, where the locations are serialized from a Four Square API and I grab the data, passing it back the view controller where I create an event. The data is serialized correctly, populating the tableView and all, so I won't bother posting that for now, just the segue method to pass the data.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let indexPath = self.tableView.indexPathForSelectedRow
let item = self.responseItems![indexPath!.row]
var eventVC = CreateEventViewController()
if segue.identifier == "pushBackToEventVC" {
if let venue = item["venue"] as? NSDictionary {
let locationString = venue["name"] as! String
let location = venue["location"]
//get lat/long strings
print(location)
eventVC.updateWithLocation(locationString)
eventVC.updateWithGeoPoint(PFGeoPoint(latitude: locationLatitude, longitude: locationLongitude))
}
eventVC = segue.destinationViewController as! CreateEventViewController
//pass location coordinates
}
//the rest of the segue method
}
The update methods in the crete event view controller, when I put a breakpoint on these methods I can see the data has been passed correctly, and the location (a PFGeoPoint) works okay but the locationString (a string) throws a "Bad instruction error" although it does print it correctly to the console
func updateWithLocation(locationString: String) {
print(locationString)
self.locationLabel.text = locationString
}
func updateWithGeoPoint(venueLocation: PFGeoPoint) {
// print(venueLocation)
self.event?.location = venueLocation
self.eventLocation = venueLocation
print(self.eventLocation)
}
Any ideas? It's basically working but won't update the label with the string although I can see it's been passed correctly. Thanks for the help as always.
Try using this code block instead,
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "pushBackToEventVC") {
let detailViewController = ((segue.destinationViewController) as! CreateEventViewController)
let indexPath = self.tableView!.indexPathForSelectedRow!
detailViewController.locationString = venue["location"]
}
}
Im writing a table view controller using an array from Parse. I need to send data through the segue but I dont know why its always returning nil. I will have to send images and text, but for now im just taking the text from the label title1 to insert it into a variable type String named example.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toDetail" {
var detailScene = segue.destinationViewController as! detailViewController
let cell = sender as! UITableViewCell
let indexPath = tableView?.indexPathForCell(cell)
detailScene.example = self.timelineData[indexPath!.row].title1?.text
}
}
For the array I have used:
var timelineData : NSMutableArray = NSMutableArray()
And the function loaddata, that is used with the function viewDidAppear
func loaddata () {
timelineData.removeAllObjects()
var findTimelineData:PFQuery = PFQuery(className: "ii")
findTimelineData.findObjectsInBackgroundWithBlock{
(objects, error)->Void in
if error == nil{
for object in objects!{
let ii:PFObject = object as! PFObject
self.timelineData.addObject(ii)
}
let array:NSArray = self.timelineData.reverseObjectEnumerator().allObjects
self.timelineData = NSMutableArray(array: array)
self.tableView.reloadData()
}
}
}
Try this. It should at least get you to the point where you're grabbing the information from the correct cell. I'm assuming your timelineData array is full of text, so that's how I accessed it, by casting it as a String. If it is full of a different type of object you need to cast it differently.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toDetail" {
if let detailScene = segue.destinationViewController as? detailViewController {
if let indexPath = tableView.indexPathForSelectedRow()?.row {
var object = self.timelineData[indexPath] as! PFObject
var title = object["title"] as! String
detailScene.example = title
}
}
}
}
It could be that the return value from indexPathForCell is returning nil or a bad value. There are quite a few articles about this function being unreliable.
A common suggestion is to use indexPathForRowAtPoint(cell.center) instead.
There is definitely something wrong with your last line of code:
detailScene.example = self.timelineData[indexPath!.row].title1?.text
I assume that self.timelineData array that holds some data.
If your array contain String class you don't need to append .title1?.text part.
If your array contain UILabel class you need change line to
detailScene.example = self.timelineData[indexPath!.row].text
because UILabel have no property called title1.
In general I think this happened because class in self.timelineData array have no property called title1.
I am a newb to coding.
I had no issues with creating a segue prior to the Swift 1.2 update. I am getting the error of Cannot assign a value of type 'PFObject' to a value of type 'PFObject?' when I try the code below.
Can anyone help me figure this out ?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "PushToDetails" {
// Get the new view controller using [segue destinationViewController].
var detailScene = segue.destinationViewController as! DetailViewController
// Pass the selected object to the destination view controller.
if let indexPath = self.tableView.indexPathForSelectedRow() {
let row = Int(indexPath.row)
detailScene.currentObject = objects[row] as! PFObject
}
}
}
Your error said can not assign a value of type PFObject to a value of type PFObject!. See the difference of between the PFObject and PFObject!?
Because PFObject! is the type of Optional. Just like String and String!.They are the different types.
Like what you written for detailScene.currentObject = objects[row] as! PFObject, the currentObject is the Optional type probably if you check it, which leads detailScene.currentObject to the Optional type.
After that you assign the objects[row], the PFObject type, to detailScene.currentObject, the PFObject! type.
Maybe you can correct your code like this,
detailScene.currentObject! = objects[row] as! PFObject
Unwrapped the currentObject to the PFObject type.