Error after update to Xcode 7 - arrays

I have browsed through some of the other posts relating to upgrade and errors but I did not see one that I thought answered my issue. The following code was working yesterday but today after upgrading, I am getting an error:
enteredDataArrayOne = [enterDate.text, enterSeason.text, enterSport.text, enterDispTo.text]
The error is as follows:
Cannot assign a value of type '[String?]' to a value of type 'NSArray'
I am very new to coding. I have gone back to review my instructional materials and it is my understanding that building an array of strings is allowed. The values that make up the array enteredDataArrayOne are the values of text fields entered by the user.
Here are the other two places that this array is used:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "goToDispenseScreenTwo") {
let DestViewControllerTwo = segue.destinationViewController as! DispenseScreenTwoViewController;
DestViewControllerTwo.toPassTwo = enteredDataArrayOne as! [String]
}
}
and then later in the same method where the array is built:
if blankData != 1 {
//add code to pass data to next veiw controller
enteredDataArrayOne = [enterDate.text, enterSeason.text, enterSport.text, enterDispTo.text]
print(enteredDataArrayOne)
self.appIsWorking ()
performSegueWithIdentifier("goToDispenseScreenTwo", sender: self)
activityIndicator.stopAnimating()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
}
I appreciate any suggestions.

This should fix your error
enteredDataArrayOne = [enterDate.text!, enterSeason.text!, enterSport.text!, enterDispTo.text!]

Related

Passing a Model between View Controllers

I am struggling to pass a model of data from one controller to the next. I am sure I am just missing something very simple but hoping I can get some help.
Below I create the code to select all the data from the row that was selected:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
print(indexPath.row)
let passingData = arrivals[indexPath.row]
print(passingData)
let controller = storyboard?.instantiateViewController(withIdentifier: "FlightInfoVC") as! FlightInfoViewController
controller.flightDataPassedIn = passingData
//Code incomplete - Will add execution to show VC
}
That print statement is reflected below:
Now where I am struggling is to get that data to go to my next view controller. Setting the array of data in my new VC doesn't seem to work because it is expecting a type of 'FlightModel' but I cannot seem to figure out how to declare that. I have tried this but I cannot convert type [Any] to 'FlightModel'
var flightDataPassedIn: FlightModel = []
Appreciate any help you can give!
It sounds like the issue is that you're trying to initialize flightDataPassedIn with a value of [], which is of incompatible type [Any].
If you're okay with the flightDataPassedIn property on FlightInfoViewController being optional, that might be the most straightforward solution. It would automatically be initialized to nil, so would not require you to set an initial value - just declare it like this:
var flightDataPassedIn: FlightModel?
If you don't want it to be optional, initialize it to a default value of type FlightModel (add an initializer to FlightModel if necessary) and overwrite it with passingData from the parent ViewController.
Hope this helps!
The issue was that I was not passing the data via the main required function that everyone uses Prepare for segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "TrackingToInfo" {
if let destinationVC = segue.destination as? FlightInfoViewController {
destinationVC.flightDataPassedIn = readyToPass
}
}
}
Within the tableview I had to set the data to a var in my currentVC of type FlightModel? then the data passed

Value of type 'Article' has no subscripts

So I know there are many other similar questions about this type of problem, but my fried brain cells genuinely cannot, for the life of me, figure out how to solve the following error: "Value of type 'Article' has no subscripts". I tried applying a lot of other solutions from other Stack Overflow posts, but the issue still persists.
Brief overview about my project: I'm trying to use a news API for some intended application. However, there are a lot of duplicate news articles within my array -- that I'm trying to remove.
So here is my API Call, works like a charm:
let topic_endpoint = "blah blah endpoint + secret api_key"
guard let url = URL(string: topic_endpoint) else {
print("Error creating url object")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request){ data, _, error in
if error != nil {
print((error?.localizedDescription)!)
return
}
if let data = data {
let response = try! JSON(data: data)
for index in response["articles"]{
let id = index.1["publishedAt"].stringValue
let title = index.1["title"].stringValue
let description = index.1["description"].stringValue
let image = index.1["urlToImage"].stringValue
let url = index.1["url"].stringValue
DispatchQueue.main.async {
//print(response)
if self.getSentimentFromBuildInAPI(text: title) == 1{
self.articles.append(Article(id: id, title: title, description: description, image: image, url: url))
}
}
}
}
}.resume()
And here is my removeDuplications function:
I first iterate throughout the entire array of type Article, and then add the title into a new array called 'usedNames'. At every step, I check to see if any other title is already used and added, and if it does I skip over that value to my array again. Hopefully, I explained this well, please let me know if I need to change anything.
func removeDuplications(){
//haven't used title yet, this is was just something I tried looking off another stackoverflow post.
guard let title = self.articles["title"] as? [[String: Any]] else{
print("error: dictionary type not recognized")
}
for index in self.articles{
if(!self.usedNames.contains(index["title"])){ //<----------this is where I get my error: 'Value of type 'Article' has no subscripts'
//Tried reappending the new titled articles (below) into my Published dictionary/array, is also showing the same issue as above
//self.articles.append(Article(id: index["id"], title: index["title"], description: index["description"], image: index["image"], url: index["url"]))
self.usedNames.append("title")
}
}
}
Thanks so much for helping me with this, really appreciate it:)
It's likely because in your
for index in self.articles
index (which is of type Article) can not be used as a dictionary, which is what you are doing when you do index["title"]
Instead, you have to do:
index.title
instead of
index["title"]

How do I fill an array of data with CoreData data?

I am learning to use SwiftUI with Core Data.
I am trying to fill a Line Chart with saved weight data like below:
LineView(data: [0, 32, 445, 56, 99])
I’ve gotten as far as this but im getting an error on the "var locations = ..." line saying "Type of expression is ambiguous without more context"
var fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "UserWeight")
var locations = mocW.executeFetchRequest(fetchRequest, error: nil) as [UserWeight]
for weight in weights {
print(weights.userWeight)
}
Any help on this and how i would populate the line chart with this data would be greatly appreciated!
For SwiftUI, I suspect that you are attempting to achieve the following...
struct YourView: View {
#FetchRequest(entity: UserWeight.entity(),
sortDescriptors: []
) var weights: FetchedResults<UserWeight>
var body: some View {
ForEach(weights) { weight in
Text(weight.userWeight)
}
}
}
Core Data entities confirm to the Identifiable protocol, so you'e able to drop the id: parameter in the ForEach structure...
ForEach(weights) { weight in
Otherwise you'd need to use...
ForEach(weights, id: \.self) { weight in
Note: As an aside, it would help us if you could provide more detail in your questions in the future. The more information you provide, the easier it is for the community to understand your issue and provide a suitable response. Remember that your question and our answers may not only help you, but also help others in the future as they visit the site looking for answers to their own problems.
How do I ask a good question?
if let appDelegate =
UIApplication.shared.delegate as? AppDelegate {
let managedObjectContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<Memory>(entityName: "Memory")
let sortDescriptor = NSSortDescriptor(key: "rating", ascending: false)
var predicate = NSPredicate(format: "mediaType == %#", "image")
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = [sortDescriptor]
do {
result = try managedObjectContext.fetch(fetchRequest)
} catch {
}
}
"result" is an array of, in my case, Memory objects which are instances of NSManagedObject. To access properties and populate views I do this:
for memory in result {
let value = memory.entityPropertyName
}
I think this should be enough to get your started, let me know if you have more questions.
If UserWeight is a subclass of NSManagedObject, you should declare your fetch request as
var fetchRequest = NSFetchRequest<UserWeight>(entityName: "UserWeight")
Or else as
let fetchRequest: NSFetchRequest<UserWeight> = UserWeight.fetchRequest()
Then you can use the fetch like this, and the type of locations will be Array<UserWeight>.
let locations = try context.fetch(fetchRequest)
I'm not sure where executeFetchRequest(fetchRequest, error: nil) comes from-- it's not a function defined by NSManagedObjectContext in Swift. It resembles the Objective-C version of the function, but in Swift it's different.

How to order PFObjects based on its creation date?

I have some user comments stored in a database (parse-server) that I would like to would like to display on my viewController's viewDidLoad(). I can easily pull the comment objects as follows:
super.viewDidLoad()
func query(){
let commentsQuery = PFQuery(className: "Comments")
commentsQuery.whereKey("objectId", equalTo: detailDisclosureKey)
commentsQuery.findObjectsInBackground { (objectss, error) in
if let objects = objectss{
if objects.count == 1{
for object in objects{
self.unOrderedComments.append(object)
}
}
}
}
}
This query dumps all of the of the comments in the unOrederedComments array. Each comment is added to the database with a createdAt property automatically being added relating the exact time of its creation. This property is a string with (as an example) the form: "2017-08-13T19:31:47.776Z" (the Z at the end is at the end of every string... not exactly sure why its there but its constant). Now, each new comment is added in order to the top of database and thus any queried result should be in order regardless. However, I would like to make sure of this by reordering it if necessary. My general thought process is to use .sorted, but I cannot figure out how to apply this to my situation
func orderComments(unOrderComments: [PFObject]) -> [PFObject]{
let orderedEventComments = unOrderedEventComments.sorted(by: { (<#PFObject#>, <#PFObject#>) -> Bool in
//code
})
}
This is the generic set up but I cannot, despite looking up several examples online figure out what to put in the <#PFObject#>'s and in the //code. I want to order them based on the "createdAt" property but this is not achieved via dot notation and instead requires PFObject["createdAt"] and using this notation keeps leading to error. I feel as so though I may need to set up a custom predicate but I do not know how to do this.
I was in the same situation, what I did was to first create an array of structs with the data I downloaded where I turned the string createdAt into a Date, then used this function:
dataArrayOrdered = unOrderedArray.sorted(by: { $0.date.compare($1.date) == .orderedAscending})
(.date being the stored Date inside my array of strcuts)
Try this code, notice that I assumed you have a variable name called ["Comments"] inside your Parse database, so replace if necessary. Also, I realised that createdAt it's in Date format, so there was no need to change it from String to Date, chek if it works the same for you, if it doesn't refer to this: Swift convert string to date.
struct Comment {
var date = Date()
var comment = String()
}
var unOrderedComments: [Comment] = []
var orderedComments = [Comment]()
override func viewDidLoad() {
super.viewDidLoad()
query()
}
func query(){
let commentsQuery = PFQuery(className: "Comments")
commentsQuery.findObjectsInBackground { (objectss, error) in
if let objects = objectss{
if objects.count >= 1{
for object in objects{
let newElement = Comment(date: object.createdAt!, comment: object["Comments"] as! String)
self.unOrderedComments.append(newElement)
print(self.unOrderedComments)
}
}
self.orderedComments = self.unOrderedComments.sorted(by: { $0.date.compare($1.date) == .orderedAscending})
print(self.orderedComments)
}
}
}

Getting array objects into NSTableView

I want to catch information from an array and display it into my NSTableView. I'm unsure what I need to do for that (I am very new to Swift and programming in general).
My table view looks like this:
I want to get value name from my array and display it in the name table with the NSTableView. I've found this tutorial on Ray Wenderlich but the code is very outdated and I don't want to use old things within my project which might not work anymore in newer OS versions.
It seems that I need an [NSTableViewDataSource numberOfRows][3] and viewFor.
Any examples on how to do this - maybe someone made this a few weeks ago with Swift 3? :D
The information within the array will be generated by the following:
var devices = [Device]()
let quantityDevices = quantityData.intValue
for i in 0...quantityDevices-1 {
let newDevice = Device()
print("created new device")
newDevice.name = titleData.stringValue + "-\(i)"
devices.append(newDevice)
}
print("now we have \(devices.count) devices in our array")
}
The important part of the code you need is the DataSource delegate functions:
extension ViewController : NSTableViewDataSource {
func numberOfRows(in tableView: NSTableView) -> Int {
return devices.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
// 1 - get the device for this row
guard let device = devices[row] else {
return nil
}
// 2 - configure the cell with the device data
return nil
}
There is an example here on StackOverflow that should give a better example

Resources