How does Enumerate work in MonoTouch?
In MonoTouch I need to process each object in an NSSet. My attempt, using Enumerate, is as follows:
public override void ReturnResults ( BarcodePickerController picker, NSSet results )
{
var n = results.Count; // Debugging - value is 3
results.Enumerate( delegate( NSObject obj, ref bool stop )
{
var foundCode = ( obj as BarcodeResult ); // Executed only once, not 3 times
if ( foundCode != null )
{
controller.BarcodeScannedResult (foundCode);
}
});
// Etc
}
Although the method is invoked with three objects in results开发者_如何学Python, only one object is processed in the delegate. I would have expected the delegate to be executed three times, but I must have the wrong idea of how it works.
Unable to find any documentation or examples. Any suggestion much appreciated.
You have to set the ref
parameter to false. This instructs the handler to continue enumerating:
if ( foundCode != null )
{
controller.BarcodeScannedResult (foundCode);
stop = false; // inside the null check
}
Here is the ObjC equivalent from Apple documentation.
Or you could try this extension method to make it easier..
public static class MyExtensions {
public static IEnumerable<T> ItemsAs<T>(this NSSet set) where T : NSObject {
List<T> res = new List<T>();
set.Enumerate( delegate( NSObject obj, ref bool stop ) {
T item = (T)( obj ); // Executed only once, not 3 times
if ( item != null ) {
res.Add (item);
stop = false; // inside the null check
}
});
return res;
}
}
Then you can do something like:
foreach(BarcodeResult foundCode in results.ItemsAs<BarcodeResult>()) {
controller.BarcodeScannedResult (foundCode);
}
Note: Keep in mind this creates another list and copies everything to it, which is less efficient. I did this because "yield return" isn't allowed in anonymous methods, and the alternative ways I could think of to make it a real enumerator without the copy were much much more code. Most of the sets I deal with are tiny so this doesn't matter, but if you have a big set this isn't ideal.
精彩评论