Title: 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]'
Tags: ios;swift;uipageviewcontroller
Question: I have three images that I am trying to display in UIPageView but every time I swipe to the third image, I get this error: 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]'
I have checked other question regarding this same issue but can't figure out where my issue resides.
Here is the rest of the output:
*** First throw call stack:
0   CoreFoundation                      0x000000010a410c65 __exceptionPreprocess + 165
1   libobjc.A.dylib                     0x000000010a0a9bb7 objc_exception_throw + 45
2   CoreFoundation                      0x000000010a30717e -[__NSArrayI objectAtIndex:] + 190
3   BonBUp                              0x0000000109b1a1cb _TFC6BonBUp14ViewController21viewControllerAtIndexfS0_FSiCS_21ContentViewController + 619
4   BonBUp                              0x0000000109b1a792 _TFC6BonBUp14ViewController18pageViewControllerfS0_FTCSo20UIPageViewController33viewControllerAfterViewControllerCSo16UIViewController_GSqS2__ + 418
5   BonBUp                              0x0000000109b1a84f _TToFC6BonBUp14ViewController18pageViewControllerfS0_FTCSo20UIPageViewController33viewControllerAfterViewControllerCSo16UIViewController_GSqS2__ + 79
6   UIKit                               0x000000010afc2c67 -[UIPageViewController _queuingScrollView:viewBefore:view:] + 129
7   UIKit                               0x000000010b06044c -[_UIQueuingScrollView _viewAtIndex:loadingIfNecessary:updatingContents:animated:] + 247
8   UIKit                               0x000000010b0625c2 -[_UIQueuingScrollView _adjustContentInsets] + 316
9   UIKit                               0x000000010b060135 -[_UIQueuingScrollView _replaceViews:updatingContents:adjustContentInsets:animated:] + 763
10  UIKit                               0x000000010b063287 -[_UIQueuingScrollView _didScrollWithAnimation:force:] + 1082
11  UIKit                               0x000000010b05f42b -[_UIQueuingScrollView layoutSubviews] + 155
12  UIKit                               0x000000010aacb9eb -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 536
13  QuartzCore                          0x000000010f122ed2 -[CALayer layoutSublayers] + 146
14  QuartzCore                          0x000000010f1176e6 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
15  QuartzCore                          0x000000010f117556 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
16  QuartzCore                          0x000000010f08386e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
17  QuartzCore                          0x000000010f084a22 _ZN2CA11Transaction6commitEv + 462
18  QuartzCore                          0x000000010f146085 _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 489
19  CoreFoundation                      0x000000010a378174 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
20  CoreFoundation                      0x000000010a377d35 __CFRunLoopDoTimer + 1045
21  CoreFoundation                      0x000000010a339d3d __CFRunLoopRun + 1901
22  CoreFoundation                      0x000000010a339366 CFRunLoopRunSpecific + 470
23  GraphicsServices                    0x000000010ec4ba3e GSEventRunModal + 161
24  UIKit                               0x000000010aa4b8c0 UIApplicationMain + 1282
25  BonBUp                              0x0000000109b21327 main + 135
26  libdyld.dylib                       0x000000010cfe2145 start + 1
27  ???                                 0x0000000000000001 0x0 + 1
libc++abi.dylib: terminating with uncaught exception of type NSException
Here is the code within my ViewController:
import UIKit
class ViewController: UIViewController, UIPageViewControllerDataSource {
var pageViewController: UIPageViewController!
var pageImages: NSArray!
override func viewDidLoad() {
super.viewDidLoad()
self.pageImages = NSArray(objects: "jeans.png", "blusas.png", "leggings.png")
self.pageViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as! UIPageViewController
self.pageViewController.dataSource = self
var startVC = self.viewControllerAtIndex(0) as ContentViewController
var viewControllers = NSArray(object: startVC)
self.pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Forward, animated: true, completion: nil)
self.pageViewController.view.frame = CGRectMake(0, 30, self.view.frame.width, self.view.frame.size.height - 60)
self.addChildViewController(self.pageViewController)
self.view.addSubview(self.pageViewController.view)
self.pageViewController.didMoveToParentViewController(self)
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
func viewControllerAtIndex(index: Int) -&gt; ContentViewController
var vc: ContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as! ContentViewController
vc.imageFile = self.pageImages[index] as! String
vc.pageIndex = index
return vc
// MARK: - Page View Controller Data Source
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -&gt; UIViewController?
var vc = viewController as! ContentViewController
var index = vc.pageIndex as Int
if (index == 0) || (index == NSNotFound)
{
return nil
}
index--
return self.viewControllerAtIndex(index)
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -&gt; UIViewController? {
var vc = viewController as! ContentViewController
var index = vc.pageIndex as Int
if (index == NSNotFound)
{
return nil
}
index++
return self.viewControllerAtIndex(index)
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -&gt; Int
return 0
And ContentViewController:
import UIKit
class ContentViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
var pageIndex: Int!
var imageFile: String!
override func viewDidLoad()
super.viewDidLoad()
self.imageView.image = UIImage(named: self.imageFile)
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
Comment: Thanks for the reply. This is what I get when I put a breakpoint there: http://imgur.com/ZY5lEoa

Comment: Did you try to put a breakpoint at ` func viewControllerAtIndex(index: Int) -> ContentViewController` and see from where is it called with index = 3 ?

Here is the accepted answer: Your are not checking if index &gt;= self.pageImages.count to return nil in viewControllerAtIndex method, so when you are on last page it will ask fro viewController after and you will end up crashing due to index out of bound, your method should look like this.
func viewControllerAtIndex(index: Int) -&gt; ContentViewController?
if index &gt;= self.pageImages.count
{
return nil
}
var vc: ContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as! ContentViewController
vc.imageFile = self.pageImages[index] as! String
vc.pageIndex = index
return vc
As your method can return nil now, so I added ? at the end of method, and you need to make some changes in code as well to use this now.
Comment for this answer: i Updated the if statement, it was count
Comment for this answer: I added ? because this method can return nil if index is out of bounds.. you need to make some changes
Comment for this answer: yes you can add UITapGestureRecognizer to UIImageView
Comment for this answer: Add tap gesture inside viewDidLoad of ContentViewController where you are adding `imageView`...
`var tapGestureZoom = UITapGestureRecognizer(target: self, action: "jns:")
self.imageView.add(tapGestureZoom)`
Comment for this answer: its addGestureRecognizer(tapGestureZoom)
Comment for this answer: you need to implement method which you provide as action ... func ins(){
// create view controller here which you want to push, or
// if you have an segue in storyboard  then call performSegue method
Comment for this answer: Thanks for that clarification but I am getting the following error when I implement that `if` statement: `Binary operator '>=' cannot be applied to operands of type 'Int' and 'NSArray!'`. I also noted you added a `?` to `ContentViewController` hence I had to modify the code in `viewDidLoad` `var startVC = self.viewControllerAtIndex(0) as ContentViewController?` and add the `?` there too. Also an `!` in `var viewControllers = NSArray(object: startVC!)` under the same method since they were showing me errors.
Comment for this answer: Got it working. Thanks! One more question, is there any way to make each image clickable and take them to different Navigation Controllers?
Comment for this answer: So it would be adding somethings like this under `viewDidLoad` method under each image? `var tapGestureZoom = UITapGestureRecognizer(target: self, action: "jns:")
tapGestureZoom.numberOfTapsRequired = 1
tapGestureZoom.numberOfTouchesRequired = 1
pageImages.userInteractionEnabled = true
pageImages.addGestureRecognizer(tapGestureZoom)`
Comment for this answer: I am getting this error: `'UIImageView' does not have a member named 'add'` should I change it to `imageView`? Also, do I have to add this code once or for each image?
Comment for this answer: Ok, do I have to add an `IBAction` like this: `@IBAction func Jns(sender: AnyObject?){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("Jeans") as! Jeans
}` And then connect `ContentViewController to `NavigationController` by adding a custom segue?


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 2, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2015:00:08/17/15', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<ios><swift><uipageviewcontroller>', 'Title': "'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]'", 'ViewCount': 3850, 'id': 32045000, 'user_AboutMe': None, 'user_AccountId': 6135023.0, 'user_DisplayName': 'wlmrlsda', 'user_Reputation': 163.0, 'user_Views': 24.0, 'user_id': 4784166.0}}