Long delays displaying UIImageView loaded from local file? - ios

I see questions regarding long delays in displaying UIImageViews after downloading, but my question involves long delays when
reading from local storage.
After archiving my hierarchy of UIImageViews to a local file (as per narohi's answer in
How to output a view hierarchy & contents to file? ),
I find that if I want to reload them, it takes 5 to 20 seconds for the views to actually appear on screen,
despite my setting setNeedsDiplay() on the main view and all the subviews.
I can immediately query the data contained in the
custom subclasses of UIView that get loaded -- showing that NSKeyedUnarchiver and all the NS-decoding and all the init()'s have completed -- however
the images just don't appear on the screen for a long time. Surely the next redraw cycle is shorter than 5-20 seconds...?
It seems odd that images from PhotoLibrary appear instantly, but anything loaded from local file storage using NSKeyedUnarchiver takes "forever."
What's going on here, and how can I speed this up?
.
.
To be explicit, the relevant part of my Swift code looks like this:
let view = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as! UIView!
if (nil == view) {
return
}
myMainView.addSubview(view)
view.setNeedsDisplay()
// now do things with the data in view ...which all works fine
I find that, even if I add something like...
for subview in view.subviews {
subview.setNeedsDisplay()
}
...it doesn't speed up the operations.
We are not talking huge datasets either, it could be just a single imageview that's being reloaded.
Now, I do also notice these delays occurring when downloading from the internet using a downloader like the one shown in
https://stackoverflow.com/a/28221670/4259243
...but I have the downloader print a completion message after not only the download but when the (synchronous operation)
data.writeToFile() is complete (and before I try to load it using NSKeyedUnarchiver), so this indicates that the delay
in UIImageView redraws is NOT because the download is still commencing....and like I say, you can query the properties of the data and it's all in memory, just not displaying on the screen.
UPDATE: As per comments, I have enclosed the needsDisplay code in dispatch_async as per Leo Dabus's advice, and done some Time Profiling as per Paulw11's. Link to Time Profiling results is here: https://i.imgur.com/sa5qfRM.png I stopped the profiling immediately after the image appeared on the screen at around 1:00, but it was actually 'loaded' during the bump around 20s. During that period it seems like nothing's happening...? The code is literally just waiting around for a while?
Just to be clear how I'm implementing the dispatch_async, see here:
func addViewToMainView(path: String) {
let view = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as! UIView!
if (nil == view) {
return
}
dispatch_async(dispatch_get_main_queue(), {
self.myMainView.addSubview(view)
view.setNeedsDisplay()
self.myMainView.setNeedsDisplay()
})
}
...Since posting this I've found a few posts where people are complaining about how slow NSKeyedUnarchiver is. Could it just be that? If so, :-(.
SECOND UPDATE: Ahh, the "let view = " needs to be in the dispatch_async. In fact, if you just put the whole thing in the dispatch_async, it works beautifully! so...
func addViewToMainView(path: String) {
dispatch_async(dispatch_get_main_queue(), {
let view = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as! UIView!
if (nil == view) {
return
}
self.myMainView.addSubview(view)
view.setNeedsDisplay()
self.myMainView.setNeedsDisplay()
})
}
This works instantly. Wow.. Credit to Leo Dabus. Leaving this here for others...

Related

Memory Allocations Profiler and Steadily Increasing Persistent Memory - Signs of Trouble?

I have an app I am developing and the stakeholder using it said that the app becomes slow and unusable/unresponsive after consistent usage all day. Killing it and starting over causes it to run fine.
I don't seem to have this trouble on my device, but I started looking at the memory usage in both simulator/phone in debugger, and observed my memory would steadily increase if I took the basic action of going between screen to screen. These are pretty involved screens, but if I just go forward to the 'add new item' screen, then back to the product listing screen, the memory jumps up 30mb. If I keep doing this same action, over and over and over, I can get it to 1.1gb of memory
I then took it a step further, hooked up my phone, and ran profiler (specifically memory leaks). I found one leak involving my usage of ads, so I just commented out all the code for a test and while the leaks are gone, the memory continues to go up steadily.
I then ran the allocations tool, and after a few min of going back and forth in the same manner, here is the output:
As you can see, it's 1.53GB and if I kept doing the same action I can get it to 2GB+. Oddly enough, my phone never seems to mind, and the screens are just slightly laggy at times otherwise not too bad. Certainly usable.
Before I start ripping out the floor boards, I wanted to confirm this is a likely sign of a problem. Any suggestions on where I can start looking? If persistent memory is the issue, what would be some typical gotchas or pitfalls? What is "anonymous vm?"
Thank you so much if you're reading this far, and appreciate any guidance!
UPDATE/EDIT
After some guidance here, I noticed, oddly enough, that on the "add product" page it causes the memory to jump ~10MB each time I visit it. After commenting out code, I narrowed it down to this section (and even the line of code) causing the jump. Removing this code causes it to remain stable and not increase.
//Render collection views
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath)
let member: MemberDto = groupMembers[indexPath.item]
let contactInitials = cell.viewWithTag(1) as! UILabel
let contactAvatar = cell.viewWithTag(2) as! UIImageView
contactAvatar.image = UIImage(named: "anonymous")
contactInitials.text = member.displayName
contactAvatar.layer.cornerRadius = contactAvatar.frame.size.width / 2
contactAvatar.clipsToBounds = true
contactAvatar.contentMode = UIViewContentMode.scaleAspectFill
contactAvatar.layer.borderWidth = 5.0
if (member.profileImage.trimmingCharacters(in: CharacterSet.whitespaces) != "") {
UserService.getProfilePicture(userId: member.userId) {
response in
contactAvatar.image = response.value
}
}
So, the offending line of code is here:
contactAvatar.image = response.value
Adding it in, and going back and forth to this tableviewcontroller causes the memory to go up and up and up all the way to 2gb. Removing that one line of code (where I set the image) keeps it stable at ~40-70mb, or it goes up but very very slowly (dozens of repeats only got it to 80mb)
I realized I was not caching this image
I decided to try caching this with my framework, and that immediately resolved the issue. I suppose the line of code was pulling the image into memory or something like that? It doesn't seem like the networking call is the actual issue, since I left that in (and even went so far to make additional calls to my API) and that doesn't seem to do much by way of memory increase.
Just a few pieces of info:
From the main screen, you tap on a + symbol in the navigation menu bar to come to this screen.
I am using a regular segue on my storyboard, associated with the navigationbutton, to take the user here
Placing deinit on this vc does not seem to ever hit, even with print/code in there and breakpoints
Making API calls from within my uitableviewcontroller doesn't seem to cause the image to load UNLESS I combine that with SETTING the image. If I make a network call, but don't set the image, it doesn't increase.
What mistake did I make? I feel like caching the image is a bandaid - I recall reading that you're not supposed to make calls to images within a UITableViewController but what is the alternative, to pull all user images from the collection in advance and cache them before the tableview loads?
EDIT 2
As #matt suggested, this was just a bandaid. The true problem still lingered as I knew deinit() was not being called. After pulling out major chunks of code, I found this
lblMessage.addTapGestureRecognizer {
self.txtMessage.becomeFirstResponder()
}
which maps to an extension class:
public func addTapGestureRecognizer(action: (() -> Void)?) {
self.isUserInteractionEnabled = true
self.tapGestureRecognizerAction = action
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture))
self.addGestureRecognizer(tapGestureRecognizer)
}
public func addLongPressGestureRecognizer(action: (() -> Void)?) {
self.isUserInteractionEnabled = true
self.longPressGestureRecognizerAction = action
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture))
self.addGestureRecognizer(longPressGestureRecognizer)
}
// Every time the user taps on the View, this function gets called,
// which triggers the closure we stored
#objc fileprivate func handleTapGesture(sender: UITapGestureRecognizer) {
if let action = self.tapGestureRecognizerAction {
action?()
} else {
print("no action")
}
}
So somewhere in here the problem must lie. I'm taking this to a new thread:
Deinit not calling - Cannot find why something is retaining (code provided)
Thanks! Hope this helps someone.
Yes it's a problem, and yes you need to fix it. The two usual causes of this sort of thing are:
You've got a retain cycle such that at least some of your view controllers are never able to go out of existence.
You've designed the storyboard (or manual segue) sequence incorrectly, so that (for example) you present from view controller A to view controller B, and then in order to get "back" you present from controller B to view controller A. Thus you are not actually going "back"; instead, you are piling up a second view controller A on top of the first one, and so on, forever.
Either way, you can rapidly test that that sort of thing is going on just by implementing deinit to print(self) in all your view controllers. Then play with the app. If you don't see the printout in the log every time you go "back", you've got a serious memory problem, because the view controller is not being released when it should be, and you need to fix it.

Unreliable randomizing or loading of images

I want to randomly display some images stored as attributes on an entity "Disc" in Core Data. I've been using the Swift Array.shuffled() function performed on the fetchedObjects of my NSFetchedResultsController "thisFRC."
First problem was that the desired images often did not appear when they should. Here's code that produced this problem. It's part of a function loadImages, which is called from viewWillAppear:
try thisFRC.performFetch()
fetchedData = thisFRC.fetchedObjects as! [Disc]
shuffledDiscs = fetchedData.shuffled()
thisDisc = shuffledDiscs [0]
Second problem was that when they did appear, I would very often see the same image repeated several (or many) times. I thought maybe the images were persisting for some unknown reason, so I did:
frontImageView.image = nil
rearImageView.image = nil
in prepareForSegue. Same problem upon returning to the original View Controller.
Third problem arose when I tried to fix the second problem by further randomizing the order of the images with the code below. It crashes at the commented line with this error: “Index out of range”.
try thisFRC.performFetch()
fetchedData = thisFRC.fetchedObjects as! [Disc]
shuffledIndices = fetchedData.indices.shuffled()
index = shuffledIndices [0] // Crashes here with “Index out of range”
shuffledDiscs = fetchedData.shuffled()
thisDisc = shuffledDiscs [index]
My questions:
1) Why doesn't the shuffled() function do a better job of randomizing? To be fair, I tried this code in a separate test app, and it seemed to work fine. If I can clear this up, I can dispense with my workaround.
2) I don't understand how the index could be out of range in index = shuffledIndices [0]
Note:
The images I'm using are quite large -- on the order of 2400 x 2400 -- being squeezed into a 160 x 160 image view, so the early anomalies could possibly be caused by scaling.
Any help would be greatly appreciated!
TIA
Resolved!
With insight from #Adis, and a thousand print() lines, I discovered the problem:
There was a function extraneously inserting a new Disc entity into my context every time I segued to one of the two connected View Controllers. This accounted for the "ghost" items that were showing up with no UIImage attributes, creating blank ImageViews. Once I deleted these anomalies, and killed the function that created them, everything works fine. I was also able to just use the shuffled() function without the extra flourish I had put on it.
All is well, and thanks to all who took the time to look!

Best place to make network calls

Network Call :-
static func getProfile(parameters:[String:AnyObject], onComplete:[String:AnyObject]->()) {
var requiredData:[String:AnyObject] = [:]
Alamofire.request(.GET,API.getProfile,parameters: parameters).validate().responseJSON { (response) in
if let responseData = response.result.value {
if let jsonData = responseData as? [String:AnyObject] {
requiredData["UserName"] = jsonData["UName"]
requiredData["UserEmail"] = jsonData["UEmail"]
requiredData["UserMobileNo"] = jsonData["UPhone"]
requiredData["UserAddress"] = jsonData["UAddress"]
requiredData["UserCity"] = jsonData["UCity"]
}// Inner If
} // Main if
onComplete(requiredData)
}// Alamofire Closed
}// Func closed
Network Call within required VC :-
override func viewDidLoad() {
super.viewDidLoad()
let parameters:[String:AnyObject] = [
"WebKey": API.WebKey.value.rawValue,
"UId":NSUserDefaults.standardUserDefaults().integerForKey("UserId")
]
NetworkInterface.getProfile(parameters) { (responseDictionary) in
//print("Passed Data \(responseDictionary["UserName"])")
self.userData = responseDictionary
self.updateUI()
}
}
As far as i know, VC Lifecycle is somewhat as follows :-
init(coder aDecoder:NSCoder) -> viewDidLoad -> viewWillAppear -> viewWillDisappear
However, Even after view appears it takes few seconds for user Information to be displayed in those textfields. I thought viewDidLoad is the best place to make network calls.
I understand that network calls are async so it will take time to fetch required data from network and respond. However, network call was made in viewDidLoad so by the time view will appear, it should already have required data ? Should it not ?
So can anyone explain me which is the best place to make network calls and why? I want textfields to be updated with user Info as soon as view Appears.
Requests need to be fired in the viewWillAppear:, only this method notifies you that the screen is about to be shown. If you don't want to send requests every time the screen is shown, consider caching the data once you have it.
viewDidLoad is not the best candidate. It has nothing to do with the appearance of the screen. It's called right after a view controller's view is requested for the first time, not when the screen is showing up.
For example, if the screen was destroyed (by popping from a navigation controller), you'll receive viewDidLoad when you show it again (by pushing the screen to the navigation controller). Or if the app receives a memory warning, a current view is unloaded and loaded again, which ends up sending the view controller viewDidLoad.
viewDidLoad is tricky.
If you think that viewDidLoad will save you from fetching the data from the server multiple times: sometimes it will, sometimes it won't. Anyway, it's not the right tool to optimize networking, caching is!
Since remote requests are expensive (they take time and traffic), you want to understand when are they sent. viewWillAppear: gives you understanding. And in conjunction with caching you can make it optimal.
UPDATE
In most cases, it's not a good idea to send requests from the view controller directly. I would suggest creating a separate networking layer.
I think viewDidLoad is the correct place to make the network call if it fits that screen's need. i.e. you don't have to re-request the data at some point. For example if profile data has changed since the view was loaded.
As for network requests taking time, it's possible that your view appears before the network request is done. I suggest adding some loading indicator that you hide after the request completed.
Also, keep in mind that network requests can fail so you should deal with that by retrying the request or displaying an error message.

XCTestCase - iOS UI Tests - dealing with UITableViews with many cells

I am experimenting with the (Xcode 7) UI XCTestCase test cases and I just stumbled onto an issue with one UIView, in which I have a UITableView with many cells(4000+).
When the app is running normally, only the visible cells are rendered and there is no performance issue at all.
However, if I run the app within the context of recording a XCTestCase and I navigate to this screen, the simulator freezes, apparently because each single cell is rendered as if it were visible.
If I try to script the navigation manually and I run the XCTestCase, the test case fails right after navigating to this screen, exiting with a "UI Testing Failure - Failed to get refreshed snapshot", apparently again because all cells are being rendered and this does not finish in time.
I think this has to do with the fact that the testing framework builds an entire metamodel of the screen under display, adding each of the 4000+ cells into the view tree hierarchy.
I tried adding an expectation, hoping this would give the testing container enough time to finish rendering all cells, but this does not work.
Is there a workaround for this? Is it somehow possible to skip building part of the UI tree hierarchy or something?
My goal is being able to write UI tests for this screen.
You might be able to avoid having the entire table render, if you can use firstMatch instead of element, and also avoid count.
I had a test that checks for expected labels in the first two cells of a table. At first, I was using app.table.cells.element(boundBy: 0) and app.table.cells.element(boundBy: 1) to find the first and second cells. This was resulting in the whole table being rendered before I could access the cells.
I adapted my test to be slightly less precise, but still good enough for me (given the huge amount of time it would take otherwise). Instead, I use matching with predicates on the expected label values, with firstMatch, to find the first cells matching the criteria I want. This way the traversal stops as soon as it finds them (and since they're at the top of the table, it's quick).
Here's the code before and after.
Before (slow, yet more precise):
private func checkRhymes(query: String, expectedFirstRhyme: String, expectedSecondRhyme: String) {
let table = app.tables.element
let cell0 = table.cells.element(boundBy: 0)
let cell1 = table.cells.element(boundBy: 1)
let actualRhyme0 = cell0.staticTexts.matching(identifier: "RhymerCellWordLabel").firstMatch.label
let actualRhyme1 = cell1.staticTexts.matching(identifier: "RhymerCellWordLabel").firstMatch.label
XCTAssertEqual(expectedFirstRhyme, actualRhyme0, "Expected first rhyme for \(query) to be \(expectedFirstRhyme) but found \(actualRhyme0)")
XCTAssertEqual(expectedSecondRhyme, actualRhyme1, "Expected first rhyme for \(query) to be \(expectedSecondRhyme) but found \(actualRhyme1)")
}
Faster, but less precise (but good enough):
private func checkRhymes(query: String, expectedFirstRhyme: String, expectedSecondRhyme: String) {
let table = app.tables.firstMatch
let label0 = table.cells.staticTexts.matching(NSPredicate(format: "label = %#", expectedFirstRhyme)).firstMatch
let label1 = table.cells.staticTexts.matching(NSPredicate(format: "label = %#", expectedSecondRhyme)).firstMatch
// We query for the first cells that we find with the expected rhymes,
// instead of directly accessing the 1st and 2nd cells in the table,
// for performance issues.
// So we can't add assertions for the "first" and "second" rhymes.
// But we can at least add assertions that both rhymes are visible,
// and the first one is above the second one.
XCTAssertTrue(label0.frame.minY < label1.frame.minY)
XCTAssertTrue(label0.isHittable)
XCTAssertTrue(label1.isHittable)
}
Reference:
https://developer.apple.com/documentation/xctest/xcuielementquery/1500515-element
Use the element property to access a query’s result when you expect a
single matching element for the query, but want to check for multiple
ambiguous matches before accessing the result. The element property
traverses your app’s accessibility tree to check for multiple matching
elements before returning, and fails the current test if there is not
a single matching element.
In cases where you know categorically that there will be a single
matching element, use the XCUIElementTypeQueryProvider firstMatch
property instead. firstMatch stops traversing your app’s accessibility
hierarchy as soon as it finds a matching element, speeding up element
query resolution.
I had the same issue, and I agree it is frustrating having to wait for the entire table to load, but that is what I had to do using the following workaround.
This may not be what you are looking for but it may help others:
Basically I am counting the cells in the table 2 times consecutively if they are not equal that means the table is still loading. Put it in a loop it and do that until both counts return the same number which would mean the table is finished loading. I then put in a stop of 30 seconds so that if this takes longer than 30 seconds, the test will fail (this was enough time in my case). If your table will take longer than that you could increase the number to 180 for 3 mins etc...
let startTime = NSDate()
var duration : TimeInterval
var cellCount1 : UInt = app.tables.cells.count
var cellCount2 : UInt = app.tables.cells.count
while (cellCount1 != cellCount2) {
cellCount1 = app.tables.cells.count
cellCount2 = app.tables.cells.count
duration = NSDate().timeIntervalSince(startTime as Date)
if (duration > 30) {
XCTFail("Took too long waiting for cells to load")
}
}
//Now I know the table is finished loading and I can tap on a cell
app.tables.cells.element(boundBy: 1).tap()

Swift Accelerometer keeps crashing with ScrollView

EDIT: I have simplified the code and added calls to NSThread.isMainThread(), to see if this was the problem. See more extensive edit below
I'm working on a fairly simple app to assist a professor in research over the summer. The app intends to determine word difficulty in sentences based on the accelerometer in the iPad.
Essentially, the user will tilt the iPad, thus creating a non-zero acceleration, and the text, which is situated in a UILabel placed within a scrollView will scroll accordingly.
This works excellently 99% of the time. In almost all of our tests, it works perfectly, it goes through the entire text without issue, and nothing bad happens. Very rarely however, it just breaks, throwing an error of EXC_BAD_ACCESS. I want to stress that on the rare occasions it does break, there is no apparent pattern, it sometimes happens in the middle of scrolling, near the end, or at the start.
Obviously I would like the app to be bug free, and this is a fairly major one which I just can't figure out, so any help you can give would be greatly appreciated.
Here is the total code for my ScrollingLabel Class (the bug always happens at the end of the startScrolling class).
import Foundation
import UIKit
import QuartzCore
import CoreMotion
public class ScrollingLabel {
//Instantiation of scroll view and label
var baseTextLabel:UILabel!
var baseScrollView:UIScrollView!
var frame:CGRect!
//Instantiation of accelerometer materials
var motionManager=CMMotionManager()
var queue=NSOperationQueue()
//To rectify the issue, I have changed this to:
//var queue=NSOperationQueue.mainQueue(), SEE EDIT BELOW
init(frame:CGRect) {
/*Initializes the object by calling 3 private setup functions,
each dealing one with a specific feature of the final label, and
finally calling the scroll function to activate the accelerometer
control*/
setupFrame(frame)
setupLabel()
setupScroll()
startScrolling()
}
private func startScrolling() {
//The main accelerometer control of the label
println(NSThread.isMainQueue) //THIS RETURNS TRUE
//Allows the start orientation to become default
var firstOrientation:Bool
var timeElapsed:Double=0
if letUserCreateDefaultOrientation {firstOrientation=true}
else {firstOrientation=false}
var standardAccel:Double=0
//Begins taking updates from the accelerometer
if motionManager.accelerometerAvailable{
motionManager.accelerometerUpdateInterval=updateTimeInterval
motionManager.startAccelerometerUpdatesToQueue(self.queue, withHandler: { (accelerometerData, error:NSError!) -> Void in
println(NSThread.isMainQueue) //THIS RETURNS FALSE
//Changes the input of acceleration depending on constant control variables
var accel:Double
if self.timerStarted {
timeElapsed+=Double(self.updateTimeInterval)
}
if !self.upDownTilt {
if self.invertTextMotion {accel = -accelerometerData.acceleration.y}
else {accel = accelerometerData.acceleration.y}
}
else {
if self.invertTextMotion {accel = -accelerometerData.acceleration.x}
else {accel = accelerometerData.acceleration.x}
}
//Changes default acceleration if allowed
if firstOrientation {
standardAccel=accel
firstOrientation=false
}
accel=accel-standardAccel
//Sets the bounds of the label to prevent nil unwrapping
var minXOffset:CGFloat=0
var maxXOffset=self.baseScrollView.contentSize.width-self.baseScrollView.frame.size.width
//If accel is greater than minimum, and label is not paused begin updates
if !self.pauseScrolling && fabs(accel)>=self.minTiltRequired {
//If the timer has not started, and accel is positive, begin the timer
if !self.timerStarted&&accel<0{
self.stopwatch.start()
self.timerStarted=true
}
//Stores the data, and moves the scrollview depending on acceleration and constant speed
if self.collectData {self.storeIndexAccelValues(accel,timeElapsed: timeElapsed)}
var targetX:CGFloat=self.baseScrollView.contentOffset.x-(CGFloat(accel) * self.speed)
if targetX>maxXOffset {targetX=maxXOffset;self.stopwatch.stop();self.doneWithText=true}
else if targetX<minXOffset {targetX=minXOffset}
self.baseScrollView.setContentOffset(CGPointMake(targetX,0),animated:true)
if self.baseScrollView.contentOffset.x>minXOffset&&self.baseScrollView.contentOffset.x<maxXOffset {
if self.PRIVATEDEBUG {
println(self.baseScrollView.contentOffset)
}
}
}
})
}
}
When it does crash, it happens at the end of the startScrolling, when I set the content Offset to target X. If you need more information I am happy to provide it, but as the bug happens so rarely I don't have anything to say about specifically when it occurs or anything like that... it just seems random.
EDIT: I have simplified the code to just the pertinent parts, and added the two locations where I called NSThread.isMainQueue(). When called on the first line of startScrolling, .isMainQueue() returns TRUE, but then when called inside motionManager.startAccelerometerUpdatesToQueue it returns FALSE.
To rectify this, I have changed self.queue from just a NSOperationQueue() to NSOperationQueue.mainQueue(), and after making this switch, the second .isMainThread() call (the one inside motionManager.startAccelerometerUpdatesToQueue) now returns TRUE as we hoped for.
That's a lot of code. I don't see anything in the line that sets your content offset based on targetX.
A couple of possibilities are
baseScrollView is getting deallocated and is a zombie (unlikely since it looks like you have it defined as a regular (strong) instance variable.)
You're calling startScrolling from a background thread. All bets are off if you update UI objects from a background thread. You can check for that using NSThread.isMainThread(). Put that code in your startScrolling method, and if it returns false, that is your problem.
EDIT:
Based on your comments below in response to my answer you are calling startScrolling from a background thread.
That is indeed very likely the problem. Edit your post to show the code that is being called from a background thread, including the context. (Your "accelerometer update cycle" code).
You can't manipulate UIKit objects from a background thread, so you likely need to wrap the UIKit changes in your "accelerometer update cycle" code in a call to dispatch_async that runs on the main thread.
EDIT #2:
You've finally posted enough information so that we can help you. Your original code had you receiving acellerometer updates on a background queue. You were doing UIKit calls from that code. That is a no-no, and the results of doing it are undefined. They can range from updates taking forever, to not happening at all, to crashing.
Changing your code to use NSOperationQueue.mainQueue() as the queue that processes updates should fix the problem.
If you need to do time-consuming processing in your handler for accelerometer updates then you could continue to use the background queue you were using before, but wrap your UIKit calls in a dispatch_async:
dispatch_async(dispatch_get_main_queue())
{
//UIKit code here
}
That way your time-consuming accelerometer update code doesn't bog down the main thread but UI updates are still done on the main thread.

Resources