I have problem with selectedRows() in SelectableSection.
Using Xcode 8, Swift 3, Eureka 2.0.0-beta.1.
func viewDidLoad() {
let branch_section = SelectableSection<ImageCheckRow<String>>("Branches", selectionType: .multipleSelection)
branch_section.tag = "branch_section"
for branch in branchList {
let branchStr = String(branch.id)
branch_section <<< ImageCheckRow<String>(branch.name){ row in
row.title = branch.name
row.selectableValue = branchStr
row.value = nil
}
}
}
#IBAction func saveFilter(_ sender: AnyObject) {
let branch_section = self.form.sectionBy(tag: "branch_section") as? SelectableSection<ImageCheckRow<String>>
invoiceParams["branches"] = branch_section!.selectedRows().map({$0.value!})
}
now i have problem with this line invoiceParams["branches"] = branch_section!.selectedRows().map({$0.value!})
map' produces '[T]', not the expected contextual result type
'AnyObject?'
What is problem here? This worked with previous versions on swift 2.3.
As far as I can see from SelectableSection.swift selectedRows returns an array of SelectableRow items:
public func selectedRows() -> [SelectableRow] {
return filter({ (row: BaseRow) -> Bool in
row is SelectableRow && row.baseValue != nil
}).map({ $0 as! SelectableRow})
}
So the map function also returns an array.
Your invoiceParams seems to be a dictionary that expects AnyObject? as value.
You can try to change the declaration of invoiceParams to something like var invoiceParams: [String: [Any]] = [:].
Since I don't know Eureka this is just a guess. But I hope it still helps a little.
Related
I Update old app to swift 3 and I have some migration errors.
on this part of code :
func done(_ request: URLRequest?, response: HTTPURLResponse?) {
let visibleCells = tableView.visibleCells as! [NewsStoryCell]
let cells = visibleCells.filter({ $0.news.thumbUrl == request?.URLString })
if let cell = cells.first {
cell.reloadThumbImage()
}
}
I have error:
Value of type 'URLRequest' has no member 'URLString'
on:
$0.news.thumbUrl == request?.URLString
It has indeed been changed in Swift 3
$0.news.thumbUrl = request?.url?.absoluteString
I have this code for Eureka library:
let section = SelectableSection<ImageCheckRow<String>, String>("Section:", selectionType: .MultipleSelection)
section.tag = "section"
for obj in arrList {
section <<< ImageCheckRow<String>(obj.name){ row in
row.title = obj.name
row.selectableValue = obj.name
row.baseValue = obj.id
row.value = nil
}
}
this shows selectable list, but next code doensn't work as it should:
#IBAction func saveAction(sender: AnyObject) {
let section = self.form.sectionByTag("section") as? SelectableSection<ImageCheckRow<String>, String>
for obj in section!.selectedRows() {
print(obj.baseValue)
}
}
this prints name field, but needs to print id(row.baseValue = obj.id).
Am i doing something wrong here?
I had been reviewing your code and I found this , seems that if we use SelectableSection we need to use selectableValue instead of baseValue for our proposes, but I think that this is an bug from Eureka because selectableValue and baseValue are the same although we set different values
you can mitigate this using row.selectableValue = obj.id instead of row.selectableValue = obj.name
Edited
try this for Int values in selectableValue replace
<ImageCheckRow<String>, String> for <ImageCheckRow<Int>, Int>
also replace section <<< ImageCheckRow<String>(obj.name) for section <<< ImageCheckRow<Int>(obj.name)
and finally adjust saveAction as I do
#IBAction func saveAction(sender: AnyObject) {
let section = self.form.sectionByTag("section") as? SelectableSection<ImageCheckRow<Int>, Int>
for obj in section!.selectedRows() {
print(obj.baseValue)
}
}
this works for me with Int on selectableValue
The problem is this
public final class ImageCheckRow<T: Equatable>: Row<T, ImageCheckCell<T>>, SelectableRowType, RowType {
public var selectableValue: T?
required public init(tag: String?) {
super.init(tag: tag)
displayValueFor = nil
}
}
the selectableValue is of type a pattern for any type you pass in declaration that is why <ImageCheckRow<Int>, Int> resolve the problem with Int
I hope this helps you, regards
I try to use Firebase framework and use it in my app, but I have a problem with undestanding, how to retrieving data from firebase and save it in my own array. Firebase structure is very simple and looks like that:
Now my code looks like that:
`var rootRef = Firebase(url: "https://mathgamepio.firebaseio.com/")
var array:[String]?
var count: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
rootRef.observeEventType(.ChildAdded) { (snap: FDataSnapshot!) -> Void in
self.count++
let math = snap.value["math"] as! String
print(self.count)
print(math)
self.array?.append(math)
print(self.array)
print("--------")
}`
The result of this operation looks like that:
self.array.append doesn't work and is nil always. How to add this data to my own array?
It looks like your array is never initialized, so self.array? will always skip append.
One solution is to check of the array exists:
if (self.array?.append(math)) == nil {
self.array = [math]
}
There are probably more ways to solve this, but I modified the answer from this question: Adding elements to optional arrays in Swift
Update
Even easier is to simply create the array, before using it:
var array:[String]?
var count: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
self.array = [];
rootRef.observeEventType(.ChildAdded) { (snap: FDataSnapshot!) -> Void in
self.count++
let math = snap.value["math"] as! String
print(self.count)
print(math)
self.array?.append(math)
print(self.array)
print("--------")
}
}
Or simply not mark the array as optional:
var array:[String] = []
var count: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
rootRef.observeEventType(.ChildAdded) { (snap: FDataSnapshot!) -> Void in
self.count++
let math = snap.value["math"] as! String
print(self.count)
print(math)
self.array.append(math)
print(self.array)
print("--------")
}
}
TIL I learned some basic Swift syntax. :-)
I have a weird issue trying to validate user input. I'm using a wrapper for a form framework and I want it to be able to validate user input.
The trouble is, when I call the closure with the userValue argument, it ends up being nil and all checks return false:
class FormRowWrap {
var tag: String
var row: AnyObject
var verification: (value: Any?) -> Bool
init(tag: String, row:AnyObject, verification:(Any?) -> Bool) {
self.tag = tag
self.row = row
self.verification = verification
}
}
class InsertViewController: FormViewController {
let rows = [
{
let tag = "Fuel Name"
let row = FormRowWrap(tag: tag,
row:TextRow(tag) {
$0.title = tag
// $0.value = last known user default
},
verification:({(value: Any?) -> Bool in
if let thing = value as? String {
//^----- the value in a **breakpoint here is nil**
//
if !thing.isEmpty {
return true
}
}
return false
}))
return row
}() as FormRowWrap,
{
let tag = "Price"
let row = FormRowWrap(tag: tag,
...
func formValuesAreValid(values: [String: Any?]) -> Bool {
var result = false
for rowWrap in self.rows {
let userValue = values[rowWrap.tag]
print("userValue \(userValue) forTag: \(values[rowWrap.tag])")
// ^---- this prints userValue **Optional(Optional("Ghh")) forTag: Optional(Optional("Ghh"))**
let entryIsValid = rowWrap.verification(value: userValue)
if (!entryIsValid) {
result = false
return result
}
}
result = true
return result
}
If I run rowWrap.verification(value:"test") it returns true, so I think it's an issue about properly unwrapping values.
Your function needs an Optional but userValue is an Optional inside another Optional:
Optional(Optional("Ghh"))
So when you force unwrap it with
let entryIsValid = rowWrap.verification(value: userValue!)
what happens actually is that you unwrap the first layer and get back an Optional:
Optional("Ghh")
which is what your function signature
(value: Any?) -> Bool
needs.
About why it's wrapped twice:
with
formValuesAreValid(values: [String: Any?])
the values in the values dictionary are Optionals, and then when you access the dictionary:
let userValue = values[rowWrap.tag]
you get yet another Optional - because accessing a dictionary always returns an Optional, so in this case values[rowWrap.tag] returns an "Optional Optional".
Then somewhere else you unwrap once thinking you'll get the value if let thing = value as? String but you get the inner Optional instead and your next check fails.
Found a way to make it work by force unwrapping the "userValue":
let entryIsValid = rowWrap.verification(value: userValue!)
I still don't understand why this works and why it doesn't work with the argument as wrapped optional.
I have been trying to fix all my code since swift 2.0 update. I have a problem that seems to be the way tuples work now:
public func generate() -> AnyGenerator <(String, JSON)> {
switch self.type {
case .Array:
let array_ = object as! [AnyObject]
var generate_ = array_.generate()
var index_: Int = 0
return anyGenerator{
if let element_: AnyObject = generate_.next() {
return ("\(index_++)", JSON(element_))
} else {
return nil
}
}
case .Dictionary:
let dictionary_ = object as! [String : AnyObject]
var generate_ = dictionary_.generate()
return anyGenerator{
if let (key_: String, value_: AnyObject) = generate_.next() {
return (key_, JSON(value_))
} else {
return nil
}
}
default:
return anyGenerator{
return nil
}
}
}
Specifically the line:
if let (key_: String, value_: AnyObject) = generate_.next()
Is throwing the error: Tuple pattern element label 'key' must be '_'
I tried to make that change already, but I didnt work...
Any ideas?
The problem is: We cannot use type annotation inside of tuple patterns anymore.
In the release notes:
Type annotations are no longer allowed in patterns and are considered part of the outlying declaration. This means that code previously written as:
var (a : Int, b : Float) = foo()
needs to be written as:
var (a,b) : (Int, Float) = foo()
if an explicit type annotation is needed. The former syntax was ambiguous with tuple element labels. (20167393)
So, you can:
if let (key_, value_): (String, AnyObject) = generate_.next() {
But in this case, you could omit : (String, AnyObject):
if let (key_, value_) = generate_.next() {