#property (nonomic,retain) CMMotionManager *motionManager; //delcare as a property.
motionManager = [[CMMotionManager alloc] init]; //init it.
motionManager.accelerometerUpdateInterval = 0.2f;
All below perform in a thread(not main thread).
-(void)handle{
[motionManager startAccelerometerUpdates];
while (1) {
CMAcceleration acceleration = motionManager.accelerometerData.acceleration;
NSLog(#"%f %f %f",acceleration.x,acceleration.y,acceleration.z);
sleep(0.5);
}
}
When I run the app in Xcode -> Instruments, I found the Living Memory increase uninterruptly,
until the app recieved memory warming and killed by system.
I try to relase the accelerometerData in while block. but make no effect. motionManager.accelerometerData release];
I don't wish to use startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler:^(CMAccelerometerData *accelerometerData,NSError *error), becuase I want to run it in background,and this block make no function when the app be suspended.
Can anyone help me?
screenshot image:http://img.blog.csdn.net/20130702120140593
Are you using ARC? You should use it.
You must also make sure your bakground thread has an autorelease pool in place. The syntax for creating an autorelease pool with ARC enabled is #autorelease { ... } and the syntax without ARC is NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ... [pool release];.
Apple has excellent documentation on how autorelease pools work. One is created automatically for the main thread but you must manually create it for background threads. You need to spend a couple of hours learning how it works, it's mandatory learning for any obj-c programmer.
Without seeing all your code, I can't tell you how it needs to work... but most likely the block or method you create the thread with needs it's contents wrapped in an autorelease pool and also the contents of your while loop needs a second autorelease pool.
EDIT: now that I've seen your code, you here is an example of how #autoreleasepool must be used to avoid leaking memory. I added line 6 and 23 to this code: https://gist.github.com/abhibeckert/5907754
I haven't tested, but that should solve your problem. It will definitely leak memory without those autorelease pools.
Basically if you have a background thread or long while loop, each needs to have it's own autorelease pool. I recommend reading this: http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
Related
I have ARC enabled in my app and noticed that if I create a ton of images, my app would crash. As part of my investigation, I created a small project that reproduces the issue which can be found here. The meat of the sample project code is the following:
int width = 10;
int height = 10;
uint8_t data[100];
while (true)
{
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate(data, width, height, 8, width, colorspace, kCGBitmapByteOrderDefault | kCGImageAlphaNone);
CGImageRef cgimage = CGBitmapContextCreateImage(context);
// Remove this line and memory is stable, keep it and you lose 15-20 MB per second. Why?
UIImage* uiimage = [UIImage imageWithCGImage:cgimage];
CGImageRelease(cgimage);
CGContextRelease(context);
CGColorSpaceRelease(colorspace);
}
While running this code, the sidebar in Xcode will show the total memory of the app increasing at around 15-20 MB per second. If you comment out the line that creates the UIImage, the leak disappears.
There are a number of questions on Stack Overflow about whether or not you should release a CGImage after creating a UIImage via imageWithCGImage, and it doesn't look like there is a real consensus. However, if I don't call CGImageRelease(cgimage), then the memory usage increases by over 100 MB per second, so I'm certain that manually releasing the image is the correct thing to do.
Since I have ARC enabled, I tried setting uiimage to nil after releasing everything, which didn't work. Not storing the return value of the call to imageWithCGImage: also doesn't prevent the leak.
Is there something fundamental I'm missing about how to use Core Graphics?
Is there something fundamental I'm missing about how to use Core Graphics?
It seems more likely that you are missing something fundamental about memory management.
Many Foundation / Cocoa framework commands, especially those that create ready-made objects, make objects that are autoreleased. That means you don't have to release the object, because it will be released later, automatically, when you are done with it. But how is that possible? Such objects go into the autorelease pool and, once their retain count drops to zero, they are drained later on, when there is an opportunity. But you are looping continuously, so there is no such opportunity. So you need to wrap your troublesome line in an #autoreleasepool{} block so as to construct and drain your own pool.
Also note that there can be intermediate autoreleased objects of which you are unaware. The autorelease pool can help with those too.
See this section of my book for more information about autoreleased objects.
In most of my interviews, I've been asked about web services and multithreading. I've done neither, so I decided to learn more about Web Services and Multithreading using Grand Central Dispatch.
For web services, the way that I understand it is that you need to fetch the data using a class such as NSURLConnection. basically setup a new NSURL, then a connection, then a request. You also need to make use of the API's methods such as didConnect, didReceiveData, and didFailLoadWithError. After you receive the data, which is generally in JSON or XML format and stored as an NSData object, you can store it and parse through it. There are multiple ways to parse through it, such as by using SBJSON or NSXMLParser. You can then do with it what you need.
For multithreading, Grand Central Dispatch is a c-style way of multithreading. Basically, you use it when you need to do heavy hauling away from the main thread to avoid the app freezing. You can dispatch synchronously or asynchronously. Asynchronously means that the method on the main thread will continue executing, synchronously means that it will not. You never need to use GCD alongside with NSURLConnection, because NSURLConnection already does its work in the background then calls upon delegates in the main thread. But, for saving and unzipping files, you should use GCD. When you call dispatch_async, you pass in a dispatch queue. You can use either a serial queue or a concurrent queue. A serial queue will execute tasks in the queue one at a time, in the order that they arrived. It is the default setting. With concurrently queues, tasks executed concurrently might be executed at the same time.
My first question is, do I have a proper understanding of these two concepts? I know that there is a lot to learn about GCD, but I just want to make sure that I have the basic ideas correct. Also, with GCD, why would someone ever want to dispatch synchronously, wouldn't that defeat the purpose of multithreading?
The only reason to dispatch synchronously is to prevent the current code from continuing until the critical section finishes.
For example, if you wanted to get some value from the shared resource and use it right away, you would need to dispatch synchronously. If the current code does not need to wait for the critical section to complete, or if it can simply submit additional follow-up tasks to the same serial queue, submitting asynchronously is generally preferred.
You can make synchronous request and dispatch it by using dispatch_async or dispatch_sync call. It will totally run in background.
-(void)requestSomething:(NSString *)url
{
NSString *queue_id = #"queue_identifier";
dispatch_queue_t queue = dispatch_queue_create([queue_id UTF8String], 0);
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
NSError *serviceError = nil;
NSURLResponse *serviceResponse = nil;
NSData *dataResponse = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&serviceResponse error:&serviceError];
if(serviceError)
{
dispatch_sync(main, ^{
// Do UI work like removing indicator or show user an alert with description of error using serviceError object.
return;
});
}
else
{
// Use dataResponse object and parse it as this part of code will not executed on main thread.
dispatch_sync(main, ^{
// Do UI work like updating table-view or labels using parsed data or removing indicator
});
}
});
// If your project is not developed under ARC mechanism, add following line
dispatch_release(queue);
}
I make some non-essential changes to the database in a background thread (shortly after app launch), and then merge them into the main context. The background thread can end up making a lot of changes, but I don't want the context save to trip up over some validation errors or some inscrutable Core Data exception in this background processing; especially since I use iCloud with Core Data, users can end up with nilled-out relationships and what not. I just want the app to keep running instead of throwing an exception and quitting.
In this case, does it make sense to have a #try-#catch block around the context save? Are there any performance or memory management issues with doing this?
Something like this:
#try {
[context performBlockAndWait: ^{
NSError *error = nil;
if ([context save:&error]){
NSLog(#"Child context saved");
[context.parentContext performBlockAndWait:^{
NSError *parentError = nil;
if ([context.parentContext save: &parentError]){
NSLog(#"Parent context saved");
}
}];
}
}];
} ....
My app ships to thousands of customers, so it would be great to know before-hand if this could cause more problems than it solves.
What exceptions are being thrown?
Since -[NSManagedObjectContext save:] uses the NSError out-parameter pattern, I would generally expect it NOT to throw. However, the general pattern in Cocoa is that exceptions are "death" and not considered recoverable.
There are places in various system frameworks that throw and catch exceptions (which you can see by setting an exception-throw breakpoint in the debugger) -- I'm looking at you Cocoa bindings -- but generally speaking if an exception bubbles up to your app's code, you're already "dead in the water."
Are there any performance or memory management issues with doing this?
These days, the performance penalty for a #try/#catch/#finally is pretty minimal (this wasn't always the case). There are memory management implications to be sure (which is probably why exceptions are generally "death" on this platform.) If you're using ARC and exit a scope by way of an exception being thrown, retains taken by ARC are not released. As described here:
The standard Cocoa convention is that exceptions signal programmer
error and are not intended to be recovered from. Making code
exceptions-safe by default would impose severe runtime and code size
penalties on code that typically does not actually care about
exceptions safety. Therefore, ARC-generated code leaks by default on
exceptions, which is just fine if the process is going to be
immediately terminated anyway. Programs which do care about recovering
from exceptions should enable the option.
In short, there's probably no point in wrapping a context save operation in a #try/#catch block.
ABAddressBookRef can only be accessed by one thread. I think a good model would be having a thread for ABAddressBookRef in the background, besides the main thread.
How can I ensure that there's only one thread while using NSOperationQueue? Simply setting max concurrency to 1 won't guarantee it to be run on the same thread.
Should I use other unique threads like web threads?
You can manually create a thread and redirect all address book access to it.
You create a thread with something like this (adapted from documentation):
NSThread* myThread = [[NSThread alloc] initWithTarget:[MyThread new]
selector:#selector(myThreadMainMethod)
object:nil];
[myThread start]; // Actually create the thread
Note that for the thread to be useful, you have to implement a run loop in thread's main method.
See example implementation of run loop in this answer.
You are then able to do stuff on this thread using the NSObject's method performSelector:onThread:withObject:waitUntilDone:.
Here's a wrapper library for ABAddressBookRef that implements this concept – RHAddressBook.
I am going crazy trying to figure this out. I am working on an application that is syncing up data from the webserver. There is a background thread that is pulling data from the server to the application. At the same time I am making changes to the UI. The values changed on UI are being saved to core data in foreground.
Through out the application I have one managedObjectContext that I fetch from the app delegate every time I create a fetchController . App delegate code
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil) {
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
Now the problem is I am getting error while trying to save the context. The errors are happening randomly in the code. I am saving the context as soon as I am making change to any entity. Also I have two relationships each in each entity one to its child that is one to many and one to its parents that is to - one. All relationship have appropriate inverse.
I think I am doing something conceptually wrong over here by mentaining one context. Could you please advice how I should manage context in a situation where both background and foreground threads are reading and writing to the coredata. Thanks.
Managed object contexts are not thread safe, so if you use the same one on more than one thread without considering concurrency-- you're going to have major problems. As in, crashing and/or data loss and maybe even data corruption. There are a couple of ways to deal with this:
Use one of the queue concurrency types when creating the context-- see docs for initWithConcurrencyType:. Then, whenever you access the data store, use either performBlock: or performBlockAndWait: to synchronize access.
Create a new managed object context for the background thread. Use NSManagedObjectContextDidSaveNotification and mergeChangesFromContextDidSaveNotification: to keep multiple contexts synchronized.
But whatever you do, do not just use one managed object context on more than one thread.