Reputation: 77631
OK, I have a coreData model with an Entity
called TechnicalQuery
. Like this...
TechnicalQuery
--------------
NSString *detail
NSDate *createdDate
NSString *solution
NSString *name
...
In the app is a sync process (the app is offline by spec) the people using the app will sync when they are back in the office with a connection. Anyway, that isn't important.
I've created a NSManagedObject
subclass for TechnicalQuery
using the same name.
It has the @property
detail defined as well as the @dynamic
detail.
At the moment the DB only has one technical query in it. I can see this by using the app to view the Technical Query "screen" with all the details on it etc... It shows the name, solution, detail, created date, etc... everything is there.
I can update the solution text in the app. Then when I go back later the update is still there. Core Data is working fine.
My problem comes when I sync back up to the server.
In debug this works fine. I throw the sync process off to a background thread. This thread then looks for any TQs that have been updated since the last sync and then converts them into JSON
data. It then starts another queue and queues up all the uploads for these TQs.
NOTE! At no point am I passing ManagedObjects
between threads. I am running a fetchrequest in one function and then storing the array and in the next function (same thread) processing the array. The only thing that gets passed to the next thread is the JSON
data and object specific URL that it needs to send to, no CoreData objects at all.
The JSON Data is gathered by a function in the ManagedObject
subclass file (it's actually in a category for the NSManagedObject
but you get the idea...) The function first converts the object into an NSDictionary
which matches the format required by the server and then converts it.
Anyway, in debug mode (i.e. running directly from Xcode to my iPhone 5 it works fine. The dictionary (and the upload data is all populated fine).
However, (finally got there) when running in release mode (i.e. when I profile in instruments) the function that produces the NSDictionary bombs out. It tells me that the property "detail" is nil. When I NSLog
the property it tells me it is nil (in release mode) but displays the text (in debug mode).
<Warning>: Exception! *** setObjectForKey: object cannot be nil (key: Detail)
I know the exact line that this is happening on and it is when I'm setting the object for the key in the NSMutableDictionary
.
Normally I'd check that I'm not setting the property somewhere but it is definitely set as I can go browse to the TQ page again and the detail text is displayed properly!?
I'm really not sure where to go now.
If anyone can provide any advice on where to look etc that would be awesome.
::EDIT 1::
OK, this is bizarre.
I have a strong property array (called recordArray) in the object that is collecting and processing the data.
There are two functions collectData
and processArray
. The collectData
function executes the fetch request and puts the results into recordArray. The processArray
function then iterates the array and processes each item.
When I log the data in the array in collectData
it shows all correctly.
When I log the same data from the same array in processArray
the objects are still there in the array but the properties are all null.
Thanks
::EDIT 2::
I tried getting rid of the property array and replaced it with an input/output pattern.
i.e. output array from the collectData function and then input it into the processArray function.
Still got the same result.
Really pulling my hair out with this one.
Thanks again
::EDIT 3::
Just adding some console logs from the NSLog entries.
1. Nov 29 09:56:39 Olivers-iPhone5 [2705] <Warning>: Collecting technical queries
2. Nov 29 09:56:39 Olivers-iPhone5 [2705] <Warning>: Tech Query: Name: test Detail: Test description from Olivers iPhone.
3. Nov 29 09:56:39 Olivers-iPhone5 [2705] <Warning>: pushing tech queries
4. Nov 29 09:56:39 Olivers-iPhone5 [2705] <Warning>: Tech Query: Name: (null) Detail: (null)
5. Nov 29 09:56:39 Olivers-iPhone5 [2705] <Warning>: (null)
6. Nov 29 09:56:39 Olivers-iPhone5 [2705] <Warning>: Exception! *** setObjectForKey: object cannot be nil (key: Detail)
7. Nov 29 09:56:39 Olivers-iPhone5 [2705] <Warning>: Something Went Wrong!
You can see that these are all happening in less than a second.
Line 2 is the NSLog of the name and detail property of the Tech Query from inside the collectData function.
Line 4 is the NSLog of the name and detail property of the Tech Query from inside the processArray function.
As you can see, line 4 shows null values for the properties.
Line 6 is the exception log from trying to add the detail property to an NSMutableArray. It went wrong because the detail property is null.
::EDIT 4::
Adding logs with thread IDs.
1. Nov 29 10:32:08 Olivers-iPhone5 [2749] <Warning>: Collecting technical queries. Thread: <NSThread: 0x1d263fa0>{name = (null), num = 8}
2. Nov 29 10:32:08 Olivers-iPhone5 [2749] <Warning>: Tech Query: Name: test Detail: Test description from Olivers iPhone. Thread: <NSThread: 0x1d263fa0>{name = (null), num = 8}
3. Nov 29 10:32:08 Olivers-iPhone5 [2749] <Warning>: pushing tech queries. Thread: <NSThread: 0x1d263fa0>{name = (null), num = 8}
4. Nov 29 10:32:08 Olivers-iPhone5 [2749] <Warning>: Tech Query: Name: (null) Detail: (null) Thread: <NSThread: 0x1d263fa0>{name = (null), num = 8}
5. Nov 29 10:32:08 Olivers-iPhone5 [2749] <Warning>: (null)
6. Nov 29 10:32:08 Olivers-iPhone5 [2749] <Warning>: Exception! *** setObjectForKey: object cannot be nil (key: Detail)
7. Nov 29 10:32:08 Olivers-iPhone5 [2749] <Warning>: Something Went Wrong!
You can see from here that I am definitely not passing anything between threads. This is all happening on the same thread.
Thanks again.
::EDIT 5::
Just to show you how I'm not making this up, here are the logs from the debug build...
1. 2012-11-29 10:36:08.471 [2767:161f] Collecting technical queries. Thread: <NSThread: 0x1cd52fb0>{name = (null), num = 8}
2. 2012-11-29 10:36:08.474 [2767:161f] Tech Query: Name: test Detail: Test description from Olivers iPhone. Thread: <NSThread: 0x1cd52fb0>{name = (null), num = 8}
3. 2012-11-29 10:36:08.474 [2767:161f] pushing tech queries. Thread: <NSThread: 0x1cd52fb0>{name = (null), num = 8}
4. 2012-11-29 10:36:08.475 [2767:161f] Tech Query: Name: test Detail: Test description from Olivers iPhone. Thread: <NSThread: 0x1cd52fb0>{name = (null), num = 8}
5. 2012-11-29 10:36:08.476 [2767:161f] Test description from Olivers iPhone.
6. 2012-11-29 10:36:08.483 [2767:1623] Uploading to url <I can't put the URL here as it's private>
7. 2012-11-29 10:36:08.906 [2767:520f] Upload Done
This is exactly the same code. The only difference is that this is running in debug mode and the logs are copied from Xcode instead of Organiser device logs.
Upvotes: 4
Views: 413
Reputation: 4285
Whilst I cannot answer exactly what your issue was, this issue came up for me and it turned out that non-main threads were not keeping the Managed Object Contexts retained in optimised whilst somehow they were in debug. By using the current NSThread's threadDictionary we keep the managed object context around throughout the threads lifecycle and the issue was resolved.
Upvotes: 3
Reputation: 8512
I don't know the final answer, but this may help you get closer to solution.
What we know is that there is different behavior on Debug and Release configurations. You should check all diferences in Build Settings and try to play with those that differ.
I had once similarly strange problem on Release. After changing Optimization Level to “Fastest, Smallest”, the bug was reproducable also on Debug.
Upvotes: 1
Reputation: 4339
Fogmeister,
You haven't really given us much information. As such, anyone will be guessing.
First, you can debug release versions of your code. Just change the configuration profile in your Xcode scheme.
Second, what changes in your code when you switch to release mode? Why would the change in a debug compile time flag change your product. (As Core Data doesn't change when you throw your DEBUG flag, it isn't most likely the problem.)
To help you further, the SO community typically needs to see some code. If you share some, folks will probably look at it to help you.
Andrew
Upvotes: 0