I have a problem with a Swift code:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.backgroundColor = UIColor.clear
cell.detailTextLabel?.backgroundColor = UIColor.clear
if indexPath.row % 2 == 0 {
cell.backgroundColor = UIColor(white: 1, alpha: 0.1)
} else {
cell.backgroundColor = UIColor(white: 1, alpha: 0.2)
}
// Load feed iamge.
let url = NSURL(string:feedImgs[indexPath.row] as! String) //** The problem - Thread 1: Fatal error: Index out of range**
let data = NSData(contentsOf:url! as URL)
var image = UIImage(data:data! as Data)
image = resizeImage(image: image!, toTheSize: CGSize(width: 80, height: 80))
let cellImageLayer: CALayer? = cell.imageView?.layer
cellImageLayer!.cornerRadius = 35
cellImageLayer!.masksToBounds = true
cell.imageView?.image = image
cell.textLabel?.text = (myFeed.object(at: indexPath.row) as AnyObject).object(forKey: "title") as? String
cell.textLabel?.textColor = UIColor.white
cell.textLabel?.numberOfLines = 0
cell.textLabel?.lineBreakMode = .byWordWrapping
cell.detailTextLabel?.text = (myFeed.object(at: indexPath.row) as AnyObject).object(forKey: "pubDate") as? String
cell.detailTextLabel?.textColor = UIColor.white
return cell
}
How can I solve that?
halfer
19.7k17 gold badges95 silver badges183 bronze badges
asked May 18, 2018 at 9:52
3
You are accessing two arrays in cellForRowAt indexPath
method, first is feedImgs
and second is myFeed
.
If both array count is same then it will not crash, if both array counts are different then it will crash for Index Out of range
for one of the array.
For example, feedImgs
have 4 objects in it and myFeed
have 5 objects then it will crash at 4th index in feedImgs
array and give you the reason Index Out of range
.
Hope this helps to you.
answered May 18, 2018 at 9:56
PPLPPL
6,2761 gold badge10 silver badges29 bronze badges
1
Index out of range mean that you need to get index from array where index greater than array items
so you use index in three places check them
let url = NSURL(string:feedImgs[indexPath.row] as! String)
,
cell.textLabel?.text = (myFeed.object(at: indexPath.row) as AnyObject).object(forKey: "title") as? String
and
cell.detailTextLabel?.text = (myFeed.object(at: indexPath.row) as AnyObject).object(forKey: "pubDate") as? String
So to avoid this issue Make is safe with if condition
(if indexPath.row < feedImgs.count{
let url = NSURL(string:feedImgs[indexPath.row] as! String)
}
(if indexPath.row < myFeed.count){
cell.detailTextLabel?.text = (myFeed.object(at: indexPath.row) as AnyObject).object(forKey: "pubDate") as? String
cell.textLabel?.text = (myFeed.object(at: indexPath.row) as AnyObject).object(forKey: "title") as? String
}
answered May 18, 2018 at 10:02
By | Last Updated on January 5th, 2022 12:18 pm | 5-min read
Off by one errors, like “Array index out of range”, happen in programming when we’ve got the boundaries of things wrong. In this tutorial, you’ll learn what an off-by-one error is and how you can solve it with Swift programming.
Here’s what we’ll get into:
- What an off-by-one error is and how to solve it
- Swift’s dreaded Array index out of range error
- Why the fencepost problem is crucial to understand
- Approaches to find and solve the OBOE in Swift
- Including mandatory puns about being off by one…
A popular quote from Jeff Atwood, author of Coding Horror, is this:
There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
Off-by-one errors (OBOEs) happen when a loop iterates one time too many, or one too few. These errors can also happen when an array is zero-indexed, and you assume that it starts at 1. An off-by-one error is considered a boundary problem, that is, a problem that occurs around the boundaries of a set of data.
Let’s take a look at an example. Imagine we’re working on a bit of code, and we want to create a loop that iterates some code exactly 5 times.
for i in 0…5 {
print(i)
}
Run the above code. What happens? For some reason – accidentally or otherwise – we’ve erroneously started counting our loop at 0. Because we’ve used the closed range operator … with 0 and 5, our loop iterates from 0 to 5, including 5. As such, the number of times the loop iterates is… 6!
It’s not likely that you make such a mistake deliberately, so the code example is a bit contrived. Consider however what happens to the loop when you change the following bits of code:
- 0 into 1 — how many iterations do you get?
- … into ..< — which numbers are included in the loop, now?
The way Swift implements for loops, with for in, actually prevents us from easily making off-by-one mistakes. The default 1…5 syntax follows natural language: a loop from 1 to 5 — in my mind, that’s 1-2-3-4-5.
But, check out how the above code works for programming languages with C-style loops:
for(i = 0; i < 5; i++) { print(i)
}
The above code runs exactly 5 times, printing out the numbers 0 to 5 (including). However, if you change < into <=, the loop runs 6 times. When you accidentally start at 1, the code only runs 4 times. It’s easy to make a typo, right? That’s the nature of off-by-one errors!
Let’s check out another example, with a while loop in Swift:
var i = 1
while(i <= 5) { i += 1 print(i)
}
// Output: 2 3 4 5 6
The above code iterates 5 times, and it has two off-by-one errors. Based on the i = 1 and i <= 5 boundaries, you’d think that this code runs from 1 to 5. It doesn’t, however. Why?
- The condition in the while statement is executed at the start of each iteration. Because the condition is i <= 5, the loop will stop executing after i equals 6, i.e., when i <= 5 is false.
- The placement of i += 1 is disadvantageous. Because i = 1, the first iteration will immediately execute i += 1, so i equals 2, prior to the first print() statement.
As a result, the printed values of i are 2-3-4-5-6. The loop runs 5 times, but the loop’s values are completely different from what you’d expect!
Off-by-one errors are all around us. Personally, I’m always confused about the “first floor” in an elevator. In The Netherlands, the first floor is called “1”, and the ground floor is called “BG”. Contrast this with Norway, where I’ve lived for a while. Their first floor is the actual first floor, i.e. the ground floor, and the second floor — what we call first floor — is called “2”. If I’m not mistaken, the same confusion can happen with American English and British English first floor/ground floor conventions. Lots of opportunity to end up on a floor too high or too low! “I went to a first floor convention, and ended up on the wrong floor!”
In the previous section, we’ve looked at how many times a loop iterates. In every example, the loop did repeat 5 times. It doesn’t matter much if it iterates 1-2-3-4-5 or 0-1-2-3-4, as long as you’ve got the number of iterations you expect (5).
But what happens when you need to use the ordinal index number of the iteration? That’s where off-by-one errors happen with arrays, and you get that dreaded Array index out of range error.
Let’s take a look at an example.
let names = [“Arthur”, “Trillian”, “Ford”, “Zaphod”, “Marvin”]
for i in 0…names.count {
print(names[i])
}
In the above code, we want to iterate over an array of strings. The goal is to print out every name in the array by using the array index i. Smart as we are, we’ve figured out that we can get the number of items in an array with the .count property. However, there’s an off-by-one error in the above code!
When you run it, you’ll get this error message back from Swift:
Thread 1: Fatal error: Array index out of range
Here’s why:
- The for in syntax with the m…n range syntax uses a lower bound m and an upper bound n. Loop from 1 to 5, with 1…5.
- Arrays in Swift are zero-indexed, meaning that their first index number is 0. The index of “Arthur” in the above array is 0.
- So far so good! We’re starting our loop with for i in 0…, so we’re starting at zero.
- The value of names.count is equal to the number of items in the array, which is 5.
- In your head, replace the names.count in 0…names.count with 5. What happens? We’re actually looping from 0 to 5 — so the loop repeats 6 times!
The loop repeats one too many times. As a result, you’ll get an Index out of range error. The index number 5 does not exist in the array, because the array only has indices 0-1-2-3-4. The index is “out of range”.
How can we solve this? In one of two ways:
- Use the half-open range operator ..<. This will make the loop iterate from m to n, but not including n. So, 0-1-2-3-4 instead of 0-1-2-3-4-5.
- Subtract 1 from the size of the array, with for i in 0…names.count-1. This will make the range’s upper bound equal to the last index of the array.
This off-by-one error for arrays is often called the fencepost error, which we’ll discuss next.
The Fencepost Error
Here’s an interesting question for you:
If you build a straight fence 30 meters long with posts spaced 3 meters apart, how many posts do you need?
You might be inclined to answer “10”, because 30 divided by 3 is 10. After all, the posts are spaced 3 meters apart. What you’re forgetting, however, is that last post — the right answer is “11”!
This is called the fencepost error. It’s based on the idea that sometimes we count the posts in a fence, and at other times, we count the sections of fence themselves.
Another example involves making a hotel booking. You’re checking in on Monday, and checkout happens on Friday. How many days and nights are you staying?
5 days, 4 nights. Monday to Friday equals 5 days (sections) and 4 nights (fenceposts). You’re always charged per night in a hotel. Consider that code you wrote accidentally counts the days from Monday to Friday, and you end up charging one “night” too many!
The fencepost problem illustrates that off-by-one errors always concern the boundaries of things, and where those borders are. If we go back to that array of names, we assert that, when an array starts at index 0, its last index is length – 1. When an array has indices from m to n inclusive, the size of the array is n + 1.
How do you solve off-by-one errors? It’s important to establish a starting point or convention, first.
- Array indices in Swift start at 0
- “A convention we’ll use for this algorithm, is starting at 1.”
- The first day of the year is January 1st
- Monday corresponds to 0, so that Sunday is 6
- Are we counting fence sections or fenceposts?
Then, you can build awareness around syntax that concerns boundaries:
- Ranges in Swift use the m…n (inclusive) or m..
- Conditional loops can use < and >, or <= and >=, and they differ
Based on those principles, you’re equipped to tackle any off-by-one error that comes your way. Does your code accidentally skip the last item in an array? Are you trying to access a post-last array item that doesn’t exist? Is the outcome of your algorithm always off by one? Check the above syntax and principles, and chances are that you’ll find that off-by-one error.
In this tutorial, we’ve discussed a common cause of bugs in programming: the off-by-one error, or OBOE. As it turns out, it’s easy to accidentally incorporate this bug into your code. Fortunately, it’s quite easy to solve, too. Awesome!
And of course, we can also just joke around, admit that we make mistakes, and remind ourselves that off-by-one errors just happen:
There are two kinds of people in the world. 1. People who understand off-by-one errors.
Create Your App Now
Related Articles
- Should You Learn SwiftUI or UIKit?
- Introduction to Grand Central Dispatch with Swift
- What are The Benefits of Creating an Insurance Chatbot?
- What is Web3, and Why is it Important? [The Ultimate Guide to Web 3.0]
- Here’s How Location-Based Marketing can help your App Marketing Strategies
- Amazon Logo History: What Message Is Hidden in Amazon Logo?
- How to Set NFT Profile Picture on Twitter and Instagram?
- The Magical 10x Developer – How?
- How to Create a Chatbot in Salesforce?
- How to write the last working day email (Sample goodbye email to coworkers)
I want to launch Lottie animation on the simulator.
Problem i am experiencing
In the following code, onboardLabel.text = onboardStringArray [i]
Thread 1: Fatal error: Index out of range
The warning has come out.
func setUpScroll () {
scrollView.contentSize = CGSize (width: view.frame.size.width * 5, height: view.frame.size.height)
for i in 0 ... 3 {
let onboardLabel = UILabel (frame: CGRect (x: CGFloat (i) * self.view.frame.size.width, y: self.view.frame.size.height/3, width: scrollView.frame.size.width, height: scrollView.frame.size.height))
onboardLabel.font = UIFont.boldSystemFont (ofSize: 15.0)
onboardLabel.textAlignment = .center
onboardLabel.text = onboardStringArray [i]
scrollView.addSubview (onboardLabel)
}
}
All code for .swift files
Here is all the code for this Swift file.
import UIKit
import Lottie
class tyutoriaruViewController: UIViewController {
var onboardStringArray = ["first1", "first2", "first3", "first4"]
@IBOutlet var scrollView: UIScrollView!
var animationArray = ["Let's post your favorite selfie!", "If i like the posted selfie ...", "You will get a token!", "! Use it! "]
override func viewDidLoad () {
super.viewDidLoad ()
scrollView.isPagingEnabled = true
setUpScroll ()
for i in 0 ... 3 {
let animationView = AnimationView ()
let animation = Animation.named (animationArray [i])
animationView.frame = CGRect (x: CGFloat (i) * self.view.frame.size.width, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height )
animationView.animation = animation
animationView.contentMode = .scaleAspectFit
animationView.loopMode = .loop
animationView.play ()
scrollView.addSubview (animationView)
}
}
func setUpScroll () {
scrollView.contentSize = CGSize (width: view.frame.size.width * 4, height: view.frame.size.height)
for i in 0 ... 3 {
let onboardLabel = UILabel (frame: CGRect (x: CGFloat (i) * self.view.frame.size.width, y: self.view.frame.size.height/3, width: scrollView.frame.size.width, height: scrollView.frame.size.height))
onboardLabel.font = UIFont.boldSystemFont (ofSize: 15.0)
onboardLabel.textAlignment = .center
onboardLabel.text = onboardStringArray [i]
scrollView.addSubview (onboardLabel)
}
}
}
You may be mistaken for the basics because i am a beginner in programming. I look forward to working with you.
The simulation will be as follows.
] (9014af9b4087e0011b0a7c69c985e6fe.png)
In this post, we will see how to resolve Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range, how do i solve this?
Question:
I am new to coding and SwiftUI in general, I am coding a crypto portfolio app
I am doing the candle stick chart using apple chart API, get my API data fetched.
sorry if my code is messy.
JSON from market data rest API
the “60” means the number of seconds and so on till the number of sec of 1 week with prices of the coin in the squared brackets
here is my data model
here is my CoinNetworkManager where i do the networking
printing above get me this in the console
19727.0
[1662278400.0, 19701.4, 19727.0, 19631.7, 19637.1, 24.43309418, 480989.386594268]
but when i try to put it in a chart i where i assume i will access through the index of the data array but i get: Fatal error: Index out of range
how do i properly access the dict/ array [String:[Double]], was i formatted incorrectly or the method?
thank you in advance everyone 🙏
Chart code here
Best Answer:
In ContentView
inside Chart
, try this approach where you check the price
(an array of Double) size, to solve your index out of range error:
Chart(coinNM.result.result?[“60”] ?? [[0.4],[0.5]], id: .self) { price in
if price.count > 1 { // <— here
RectangleMark(x: .value(«Close Time», price[0]),
yStart: .value(«Low Price», price[1]), // <— because
yEnd: .value(«High Price», price[0]), width: 4)
}
}
[/code]
Or this, depending on what you want to show:
Chart(coinNM.result.result?[“60”] ?? [[0.4],[0.5]], id: .self) { price in
if price.count > 3 { // <— here
RectangleMark(x: .value(«Close Time», price[0]),
yStart: .value(«Low Price», price[3]), // <— because
yEnd: .value(«High Price», price[2]), width: 4)
}
}
[/code]
If you have better answer, please add a comment about this, thank you!
Source: Stackoverflow.com
Некоторые из них не дают мне 100% смысла без контекста, но на основе того, что я могу сделать, кажется, лучшим решением для вас будет использование одного словаря для доступа к SKSpriteNode
а также направления и скорости. Для этого вы можете создать пользовательский объект или просто использовать простой кортеж.
После инициализации словаря и заполнения его объектами вы можете получить доступ к одному значению в словаре, чтобы получить все данные, необходимые для вашей функции createEnemy
. Это может выглядеть примерно так:
var tracks = [Int : (node: SKSpriteNode, direction: CGFloat, velocity: CGFloat)]()
func setupTrack() {
for i in 0 ... 9 {
if let track = self.childNode(withName: "(i)") as? SKSpriteNode {
//Get direction and velocity here, if initial value is known
//Setting to 0 for now
tracks[i] = (node: track, direction: 0, velocity: 0)
}
}
}
func createEnemy(forTrack track: Int) -> SKShapeNode? {
guard let thisTrack = tracks[track] else { return nil }
let enemySprite = SKShapeNode()
enemySprite.name = "ENEMY"
enemySprite.path = CGPath(roundedRect: CGRect(x: 0, y: -10, width: 20, height: 20), cornerWidth: 10, cornerHeight: 10, transform: nil)
let enemyPosition = thisTrack.node.position
let left = thisTrack.direction
enemySprite.position.x = left ? -50 : self.size.height + 50
enemySprite.position.y = enemyPosition.y
enemySprite.physicsBody?.velocity = left ? CGVector(dx: thisTrack.velocity, dy: 0) : CGVector(dx: 0, dy: -thisTrack.velocity)
return enemySprite
}
Это не позволит вам выйти за пределы вашего массива. Обратите внимание на это: поскольку вы выполняете цикл с жестко закодированным диапазоном 0… 9, но вы необязательно добавляете элементы к этому Array
(в случае, если ваша if let track
работает), вы не гарантируете, что элемент «track» с имя «7» соответствует 7-му индексу в вашем массиве. Это еще одна причина, по которой Dictionary
более безопасен. Кроме того, кажется, что вы поддерживаете 3 отдельных массива (дорожки, directionArray и velocityArray), которые, похоже, подвержены ошибкам по той же причине, которую я только что описал.
My bad sorry about that, below is the full back trace of the error.
* thread #1: tid = 0x6d530, 0x01e002e0 libswiftCore.dylib`function signature specialization <preserving fragile attribute, Arg[2] = Dead, Arg[3] = Dead> of Swift._fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt, flags : Swift.UInt32) -> Swift.Never + 124, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xe7ffdefe)
frame #0: 0x01e002e0 libswiftCore.dylib`function signature specialization <preserving fragile attribute, Arg[2] = Dead, Arg[3] = Dead> of Swift._fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt, flags : Swift.UInt32) -> Swift.Never + 124
frame #1: 0x01cbbd3c libswiftCore.dylib`Swift._ContiguousArrayBuffer._checkValidSubscript (Swift.Int) -> () + 164
frame #2: 0x01cbbde0 libswiftCore.dylib`Swift._ArrayBuffer._checkInoutAndNativeTypeCheckedBounds (Swift.Int, wasNativeTypeChecked : Swift.Bool) -> () + 164
frame #3: 0x01ccd430 libswiftCore.dylib`Swift.Array.subscript.getter : (Swift.Int) -> A + 112
frame #4: 0x006a9d04 Charts`CombinedChartData.entryForHighlight(highlight=0x171832f0, self=0x15d04040) -> ChartDataEntry? + 200 at CombinedChartData.swift:278
* frame #5: 0x0069b138 Charts`ChartViewBase.highlightValue(highlight=0x171832f0, callDelegate=true, self=0x15e35710) -> () + 652 at ChartViewBase.swift:547
frame #6: 0x0069ac28 Charts`ChartViewBase.highlightValue(x=0, y=NaN, dataSetIndex=0, callDelegate=true, self=0x15e35710) -> () + 536 at ChartViewBase.swift:522
frame #7: 0x0069a964 Charts`ChartViewBase.highlightValue(x=0, dataSetIndex=0, callDelegate=true, self=0x15e35710) -> () + 136 at ChartViewBase.swift:499
frame #8: 0x0069a744 Charts`ChartViewBase.highlightValue(x=0, dataSetIndex=0, self=0x15e35710) -> () + 88 at ChartViewBase.swift:478
frame #9: 0x0005f7b8 UrWtU8`CombinedChartView.setCombinedChart(xValues=Swift.Dictionary<UrWtU8.SegmentKey, Swift.String> @ 0x003f3158, yValues=0 key/value pairs, order=7 values, self=0x15e35710) -> () + 9808 at ViewExtensions.swift:379
frame #10: 0x0004ac7c UrWtU8`FJViewController.setChart(self=0x16016200) -> () + 2320 at FJViewController.swift:143
frame #11: 0x00048d68 UrWtU8`FJViewController.viewDidLoad(self=0x16016200) -> () + 1456 at FJViewController.swift:102
frame #12: 0x00048ebc UrWtU8`@objc FJViewController.viewDidLoad() -> () + 56 at FJViewController.swift:0
frame #13: 0x28072d8a UIKit`-[UIViewController loadViewIfRequired] + 1026
frame #14: 0x28130682 UIKit`-[UINavigationController _layoutViewController:] + 38
frame #15: 0x28130574 UIKit`-[UINavigationController _updateScrollViewFromViewController:toViewController:] + 376
frame #16: 0x2812f928 UIKit`-[UINavigationController _startTransition:fromViewController:toViewController:] + 96
frame #17: 0x2812f55e UIKit`-[UINavigationController _startDeferredTransitionIfNeeded:] + 834
frame #18: 0x2812f1b4 UIKit`-[UINavigationController __viewWillLayoutSubviews] + 52
frame #19: 0x2812f12a UIKit`-[UILayoutContainerView layoutSubviews] + 214
frame #20: 0x2806ea72 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 714
frame #21: 0x26106bcc QuartzCore`-[CALayer layoutSublayers] + 128
frame #22: 0x26102374 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 348
frame #23: 0x26102208 QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16
frame #24: 0x261016d0 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 368
frame #25: 0x261013a4 QuartzCore`CA::Transaction::commit() + 520
frame #26: 0x260fab2a QuartzCore`CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 138
frame #27: 0x23ab96c8 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 20
frame #28: 0x23ab79cc CoreFoundation`__CFRunLoopDoObservers + 280
frame #29: 0x23ab7dfe CoreFoundation`__CFRunLoopRun + 958
frame #30: 0x23a07228 CoreFoundation`CFRunLoopRunSpecific + 520
frame #31: 0x23a07014 CoreFoundation`CFRunLoopRunInMode + 108
frame #32: 0x24ff7ac8 GraphicsServices`GSEventRunModal + 160
frame #33: 0x280db188 UIKit`UIApplicationMain + 144
frame #34: 0x000fdac4 UrWtU8`main + 172 at AppDelegate.swift:33
frame #35: 0x236af872 libdyld.dylib`start + 2