Crash in UIPageViewController when adding pages - ios

In the iOS 11 app I'm developing (using Swift 4), I need to dynamically add pages to a UIPageViewController. However, in some circumstances, I receive the following crash error (NSInternalInconsistencyException):
2017-11-27 14:55:54.787260+0000 MyApp[380:79434] *** Assertion failure in -[UIPageViewController _flushViewController:animated:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3698.21.8/UIPageViewController.m:2124
2017-11-27 14:55:54.791022+0000 MyApp[380:79434] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Don't know about flushed view <UIView: 0x12dd48ac0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x1c003c280>>'
I am very new to iOS development, so I'm sorry if the answer is obvious, but I'm having a hard time finding the root cause for the crash. The logged message isn't being very helpful either...
This is the code I'm using to add pages:
//Inflate the view controller
let viewController = newViewController(param: someParam )
//Add it to the view controllers pool
viewControllersOrdered.insert(viewController, at: getInsertionIndex(param: someOtherParam) )
//Add it to the pageViewController
pageViewController.setViewControllers([viewController], direction: .forward, animated: false, completion: nil)
//Force cache to be cleared
pageViewController.dataSource = nil;
pageViewController.dataSource = self;
The getInsertionIndex function is working correctly, that is not the source of the crash.

In the iOS 11 app I'm developing (using Swift 4), I need to dynamically add pages to a UIPageViewController.
It sounds like what you mean is: you do not know what the next / previous view controller will be until the user actually tries to "turn the page". In that case, a scrolling UIPageViewController is not a good fit for your architecture (because, as you have already figured out, it precaches the next and previous pages). You have two choices:
Use a page-curl UIPageViewController. It doesn't precache its pages, so you are not called upon to make a decision until the user actually asks to turn the page.
Don't use a UIPageViewController at all; use a paging horizontal scroll view and manage the content view yourself.
Also, if you're using a UIPageViewController, in no case should you also be holding a retained list of child view controllers. That is the job of the UIPageViewController. Your job is merely to supply the next or previous view controller, which you should create on demand and at no other time, and release it into the UIPageViewController's sole control.

The main rules of crash-free using UIPageController with scroll transition style:
1) set dataSource before calling setViewControllers method
2) use setViewControllers method without animation (animated: false)
3) set dataSource to nil for single page mode
4) don't allow cycles for 2-page mode
One can find full Swift realisation of a stable subclass at my detailed answer
The initial code and usage examples one can find at GitHub project.

Related

AppleTV app crashes because of a UITableViewCell not providing a parentFocusEnvironment

Since Xcode 14 (AppleTV SDK 16.0) and tvOS 16.0, my AppleTV app crashes when I try to call reloadData() on a UITableView after the user selects a cell (the goal is to update the table model and view). The crash states that a UITableViewCell does not have a parentFocusEnvironment:
*** Assertion failure in -[_UIFocusItemInfo _createFocusedRegion], _UIFocusItemInfo.m:187
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Focus item <UITableViewCell: 0x7f92d202fc00> does not provide a parentFocusEnvironment.'
The app creates regular UITableViewCell hence does not override this property so I don't understand why it is missing.
• On tvOS 15.4 (whatever Xcode version 13.4.1 or 14), the app does not crash and the behaviour is as expected. No system warnings or logs.
• On tvOS 16.0 with XCode 13.4.1 (AppleTV SDK 15.0), the app does not crash either but the unfocused view of the selected UITableViewCell stays in the view hierarchy after the reloading. Also a system log warns that the focus item (UITableViewCell) does not define a parentFocusEnvironment and that the app will crash in a future version -> my crash.
[Assert] Focus item <UITableViewCell: 0x7fe4290a7c00> does not provide a parentFocusEnvironment. This will become an assert in a future version.
[Assert] Failed to create FocusRegion for FocusItem: <UITableViewCell: 0x7ff129856600; frame = (0 800; 880 66); text = 'Show empty sections'; autoresize = W; layer = <CALayer: 0x600003a1f740>> with parentFocusEnvironment: (null) focusItemContainer: (null)
I've been able to create a sample project where the crash can be reproduced: https://github.com/aureliencolas/NavAndTableView
I've filed a feedback request to Apple a week ago with the sample project but I've got no response so far.
Any advice on how to refresh the tableView in a more appropriate way is welcome.
After requesting a code-level support, an Apple engineer helped me find the fix.
Turns out I was not recycling UITableView cells, but creating new ones each time (which I don't usually do but, in this context, there were no point in recycling cells) and doing so, the cell's parentFocusEnvironment was not always defined.
As it was working fine before tvOS 16 and cells recycling not being mandatory, I still consider it a TVOS 16 regression but the issue is now fixed and it's what matters.
Update:
The fix below does only work if the focus has been changed using touch input. Once focus has been changed using the external keyboard arrow keys, it still crashes at (with the same stack trace).
Different approach for now is to store the old parentFocusEnvironment and to return that at all times. This satisfies the assertion within the focus update, but I am still unsure of any side effects this might have:
// Custom Cell
#interface Cell : UITableViewCell
// Weak(!) reference to the last focus environment
#property(nonatomic, weak) id<UIFocusEnvironment> lastParentFocusEnvironment;
#end
#implementation Cell
- (id<UIFocusEnvironment>)parentFocusEnvironment
{
// Always use original parent environment as long as it is available
id environment = [super parentFocusEnvironment];
if (environment)
self.lastParentFocusEnvironment = environment;
return self.lastParentFocusEnvironment;
}
#end
I see the same crash on iPadOS when contents of a focussed table view are cleared. The table view correctly removes the focus and informs the delegate in - (void)tableView:(UITableView *)tableView didUpdateFocusInContext:(UITableViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator . However, the view crashes after that delegate method is invoked, stating that the old view, which had focus before, does not have a parentFocusEnvironment, since it had been removed from the view hierarchy.
The crash occurred in the next layout phase after the table view updated, since focus updates appear to happen during layout. This table already uses cell recycling, so that could not be the solution as mentioned in other answers.
The fix was to remove the selection from the table view before calling reloadData like so (assuming selectionFollowsFocus is set on the table view):
// Gather data..
if (!hasRowToFocus) {
// Remove selection
[self.tableView selectRowAtIndexPath:nil animated:NO scrollPosition:UITableViewScrollPositionNone];
// Update focus while the old focussed view is still visible to avoid the crash
[self.tableView setNeedsFocusUpdate];
[self.tableView updateFocusIfNeeded];
}
// Proceed with table view updates..
[tableView reloadData];
...
I'd also consider this a bug, since the SDKs focus validation ignores the fact that an old view might be removed from the view hierarchy and thus lacking a parentFocusEnvironment.

How can I force update my UI immediately in Swift 5 using UIKit?

I ran into a problem with my UI, which is not updating immediately.
I am calling someCustomView.isHidden = false first. After that I create a new instance of a new View Controller. Inside the new VCs viewDidLoad(), I am loading a "new Machine Learning Model", which takes some time.
private func someFuncThatGetsCalled() {
print("1")
self.viewLoading.isHidden = false
print("2")
performSegue(withIdentifier: "goToModelVCSegue", sender: nil)
}
As soon as I press the button that calls this function, "1" and "2" is printed in the console. However the view is not getting visible before the viewDidLoad() of my new VC is finished.
Is there any possibility to force update a UIView immediately? setNeedsDisplay() did not work for me.
Thanks for your help!
Use layoutIfNeeded() Apple Docs
layoutIfNeeded()
Lays out the subviews immediately, if layout updates are pending.
Use this method to force the view to update its layout immediately. When using Auto Layout, the layout engine updates the position of views as needed to satisfy changes in constraints. Using the view that receives the message as the root view, this method lays out the view subtree starting at the root. If no layout updates are pending, this method exits without modifying the layout or calling any layout-related callbacks.
So As a rule of thumb,
layoutifneeded : Immediate (current update cycle) , synchronous call
setNeedsLayout :relaxed ( wait till Next Update cycle) , asynchronous call
So, layoutIfNeeded says update immediately please, whereas setNeedsLayout says please update but you can wait until the next update cycle.
how to use
yourView.layoutIfNeeded()
You can also refer to the diagram to better remember the order of these passes
Source Apple docs on layoutIfNeeded
Image credit Medium artcle
A couple problems...
If you have a view controller that "takes some time" to load, you should not try to do it in that manner.
The app will be non-responsive and appear "frozen."
A much better approach would be:
on someFuncThatGetsCalled()
hide viewLoading and replace it with an activity indicator (spinner, or something else that let's the user know the app is not stuck)
instantiate your ModelVC
when ModelVC has finished its setup, have it inform the current VC (via delegate)
current VC then shows / navigates to the already instantiated and prepared ModelVC
Or, probably a better option... Move your time-consuming setup in ModelVC to a point after the view has appeared. You can show an activity indicator in viewDidLoad(). That is really the most common UX - you see it all the time when the new VC has to retrieve remote data to display - and it would fit wit what users have come to expect.

Flickering initial Storyboard content before viewDidLoad()?

I'm scratching my head for days already trying to understand what I observe. I'm doing iOS development for many ears and I believe I have never seen such effect:
Basically for all ViewControllers I have in the app (defined in a Storyboard), when the view appears, the initial storyboard defined content/layout is displayed for a second and then the proper content appears.
I'm doing all UI element setup is viewDidLoad() so I expect when content appears it must be already properly configured.
No idea what it can be. Changes in Swift/Xcode? Some hidden project configuration?
sounds to me like you are displaying your vc too soon,
it might be that your initial setup is too costly, or that you are calling a service to get that initial data and until the response arrives your vc is still 'flickering' as you put it.
this is usually solved by presenting a loader and making the actual transition only once you are finished with the initialization / data getting phase.
some initializations are more costly than others.

UIPageViewController position is messed up after setting new page programmatically. How to fix? [duplicate]

My UIPageViewController was working fine in iOS 5. But when iOS 6 came along, I wanted to use the new scroll transition style (UIPageViewControllerTransitionStyleScroll) instead of the page curl style. This caused my UIPageViewController to break.
It works fine except right after I've called setViewControllers:direction:animated:completion:. After that, the next time the user scrolls manually by one page, we get the wrong page. What's wrong here?
My workaround of this bug was to create a block when finished that was setting the same viewcontroller but without animation
__weak YourSelfClass *blocksafeSelf = self;
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished){
if(finished)
{
dispatch_async(dispatch_get_main_queue(), ^{
[blocksafeSelf.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];// bug fix for uipageview controller
});
}
}];
This is actually a bug in UIPageViewController. It occurs only with the scroll style (UIPageViewControllerTransitionStyleScroll) and only after calling setViewControllers:direction:animated:completion: with animated:YES. Thus there are two workarounds:
Don't use UIPageViewControllerTransitionStyleScroll.
Or, if you call setViewControllers:direction:animated:completion:, use only animated:NO.
To see the bug clearly, call setViewControllers:direction:animated:completion: and then, in the interface (as user), navigate left (back) to the preceding page manually. You will navigate back to the wrong page: not the preceding page at all, but the page you were on when setViewControllers:direction:animated:completion: was called.
The reason for the bug appears to be that, when using the scroll style, UIPageViewController does some sort of internal caching. Thus, after the call to setViewControllers:direction:animated:completion:, it fails to clear its internal cache. It thinks it knows what the preceding page is. Thus, when the user navigates leftward to the preceding page, UIPageViewController fails to call the dataSource method pageViewController:viewControllerBeforeViewController:, or calls it with the wrong current view controller.
I have posted a movie that clearly demonstrates how to see the bug:
http://www.apeth.com/PageViewControllerBug.mov
EDIT This bug will probably be fixed in iOS 8.
EDIT For another interesting workaround for this bug, see this answer: https://stackoverflow.com/a/21624169/341994
Here is a "rough" gist I put together. It contains a UIPageViewController alternative that suffers from Alzheimer (ie: it doesn't have the internal caching of the Apple implementation).
This class isn't complete but it works in my situation (namely: horizontal scroll).
As of iOS 12 the problem described in the original question seems to be almost fixed. I came to this question because I experienced it in my particular setup, in which it does still happen, hence the word "almost" here.
The setup I experienced this issue was:
1) the app was opened via a deep link
2) based on the link the app had to switch to a particular tab and open a given item there via push
3) described issue happened only when the target tab was not previously selected by user (so that UIPageViewController was supposed to animate to that tab) and only when setViewControllers:direction:animated:completion: had animated = true
4) after the push returning back to the view controller containing the UIPageViewController, the latter was found to be a big mess - it was presenting completely wrong view controllers, even though debugging showed everything was fine on the logic level
I supposed that the root of the problem was that I was pushing view controller very quick after setViewControllers:direction:animated:completion: called, so that the UIPageViewController had no chance to finish something (maybe animation, or caching, or something else).
Simply giving UIPageViewController some spare time by delaying my programmatic navigation in UI via
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) { ... }
fixed the issue for me. And it also made the programmatic opening of the linked item more user friendly visually.
Hope this helps someone in similar situation.
Because pageviewVC call multi childVC when swipe it. But we just need last page that visible.
In my case, I need to change index for segmented control when change pageView.
Hope this help someone :)
extension ViewController: UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
guard let pageView = pageViewController.viewControllers?.first as? ChildViewController else { return }
segmentedControl.set(pageView.index)
}
}
This bug still exists in iOS9. I am using the same workaround that George Tsifrikas posted above, but a Swift version:
pageViewController.setViewControllers([page], direction: direction, animated: true) { done in
if done {
dispatch_async(dispatch_get_main_queue()) {
self.pageViewController.setViewControllers([page], direction: direction, animated: false, completion: {done in })
}
}
}
Another simple workaround in Swift: Just reset the UIPageViewController's datasource. This apparently clears its cache and works around the bug. Here's a method to go directly to a page without breaking subsequent swipes. In the following, m_pages is an array of your view controllers. I show how to find currPage (the index of the current page) below.
func goToPage(_ index: Int, animated: Bool)
{
if m_pages.count > 0 && index >= 0 && index < m_pages.count && index != currPage
{
var dir: UIPageViewController.NavigationDirection
if index < currPage
{
dir = UIPageViewController.NavigationDirection.reverse
}
else
{
dir = UIPageViewController.NavigationDirection.forward
}
m_pageViewController.setViewControllers([m_pages[index]], direction: dir, animated: animated, completion: nil)
delegate?.tabDisplayed(sender: self, index: index)
m_pageViewController.dataSource = self;
}
}
How to find the current page:
var currPage: Int
{
get
{
if let currController = m_pageViewController.viewControllers?[0]
{
return m_pages.index(of: currController as! AtomViewController) ?? 0
}
return 0
}
}
STATEMENT:
It seems that Apple has spotted that developers are using UIPageViewController in very different applications that go way beyond the
originally intended ones Apple based their design-choices on in the first place. Rather than using it in a gesture driven linear fashion
PVC is often used to programmatically jump to random
positions within a structured environment. So they have enhanced their implementation of UIPageViewController and the class is now calling both DataSource
callbacks
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
after setting a new contentViewController on UIPageViewController with
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
even if an animated turn of pages rather suggests a linear progress in an e.g. page hierarchy like a book or PDF with consecutive pages. Although - I doubt that Apple from a HIG standpoint
is very fond of seeing PVC being used this way, but - it doesn't break backwards compatibility, it was an easy fix, so - they eventually did it. Actually it is just one more call of one of the two DataSource methods that is absolutely unnecessary in a linear environment where pages (ViewControllers) have already been cashed for later use.
However, even if this enhancement might come in very handy for certain use-cases the initial behavior of the class is NOT to be considered a bug. The fact that a lot of developers do - also in other
posts on SO that accuse UIPageViewController of misbehavior - rather emphasizes a widely spread misconception of its design, purpose and functionality.
Without trying to offend any of my fellow developers here in this great facility I nonetheless decided not to remove my initial 'disquisition' that clearly explains to the OP the mechanics of PVC and why his assumption is wrong that he has to deal with a bug here.
This might also be of use for any other fellow developer too who struggles with some intricacies in the implementation of UIPageViewController!
ORIGINAL ANSWER:
After having read all the answers over and over again - included the
accepted one - there is just one more thing left to say...
The design of UIPageViewController is absolutely FLAWLESS and all the
hacks you submit in order to circumvent an alleged bug is nothing but
remedies for your own faulty assumptions because you goofed it up in the
first place!!!
THERE IS NO BUG AT ALL! You are just fighting the framework. I'll explain why!
There is so much talk about page numbers and indices! These are concepts the
controller knows NOTHING about! The only thing it knows is - it is showing
some content (btw. provided by you as a dataViewController) and that it can
do something like a right/left animation in order to imitate a page turn.
CURL or SCROLL...!!!
In the pageViewController's world there only exists a current SPACE (let's call
it just this way to avoid confusion with pages and indices).
When you initially set a pageViewController it only minds about this very SPACE.
Only when you start panning its view it starts asking its DataSource what it
eventually should display in case a left/right flip should happen. When you start
panning to the left the PVC asks first for the BEFORE-SPACE and then for the
AFTER-SPACE, in case you start to the right it does it the other way round.
After the completed animation (a new SPACE is displayed by the PVC's view) the
PVC considers this SPACE as its new center of the universe and while it is at it, it
asks the DataSource about the one it still does not know anything about. In case of
a completed turn to the right it wants to know about the new AFTER space and in
case of a completed turn to the left it asks for a new BEFORE space.
The old BEFORE space (from before the animation) is in case of a completed turn to
the right completely obsolete and gets deallocated as soon as possible. The old center
is now the new BEFORE and the former AFTER is the new center. Everything just
shifted one step to the right.
So - no talk of 'which page' or 'whatever index' - just simply - is there a BEFORE or
an AFTER space. If you return NIL to one of the DataSource callbacks the PVC just
assumes it is at one extreme of your range of SPACES. If you return NIL to both
callbacks it assumes it is showing the one and only SPACE there is and will never
ever again call a DataSource callback anymore! The logic is up to you! You define
pages and indices in your code! Not the PVC!!!
For the user of the class there are two means of interacting with the PVC.
A pan-gesture that indicates whether a turn to the BEFORE/AFTER space is desired
A method - namely setViewControllers:direction:animated:completion:
This method does exactly the same than the pan gesture is doing. You are indicating the
direction (e.g. UIPageViewControllerNavigationDirectionBackward/Forward)
for the animation - if there is one intended - which in other words just means -> going to
BEFORE or AFTER...
Again - no mentioning of indices, page-numbers etc....!!!
It is just a programmatically way of achieving the same a gesture would!
And the PVC is doing right by showing the old content again when moving back
to the left after having moved to the right in the first place. Remember
- it is just showing content (that you provide) in a structured way - which is a 'single page turn' by design!!!
That is the concept of a page turn - or BOOK, if you like that term better!
Just because you goof it up by submitting PAGE 8 after PAGE 1 doesn't mean the PVC
cares at all about your twisted opinion of how a book should work. And the user of your
apps neither. Flipping to the right and back to the left should definitely result in reaching
the original page - IF done with an animation. And it is up to YOU to correct the goof by
finding a solution for the disaster. Don't blame it on the UIPageViewController. It is doing
its job perfectly!
Just ask yourself - would you do the same thing with a PAGE-CURL animation? NO ?
Well, neither should you with a SCROLL animation!!! An animated page turn is a page turn and only a page turn!
In either mode!
And if you decide to tear out PAGE 2 to PAGE 7 of your BOOK that's perfectly fine!
But just don't expect UIPageViewController to invent a non-existing PAGE 7 when turning back to the recent page unless YOU tell it that things have changed...
If you really want to achieve an uncoordinated jump to elsewhere, well - do it without an
animation! In most cases this will not be very elegant but - it's possible... -
And the PVC even plays nicely along! When jumping to a new SPACE without animation
it will ask you further down the road for both - the BEFORE and AFTER controller. So your application-logic can keep up with the PVC...
But with an animation you are always conveying - move to the previous/next space (BEFORE -
AFTER). So logically there is no need at all for the PVC to ask again about a space it already
knows about when animating page turns!!!
If you wanna see PAGE 7 when flipping back to the left after having animated from PAGE 1
to the right - well, I would say - that's definitely your very own problem!
And just in case you are looking for a better solution than the 'completion-block' hack from
the accepted answer (because with it you are doing work beforehand for something that might
possibly not even get used further down the road) use the gesture recognizer delegate:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
Set your PVC's DataViewController here (without animation) if you really intend to go back
left to PAGE 7 and the DataSource will be asked for BEFORE and AFTER and you can submit
whatever page you like! With a flag or ivar that you should have stashed away when doing your uncontrolled
jump from PAGE 1 to 8 this should be no problem...
And when people keep on complaining about a bug in the PVC - doing 2 page turns when it is
supposed to do 1 turn only - point them to this article.
Same problem - triggering an un-animated setViewControllers: method within the transition gesture
will cause exactly the same havoc. You think you set the new center - the DataSource is asked
for the new BEFORE - AFTER dataController - you reset your index count... - Well, that seems OK...
But - after all that business the PVC ends its transition/animation and wants to know about the
next (still unknown to it) dataViewController (BEFORE or AFTER) and also triggers the DataSource. That's totally justified ! It needs to know where in its small BEFORE - CENTER - AFTER
world it is and be prepared for the next turn.
But your program-logic adds another index++ count to its logic and suddenly got 2 page turns !!!
And that is one off from where you think you are.
And YOU have to account for that! Not UIPageViewController !!!
That is exactly the point of the DataSourceProtocol only having two methods! It wants to be as generic as possible - leaving you the space and freedom to define your own logic and not being stuck with somebody else's special ideas and use-cases! The logic is completely up to you. And only because you find functions like
- (DataViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard position:(GSPositionOfDataViewController)position;
- (NSUInteger)indexOfViewController:(DataViewController *)viewController;
in all the copy/pasted sample applications in the cloud doesn't necessarily mean that you have to eat that pre-cook food! Extend them any way you like! Just look above - in my signature you will find a 'position:' argument! I extended this to know later on if a completed page turn was a right or a left turn. Because the delegate unfortunately just tells you whether your turn completed or not! It doesn't tell you about the direction! But this sometimes matters for index-counting, depending on your application's need...
Go crazy - they are your's...
HAPPY CODING !!!

App Crashes if AddAnnotations doesn't finish

I have an Application, which is a SplitViewController that has a master view on the left and the detail view on the right. One of the views (Branch Finder) is a Map view that loads a series of Annotations to the Map.
If I let the annotations load before switching to any other view (loading the annotations take takes all of 1 second) then everything is fine. However, if the user quickly switches off the Branch Finder view, whilst the annotations are being loaded, then the App will crash with the following notice:
[BranchFinder_iPad respondsToSelector:]: message sent to deallocated instance 0x807d230
Now, my thoughts are that the deallocated instance would refer to the Array (declared in the header of the view) that contains all the annotations being released and set to nil when the user leaves the BranchFinder_iPad view. This is the array that is being passed to the addAnnotations method.
[self.mapView addAnnotations:branchSites];
Has anyone else encountered an issue where leaving a view, mid-way in the add allocations and a crash occurs if the user moves to another view.
Just to clarify:
If I wait for the annotations to load, switching to any other view causes no problem.
I did have a custom annotation view, but I stripped that out of my code (to eliminate it from the mix). Doing this has not changed anything.
I have looked elsewhere for help on this issue, but a lot of the view tutorials regarding map views are single view only, so this issue hasn't arisen.
I have found a vaguely similar issue # the following: mapkit addAnnotations crashes
And finally, I have just made the jump to x-code 4. I think some of my problems are just because I'm relearning some of the things I should know.
Regards,
Nathan A
PS: I wanted to attach an image to this, but am having trouble. I don't have the reputation points to do it natively, and my workplace doesn't allow me access to any image hosting portals. I will endeavour to add an image later today.
Hey anyone who reads this.
I basically performed a rookie mistake here - for the MKMapView in my application, I had to set the delegate to nil as part of the deallocation routine within my view. THe apple documentation makes mention of this in the below document:
http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKMapViewDelegate_Protocol/MKMapViewDelegate/MKMapViewDelegate.html
For the relevant section:
Before releasing an MKMapView object for which you have set a delegate, remember to set that object’s delegate property to nil. One place you can do this is in the dealloc method where you dispose of the map view.
Not having this was only causing an issue if I switched to another view AND if the MKMapView was still being referenced in executing code, such as the addAnnotations routine.

Resources