Assigning an enumerator and it's reverse to a variable - ios

I'm stuck with this problem... I would like to enumerate in a regular for loop for one condition, and in reverse for another condition. Something like this:
var enumerator = 0..<length
if(stringPosition == .End) {
enumerator = reverse(enumerator) //[C.Generator.Element] is not convertible to 'Range<Int>'
}
for index in enumerator {
//do stuff
}
I'm getting a not convertible error there, and can't figure out how to proceed with that. I've tried different typecasting magic but that just doesn't work.
How should I sort out the conversion there?

Just casting to Array should work.
var enumerator = Array(0..<length) // <-- here
if(stringPosition == .End) {
enumerator = reverse(enumerator)
// then, enumerator.reverse() is better, I think
}
for index in enumerator {
//do stuff
}
I think, more (memory) efficient way is like:
let range = lazy(0..<length)
let enumerator = stringPosition == .End ? SequenceOf(range.reverse()) : SequenceOf(range)
for index in enumerator {
//do stuff
}
SequenceOf is a wrapper of any SequenceType. You can use this to store different sequence type to one variable.
for lazy(), see this answer or this.

Related

If condition issues in swift

I know its a basic question but I'm facing an issue related to it that i'm getting data from backend service.
From service I got [] in response. and I'm comparing it with my model class array. Mean if my model class array is qual to [], than I have to perform something.
My code is this,
let addonCategory = subCategoryModel![tappedIndex.section].items[tappedIndex.row].addonCategory
print(addonCategory as Any)
if addonCategory == "[]"{
print("Hello")
}
else {
print("Hi")
}
But when i compare it with [] brackets it shows error message that,
Cannot assign value of type 'String' to type '[AddonCategoryModel]?'
How can i compare it with brackets?
You need to check whether an array has an element or not.
if addonCategory.count > 0 {
// array has element
} else {
// array hasn't element
}
Alternatively you can use guard let or if let to check.
Using if let
if let addonCategory = subCategoryModel[tappedIndex.section].items[tappedIndex.row].addonCategory, addonCategory.isEmpty {
print(addonCategory)
print("Hello")
} else {
print("Hi")
}
You have to use array properties on addonCategory. It is not of type String
let addonCategory = subCategoryModel![tappedIndex.section].items[tappedIndex.row].addonCategory
print(addonCategory.count == 0 ? "Hello" : "Hi")
Here I have used ternary operator instead of traditional if-else syntax.

why I have to unwrap value before I use

A block is defined like below
// Declare block ( optional )
typealias sorting = (([Schedule], [String]) -> [Schedule])?
var sortSchedule: sorting = { (schedules, sortDescription) in
var array = [Schedule]()
for string in sortDescription
{
for (index, schedule) in schedules.enumerate()
{
if string == schedule.startTime
{
array.append(schedule)
break
}
}
}
return array
}
At some points, I am invoking a block by doing
let allSchedules = sortSchedule?(result, sortDescription())
for schedule in allSchedules // Xcode complains at here
{
..........
}
Im using ? because I want to make sure that if the block exists, then do something. However, Xcode complains for the for loop
value of optional type [Schedule]? not upwrapped, did you mean to use '!' or '?'?
Im not sure why because the return type of a block is an array which can have 0 or more than one items.
Does anyone know why xcode is complaining.
You are use ? in line let allSchedules = sortSchedule?(result, sortDescription()) not "for sure that if the block exists", but just for note, that you understand that it can be nil. Behind scene allSchedules have type Array<Schedule>?. And you can not use for in cycle for nil. You better use optional binding:
if let allSchedules = sortSchedule?(result, sortDescription())
{
for schedule in allSchedules
{
//..........
}
}

How to avoid If let in Swift before doing a for loop

I have this code on Swift:
let items = doSomethingFuncToGetDataWithOptionalResults()
if let items = items {
for item in items {
// so something...
}
}
Could anyone can help me to avoid if let ... in this case. It would be better if we could ignore if let in this case. I feel annoyed when writing this statements every time.
Regards,
Generally, if a function returns an optional then you can use
optional chaining to operate on the result only if it is not nil.
In your case of an optional array you can use
optional chaining and forEach():
doSomethingFuncToGetDataWithOptionalResults()?.forEach { item in
// do something with `item` ...
}
The forEach() statement will not be executed if the function
returns nil.
You can do something like this:
if let items = doSomethingFuncToGetDataWithOptionalResults() {
for item in items {
// so something...
}
}

How to prettify enum with arguments comparison in Swift?

This is what I have
let kind = //This returns one of the cases with it corresponding arguments
if kind == .didChangeValue(value: nil) {
//my Stuff
}
this is what I want:
if kind == .didChangeValue {
//my Stuff
}
Notice that:
This is happening because my enum has arguments, I already implemented how they should compare with each other and the value has no value to me.
So, I'm trying to get it to look more swifty and less like a RAW HACK
You can check an enumeration value with pattern matching:
if case .didChangeValue = kind {
// ...
}

Swift infinite loop while iterating array

I have a protocol defined as...
#objc protocol MyDatasource : class {
var currentReportListObjects:[ReportListObject] { get };
}
and some code to iterate the returned array (as an NSArray from ObjC) in Swift as...
if let reportListObjects = datasource?.currentReportListObjects {
for reportListObject:ReportListObject? in reportListObjects {
if let report = reportListObject {
// Do something useful with 'report'
}
}
}
If my reportListObjects array is nil, I get stuck in an infinite loop at the for-loop. Equally, if there is data in the array, it is iterated and 'something useful' is done until the end of my array is reached but the loop is not broken and continues infinitely.
What am I doing wrong? Or is there something blindingly obvious I'm missing here?
You've added a lot of extra Optionals here that are confusing things. Here's what you mean:
for report in datasource?.currentReportListObjects ?? [] {
// Do something useful with 'report'
}
If datasource has a value, this will iterate over its currentReportListObjects. Otherwise it will iterate over an empty list.
If you did want to break it out, rather than using ??, then you just mean this:
if let reportListObjects = datasource?.currentReportListObjects {
for report in reportListObjects {
println(report)
}
}
There's no need for the intermediate reportListObject:ReportListObject? (and that's the source of your problem, since it accepts nil, which is the usual termination of a generator).

Resources