Bug 7723 - NSDictionary enumeration is returning empty/null key randomly
Summary: NSDictionary enumeration is returning empty/null key randomly
Status: VERIFIED DUPLICATE of bug 19718
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime ()
Version: 6.0.x
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Mark Probst
URL:
: 16208 ()
Depends on: 19718
Blocks:
  Show dependency tree
 
Reported: 2012-10-08 10:19 UTC by Michal
Modified: 2014-09-05 08:11 UTC (History)
10 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Sample app (8.73 KB, application/zip)
2012-10-08 10:19 UTC, Michal
Details
smaller test case (6.12 KB, application/zip)
2013-07-18 09:35 UTC, Sebastien Pouliot
Details
patch for maccore to log extra info (1.21 KB, patch)
2013-07-18 09:37 UTC, Sebastien Pouliot
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
VERIFIED DUPLICATE of bug 19718

Description Michal 2012-10-08 10:19:43 UTC
Created attachment 2707 [details]
Sample app

When trying to enumerate NSDictionary returned from NSHttpUrlResponse.AllHeaderFields, the returned KeyValuePair or just Key(NSString) is sometimes (randomly) null/with zero handle.

To test it, open attached sample, and change url in AppDelegate.cs file on line 243 to point to some server (the best is on local network, I'm not sure if the same can happen on internet servers, maybe the speed is causing the problem). Run app (also happen on simulator) and start Test 2. After few (thousands) of request, app should write something like this to console (2012-10-08 16:12:22.886 NSDictEnumeration[1713:5803] 0/7). You should put a breakpoint on line 226 and when hit, examine 'key' object. It should be not initialized NSSstring with zero Handle. The problem is occuring when using MT 5.4 or the latest 6 and was not present in previous MT versions (e.g. 5.2.13).

There is also Test 1, which (after few thousands rounds) ends with something like this (found as a sideeffect when searching for smallest sample for test 2, maybe related):

2012-10-08 14:46:26.452 NSDictEnumeration[1613:5803] 58000
NSDictEnumeration(1613,0xb05e9000) malloc: *** mmap(size=2097152) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Stacktrace:

  at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging.intptr_objc_msgSend (intptr,intptr) <IL 0x00026, 0xffffffff>
  at MonoTouch.Foundation.NSString.FromHandle (intptr) [0x00012] in /Developer/MonoTouch/Source/monotouch/src/shared/Foundation/NSString.cs:159
  at MonoTouch.Foundation.NSString.ToString () [0x00017] in /Developer/MonoTouch/Source/monotouch/src/shared/Foundation/NSString.cs:137
  at NSDictEnumeration.AppDelegate/MyDicClass..ctor (MonoTouch.Foundation.NSDictionary) [0x00021] in /Users/michalsartoris/Projects/iOS/Bugs/NSDictEnumeration/NSDictEnumeration/AppDelegate.cs:90
  at NSDictEnumeration.AppDelegate.OnTest () [0x00049] in /Users/michalsartoris/Projects/iOS/Bugs/NSDictEnumeration/NSDictEnumeration/AppDelegate.cs:110
  at System.Threading.Thread.StartInternal () [0x0001d] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System.Threading/Thread.cs:697
  at (wrapper runtime-invoke) object.runtime_invoke_void__this__ (object,intptr,intptr,intptr) <IL 0x0004e, 0xffffffff>

Native stacktrace:

	0   NSDictEnumeration                   0x0009573c mono_handle_native_sigsegv + 284
	1   NSDictEnumeration                   0x0000c028 mono_sigsegv_signal_handler + 248
	2   libsystem_c.dylib                   0x987ec86b _sigtramp + 43
	3   ???                                 0xffffffff 0x0 + 4294967295
	4   Foundation                          0x01965722 bytesInEncoding + 264
	5   Foundation                          0x01965615 -[NSString(NSStringOtherEncodings) UTF8String] + 42
	6   CoreFoundation                      0x01316fe2 -[__NSCFString UTF8String] + 82
	7   ???                                 0x0c7e6b73 0x0 + 209611635
	8   ???                                 0x10be28d8 0x0 + 280897752
	9   ???                                 0x10be2840 0x0 + 280897600
	10  ???                                 0x10be226c 0x0 + 280896108
	11  ???                                 0x10bdcc2c 0x0 + 280874028
	12  ???                                 0x10bdc44e 0x0 + 280872014
	13  ???                                 0x0b4ebba0 0x0 + 189709216
	14  NSDictEnumeration                   0x000103e2 mono_jit_runtime_invoke + 722
	15  NSDictEnumeration                   0x00173c7e mono_runtime_invoke + 126
	16  NSDictEnumeration                   0x00173dec mono_runtime_delegate_invoke + 140
	17  NSDictEnumeration                   0x001d3802 start_wrapper + 482
	18  NSDictEnumeration                   0x0020571a thread_start_routine + 154
	19  NSDictEnumeration                   0x001b0ab0 gc_start_thread + 80
	20  libsystem_c.dylib                   0x98800557 _pthread_start + 344
	21  libsystem_c.dylib                   0x987eacee thread_start + 34
Comment 1 Michal 2012-10-08 10:20:55 UTC
One more note: happens with SGen GC.
Comment 2 Rolf Bjarne Kvinge [MSFT] 2012-10-08 19:33:15 UTC
I can reproduce this, but only when SGen is enabled.

Rodrigo, I believe this is your area :)
Comment 3 Michal 2012-10-16 04:44:16 UTC
Rewritting the probelmatic code like this:

var allKeysSelHandle = MonoTouch.ObjCRuntime.Selector.GetHandle("allKeys");
var allKeysPtr = MonoTouch.ObjCRuntime.Messaging.IntPtr_objc_msgSend(headers.Handle, allKeysSelHandle);
using(var allKeys = (NSArray)MonoTouch.ObjCRuntime.Runtime.GetNSObject(allKeysPtr))
{
	for (int i = 0; i < allKeys.Count; i++)
	{
		NSObject key;
		IntPtr ptr;
		try
		{
			ptr = allKeys.ValueAt((uint)i);
			using(key = (NSObject)MonoTouch.ObjCRuntime.Runtime.GetNSObject(ptr))
			{
				_headers.Add(key.ToString(), headers[key].ToString());
			}
		}
		catch(Exception ex)
		{
			Console.WriteLine(ex);
		}
	}
}

I was able to pass one million iterations (two times) without problem. But if value from ValueAt is passed directly (without variable) into GetNSObject, the problem still occurs:

 using(key = (NSObject)MonoTouch.ObjCRuntime.Runtime.GetNSObject(allKeys.ValueAt((uint)i)))

This reminds me similar problems of older MT versions (if I remember it right)  where objects passed directly from one method to another without intermediate variable were sometimes GC'ed. Maybe this can help.
Comment 5 Valerio 2012-10-18 09:28:42 UTC
We are experiencing the same problem, developing a solution for our customer.
The situation is becoming critical for us, haven't you find a resolution?
Regards.
Comment 6 Rolf Bjarne Kvinge [MSFT] 2012-10-18 17:44:33 UTC
Valerio, try disabling sgen for now. GC bugs are in general very tricky and it takes time to fix them.
Comment 7 Rodrigo Kumpera 2012-11-30 11:09:07 UTC
Hi guys,

I cannot reproduce the bug, so please check if I did the right thing:

Using MonoTouch 6.0.6 with MD 3.0.5;
Set the project to Release/iPhone;
Change project settings to use sgen;
Change url to point to my IP at port 8080;
Fire xsp locally (type xsp4 from any directory);
Compile & deploy to an iPad 2 with iOS 6.0; and
Fire test 2 and wait.

I got to 37000 iterations with no error messages.
Comment 8 Rolf Bjarne Kvinge [MSFT] 2012-11-30 19:08:28 UTC
I can still reproduce this, with MT 23bf566c46c1ca9d8465239a57514c2380ef90ab and the simulator.

Note that the lines indicating errors do not stand out very much in the application output, it's easy to overlook them.

If you change these CWLs:

Console.WriteLine("{0}/{1}", i, xxx.Count);

into:

Console.WriteLine("{0}/{1}: {2}", i, xxx.Count, ex.Message);

They stand out a lot more and they're harder to miss.
Comment 9 Rolf Bjarne Kvinge [MSFT] 2012-11-30 19:13:45 UTC
I did:
* Start xsp2 in any directory
* Change the ip to 127.0.0.1:8080
* Run.

I did not change configuration, nor did I have to turn on sgen (it's already turned on for Debug|iPhoneSimulator).

Test 1 failed in ~2000 iterations, Test 2 varied a bit (between 200 and 2000, depending on the run).
Comment 10 Michal 2012-12-03 03:55:22 UTC
1. CWLs: I have breakpoint on line 260 (inside catch) to know about problem, so this may caused I did not focus on output. Sorry.

2. Rolf's steps also work for me, test 2 failing within few seconds (it was about 5000-20000 iters).

3. As my workaround (mantioned above) seemed to work with single thread, it was not working when using with multiple threads. But this seems to work also with multiple threads:

Instead of this: key = (NSObject)MonoTouch.ObjCRuntime.Runtime.GetNSObject(ptr), create NSObject directly: key = new NSObject(ptr).
Comment 11 Sebastien Pouliot 2013-07-16 13:43:23 UTC
As far as "Test 1" is concerned I do not see a difference with using (or not) sgen for the GC (using Mono-3.0 based Xamarin.iOS 6.3.x).

OTOH there's an issue using the `NSDictionary.Keys` property where it will leak memory (easy to see using Instruments). The sample code calls it several time and fails (for me) around 74k iterations, with an error message near-identical to the original description:

2013-07-16 12:16:03.969 NSDictEnumeration[52780:6603] 74100
NSDictEnumeration(52780,0xb06ed000) malloc: *** mmap(size=16777216) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug

That part can be worked around by avoiding the Keys property. E.g. a foreach loop would hit this condition much less often and would run all of "Test 1" loop:

	foreach (var kvp in nsdic) {
		_dic.Add (kvp.Key.ToString (), kvp.Value.ToString ());
	}
Comment 12 Sebastien Pouliot 2013-07-16 14:15:44 UTC
The "leak" is caused by the use of the (only) NSAutoreleasePool. Since this is a tight loop everything gets tracked by the thread's autoreleasepool (and never gets drained before we run out of memory).

Adding an additional NSAutoreleasePool, which will get drained and release memory periodically (once ever iteration from NSDictionary to MyDicClass), completely fix the "leak".

E.g.

	using (var ns = new NSAutoreleasePool ()) {
		NSObject key;
		for (int i = 0; i < nsdic.Count; i++)
		{
			try
			{
				key = nsdic.Keys[i];
				_dic.Add(key.ToString(), nsdic[key].ToString());
			}
			catch (Exception e)
			{
				Console.WriteLine("{0}/{1} {2}", i, nsdic.Count, e.Message);
			}
		}
	}

E.g. 2:

	using (var ns = new NSAutoreleasePool ()) {
		foreach (var kvp in nsdic) {
			_dic.Add (kvp.Key.ToString (), kvp.Value.ToString ());
		}
	}
Comment 13 Sebastien Pouliot 2013-07-17 09:11:01 UTC
a. Test #2 still fails when executed with sgen, generally pretty fast, e.g. it can happen within the first 100 iterations:

> 2013-07-17 09:05:44.434 NSDictEnumeration[65153:6903] Iter #0: 


b. Test #2 also fails under Boehm, not just sgen. It takes a lot more iterations under Bohem, e.g.

> 2013-07-17 08:49:54.249 NSDictEnumeration[65061:5e07] Iter #56000: 


c. Test #2 only fails when execute on a separate thread. E.g. by changing one line:

//	_btn2.TouchUpInside += (sender, e) => { EnableButtons(false); var thread = new System.Threading.Thread(OnTestNet); thread.Start(); };
	_btn2.TouchUpInside += (sender, e) => { EnableButtons(false); OnTestNet (); };

I was able to run the sample (w/sgen) up to 103300 iterations before stopping it, e.g.

> 2013-07-17 08:15:09.774 NSDictEnumeration[61324:a0b] Iter #103300:


That tells us that:

* it's not an issue with NSDictionary (or we would be able to duplicate it using Test #1). It's likely relate to how the NSUrl* types works;

* it's unlikely to be GC related;

* it's very likely threading related;
Comment 14 Sebastien Pouliot 2013-07-17 10:00:29 UTC
As a workaround copying the headers inside the main thread seems to work fine.

NSRunLoop.Current.InvokeOnMainThread (() => {
	foreach (var kvp in headers) {
		_headers.Add (kvp.Key.ToString (), kvp.Value.ToString ());
	}
});

E.g. more than 100k iterations using sgen without failure.

2013-07-17 09:42:19.119 NSDictEnumeration[65273:6403] Iter #118700:
Comment 15 Sebastien Pouliot 2013-07-18 09:35:01 UTC
Created attachment 4367 [details]
smaller test case

Rodrigo, it really looks like a GC issue after all (maybe the NRE from Boehm is different or the issue affects both).

To duplicate:
* download my attachment, it's a smaller/simpler version of the original;
* ensure the GC is set to sgen (boehm takes a lot more time to reach an NRE);
* start xsp;
* build/run it for Debug|Simulator (no device needed) using any XI version (e.g. 6.9.4 can reproduce it);
* click on Test2, wait... most times it's quick, some times it takes longer

You'll get a bunch of lines showing index, handles and a reference count then… you'll get the NRE. The last CWL line will look like:
2013-07-18 09:28:55.301 NSDictEnumeration[16064:6403] 3 0 0
Comment 16 Sebastien Pouliot 2013-07-18 09:37:21 UTC
Created attachment 4368 [details]
patch for maccore to log extra info

Now patch your maccore tree with the attached patch. It simply add some logging so that:

* Shows every T is added to the T[] array. We know that they are all valid when added (and print each handle);

* Once the array is populated we iterate it again to check its content. We print a "zomg" if an handle is null (this does not always get hit, i.e. it can pass there and fail later like shown below).

* It shows a stack trace when NSObject.Dispose is called (you can disable it, it's faster)

Next rebuild monotouch and try again. You'll get a log showing something like:

2013-07-17 23:03:11.029 NSDictEnumeration[88084:6403] key #0 ptr 6040016 handle 6040016 rc -1
2013-07-17 23:03:11.030 NSDictEnumeration[88084:6403] key #1 ptr 6040616 handle 6040616 rc -1
2013-07-17 23:03:11.030 NSDictEnumeration[88084:6403] key #2 ptr 358242208 handle 358242208 rc 4
2013-07-17 23:03:11.030 NSDictEnumeration[88084:6403] key #3 ptr 6039456 handle 6039456 rc -1
2013-07-17 23:03:11.030 NSDictEnumeration[88084:6403] key #4 ptr 6039536 handle 6039536 rc -1
2013-07-17 23:03:11.031 NSDictEnumeration[88084:6403] key #5 ptr 6039616 handle 6039616 rc -1
2013-07-17 23:03:11.031 NSDictEnumeration[88084:6403] key #6 ptr 6039256 handle 6039256 rc -1
2013-07-17 23:03:11.031 NSDictEnumeration[88084:6403] key #7 ptr 6039296 handle 6039296 rc -1
2013-07-17 23:03:11.031 NSDictEnumeration[88084:6403] 0 6040016 -1
2013-07-17 23:03:11.031 NSDictEnumeration[88084:6403] 1 6040616 -1
2013-07-17 23:03:11.032 NSDictEnumeration[88084:2203] Dispose (False) Handle 6039536    at System.Environment.get_StackTrace() in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System/Environment.cs:line 261
   at MonoTouch.Foundation.NSObject.Dispose(Boolean disposing) in /Developer/MonoTouch/Source/monotouch/src/shared/Foundation/NSObject2.cs:line 483
   at MonoTouch.Foundation.NSString.Dispose(Boolean disposing) in /Developer/MonoTouch/Source/monotouch/src/Foundation/NSString.g.cs:line 663
   at MonoTouch.Foundation.NSObject.Finalize() in /Developer/MonoTouch/Source/monotouch/src/shared/Foundation/NSObject2.cs:line 89
2013-07-17 23:03:11.032 NSDictEnumeration[88084:2203] Dispose (False) Handle 358231360    at System.Environment.get_StackTrace() in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System/Environment.cs:line 261
   at MonoTouch.Foundation.NSObject.Dispose(Boolean disposing) in /Developer/MonoTouch/Source/monotouch/src/shared/Foundation/NSObject2.cs:line 483
   at MonoTouch.Foundation.NSString.Dispose(Boolean disposing) in /Developer/MonoTouch/Source/monotouch/src/Foundation/NSString.g.cs:line 663
   at MonoTouch.Foundation.NSObject.Finalize() in /Developer/MonoTouch/Source/monotouch/src/shared/Foundation/NSObject2.cs:line 89
2013-07-17 23:03:11.033 NSDictEnumeration[88084:6403] 2 358242208 4
2013-07-17 23:03:11.033 NSDictEnumeration[88084:6403] 3 6039456 -1

then NullReferenceException


we see that:

* we got the NRE after checking item #3;

* key #4 was added to the T[] and had a valid Handle at that time;

2013-07-17 23:03:11.030 NSDictEnumeration[88084:6403] key #4 ptr 6039536 handle 6039536 rc -1

* Just after #1 and before #2 Dispose was called with False on that same Handle - which should still be referenced (as a member of the array). Since Dispose called with 'False' this comes from the GC (and the stack trace shows it comes from ~NSObject);

2013-07-17 23:03:11.032 NSDictEnumeration[88084:2203] Dispose (False) Handle 6039536    at 

Somehow the GC decided it could do without that instance…

note: this can all happen inside the NSArray.ArrayFromHandle<T> method.
Comment 17 Rodrigo Kumpera 2013-07-18 14:13:19 UTC
Mark, could try Sebastien's repro and see what's going on?
Comment 18 Mark Probst 2013-07-18 20:28:58 UTC
Does the output look different when it crashes in Boehm vs SGen?
Comment 19 Mark Probst 2013-07-19 14:13:01 UTC
This throws an NRE for me almost immediately both on Boehm as well as SGen.  The fact that the reference in question is null, not some random, invalid pointer, is evidence that this is not a GC issue.  I'll try to simplify the test case.
Comment 20 Sebastien Pouliot 2013-07-19 14:21:22 UTC
An NRE with Boehm always took me between 10x-100x more time/iterations than sgen.

The fact that it's null is because the object Dispose(false) was called (from the finalizer). That changes the internal handle to IntPtr.Zero and that's why the sample fails with a null (not random) value later. However the finalizer should not have been called for an object that was referenced (inside an array).
Comment 21 Mark Probst 2013-07-19 14:51:08 UTC
The last output before the NRE in my case, however, is

2013-07-19 11:19:39.090 NSDictEnumeration[15184:5307] 1 0 0
Comment 22 Sebastien Pouliot 2013-07-19 15:09:22 UTC
Normal, looks like I missed that last line in my copy/paste. The CWL was added just before the NRE location.

It means `keys[1]` has an an NSObject with a Handle of IntPtr.Zero (the 2nd `0`). That will make NSString returns null (and lead to the NRE).

The above logs should show what the original handle, when it was added to the `keys` array.
Comment 23 Rolf Bjarne Kvinge [MSFT] 2013-11-14 09:42:57 UTC
So what I believe is happening is the following:

* A managed NSString is created (for the native object 0xdeadf00d), used, and forgotten about.
* The GC realizes that managed NSString instance can be freed, and queues it for finalization.
* The native 0xdeadf00d pointer pops up again, and we fetch the managed object from our weak ref hash table.
* The finalization threads gets around to finalizing the managed NSString instance.
* The main thread now sees a disposed NSString instance.

Rodrigo, didn't you have a POC for a fix for this problem? I certainly sounds like it's something we've looked at before.
Comment 24 Rolf Bjarne Kvinge [MSFT] 2013-11-14 09:43:10 UTC
*** Bug 16208 has been marked as a duplicate of this bug. ***
Comment 25 Rolf Bjarne Kvinge [MSFT] 2013-11-14 09:43:57 UTC
Bug #16208 might have an easier test case to reproduce this.
Comment 26 Rolf Bjarne Kvinge [MSFT] 2014-05-13 07:48:46 UTC
A new internal bug has been opened to track the fix (#19718), since the resolution will involve internal implementation details.

This bug will automatically be updated/notified when bug #19718 is fixed.

*** This bug has been marked as a duplicate of bug 19718 ***
Comment 27 Ram Chandra 2014-08-05 10:01:14 UTC
I have checked this issue with following builds:

Mac OS X 10.8.4
Xamarin Studio:5.3 (build 412)
Xcode 5.1.1 (5085)
Xamarin.iOS: 7.4.0.87 (Enterprise Edition)

Build Information 
Release ID: 503000412
Git revision: 77e042831804079a649ee83092ed36c7c10773a2
Build date: 2014-08-01 06:32:22-04
Xamarin addins: 57e379e6a9454a1c0d97aa3f770e7ae7cc16c522

To check this issue, I have deployed the application on device and tap "Start cycle" button and after few minutes, I have tapped the "Stop cycle" button and when I check the status I am not getting any error. 

The status result is:

Iterations: 210093 
Error getting Hello : 0
Error getting Bye : 0
Error native Hello: 0
Errors native Bye: 0

This issue has been fixed. Hence, I am closing this issue.
Comment 28 vishnu sharma 2014-09-05 07:36:16 UTC
@RamChandra I don't see the issue is fixed.

I am using the latest things 
Xamarin Studio Version 5.3 (build 439)
Xamarin.Mac Version: 1.10.0.9 (Enterprise Edition)

But in my mac project I am facing the same issue very frequently but very randomly also.

Some time it just pass the value for key but some time randomly crashes with "NullPointerException"


My code is: 

NSString nodeJson = new NSString (serverCommunicator.getDataJson (path));     /* getDataJson method returns a JSON string received from server. */
NSDictionary nodeDict = new NSDictionary ();
nodeDict = (NSDictionary)MonoMac.Foundation.NSJsonSerialization.Deserialize (nodeJson.DataUsingEncoding (NSStringEncoding.UTF8), NSJsonReadingOptions.MutableContainers, new NSError ());

var prefSpecifierDict = nodeDict[(NSString)"message"] as NSDictionary;
tempChildrenArray = prefSpecifierDict[(NSString)"children"] as NSMutableArray;
	
foreach (var prefItem in NSMutableArray.FromArray<NSDictionary> (tempChildrenArray)) {
							if (prefItem.ContainsKey (new NSString ("name"))) {
								currentNodeNameArray.Add (prefItem [(NSString)"name"] as NSString);
						}
					}



You just can not close any issue if its nor reproduced on your side while other people are facing it  and mostly you just mark the issue as duplicate and close it. Lets keep the conversation running.

Vishnu Sharma
Comment 29 Rolf Bjarne Kvinge [MSFT] 2014-09-05 07:41:30 UTC
@Vishnu: the fix hasn't reached Xamarin.Mac yet, for now it's only in Xamarin.iOS. It will be included in a future release (at this time I don't know which version number that release will have).
Comment 30 vishnu sharma 2014-09-05 07:52:29 UTC
@Rolf any workaround for this issue ? Because I am at critical point in project and the app just crash randomly and if I add this code in Try catch block it miss that particular value that is not acceptable in my case.

Thanks
Vishnu Sharma
Comment 31 Rolf Bjarne Kvinge [MSFT] 2014-09-05 08:06:02 UTC
@Vishnu:

Try making all the NSString conversions static variables instead.

So instead of (NSString)"message", you have a static NSString variable:

    static NSString message_str = "message";

and do it for all the conversions.
Comment 32 Yuri Tikhomirov 2014-09-05 08:11:06 UTC
@Vishnu, there's some workaround I used in Xamarin.iOS (see below).

Also I'm not sure you're doing it right with Xamarin/C#/JSON.

There is a great tool named Newtonsoft Json.NET:
https://json.codeplex.com/

It bring very powerful C#-oriented JSON processing and helps to avoid dealing with native strings (NSString).

Meanwhile, the workaround code (the function is used to extract the string from NSDictionary):

		private static readonly IntPtr sel_ObjForKey = Selector.GetHandle ("objectForKey:");

		public static string StringForKey(this NSDictionary obj, string key)
		{
			IntPtr nskey = NSString.CreateNative(key);
			try 
			{
				var nso = Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr (obj.Handle, sel_ObjForKey, nskey));

				if (nso == null)
					return null;

				string str = nso as NSString;

				return str;
			}
			finally
			{
				NSString.ReleaseNative(nskey);
			}
		}