Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8882691
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 14, 20262026-06-14T20:38:32+00:00 2026-06-14T20:38:32+00:00

I’m currently porting a small Winforms-based .NET application to use a native Mac front-end

  • 0

I’m currently porting a small Winforms-based .NET application to use a native Mac front-end with MonoMac. The application has a TreeControl with icons and text, which does not exist out of the box in Cocoa.

So far, I’ve ported almost all of the ImageAndTextCell code in Apple’s DragNDrop example: https://developer.apple.com/library/mac/#samplecode/DragNDropOutlineView/Listings/ImageAndTextCell_m.html#//apple_ref/doc/uid/DTS40008831-ImageAndTextCell_m-DontLinkElementID_6, which is assigned to an NSOutlineView as a custom cell.

It seems to be working almost perfectly, except that I have not figured out how to properly port the copyWithZone method. Unfortunately, this means the internal copies that NSOutlineView is making do not have the image field, and it leads to the images briefly vanishing during expand and collapse operations. The objective-c code in question is:

- (id)copyWithZone:(NSZone *)zone {
    ImageAndTextCell *cell = (ImageAndTextCell *)[super copyWithZone:zone];
    // The image ivar will be directly copied; we need to retain or copy it.
    cell->image = [image retain];
    return cell;
}

The first line is what’s tripping me up, as MonoMac does not expose a copyWithZone method, and I don’t know how to otherwise call it.

Update

Based on current answers and additional research and testing, I’ve come up with a variety of models for copying an object.

static List<ImageAndTextCell> _refPool = new List<ImageAndTextCell>();

// Method 1

static IntPtr selRetain = Selector.GetHandle ("retain");

[Export("copyWithZone:")]
public virtual NSObject CopyWithZone(IntPtr zone) {
    ImageAndTextCell cell = new ImageAndTextCell() {
        Title = Title,
        Image = Image,
    };

    Messaging.void_objc_msgSend (cell.Handle, selRetain);

    return cell;
}

// Method 2

[Export("copyWithZone:")]
public virtual NSObject CopyWithZone(IntPtr zone) {
    ImageAndTextCell cell = new ImageAndTextCell() {
        Title = Title,
        Image = Image,
    };

    _refPool.Add(cell);

    return cell;
}

[Export("dealloc")]
public void Dealloc ()
{
    _refPool.Remove(this);
    this.Dispose();
}

// Method 3

static IntPtr selRetain = Selector.GetHandle ("retain");

[Export("copyWithZone:")]
public virtual NSObject CopyWithZone(IntPtr zone) {
    ImageAndTextCell cell = new ImageAndTextCell() {
        Title = Title,
        Image = Image,
    };

    _refPool.Add(cell);
    Messaging.void_objc_msgSend (cell.Handle, selRetain);

    return cell;
}

// Method 4

static IntPtr selRetain = Selector.GetHandle ("retain");
static IntPtr selRetainCount = Selector.GetHandle("retainCount");

[Export("copyWithZone:")]
public virtual NSObject CopyWithZone (IntPtr zone)
{
    ImageAndTextCell cell = new ImageAndTextCell () {
        Title = Title,
        Image = Image,
    };

    _refPool.Add (cell);
    Messaging.void_objc_msgSend (cell.Handle, selRetain);

    return cell;
}

public void PeriodicCleanup ()
{
    List<ImageAndTextCell> markedForDelete = new List<ImageAndTextCell> ();

    foreach (ImageAndTextCell cell in _refPool) {
        uint count = Messaging.UInt32_objc_msgSend (cell.Handle, selRetainCount);
        if (count == 1)
            markedForDelete.Add (cell);
    }

    foreach (ImageAndTextCell cell in markedForDelete) {
        _refPool.Remove (cell);
        cell.Dispose ();
    }
}

// Method 5

static IntPtr selCopyWithZone = Selector.GetHandle("copyWithZone:");

[Export("copyWithZone:")]
public virtual NSObject CopyWithZone(IntPtr zone) {
    IntPtr copyHandle = Messaging.IntPtr_objc_msgSendSuper_IntPtr(SuperHandle, selCopyWithZone, zone);
    ImageAndTextCell cell = new ImageAndTextCell(copyHandle) {
        Image = Image,
    };

    _refPool.Add(cell);

    return cell;
}

Method 1: Increases the retain count of the unmanaged object. The unmanaged object will persist persist forever (I think? dealloc never called), and the managed object will be harvested early. Seems to be lose-lose all-around, but runs in practice.

Method 2: Saves a reference of the managed object. The unmanaged object is left alone, and dealloc appears to be invoked at a reasonable time by the caller. At this point the managed object is released and disposed. This seems reasonable, but on the downside the base type’s dealloc won’t be run (I think?)

Method 3: Increases the retain count and saves a reference. Unmanaged and managed objects leak forever.

Method 4: Extends Method 3 by adding a cleanup function that is run periodically (e.g. during Init of each new ImageAndTextCell object). The cleanup function checks the retain counts of the stored objects. A retain count of 1 means the caller has released it, so we should as well. Should eliminate leaking in theory.

Method 5: Attempt to invoke the copyWithZone method on the base type, and then construct a new ImageAndTextView object with the resulting handle. Seems to do the right thing (the base data is cloned). Internally, NSObject bumps the retain count on objects constructed like this, so we also use the PeriodicCleanup function to release these objects when they’re no longer used.

Based on the above, I believe Method 5 is the best approach since it should be the only one that results in a truly correct copy of the base type data, but I don’t know if the approach is inherently dangerous (I am also making some assumptions about the underlying implementation of NSObject). So far nothing bad has happened “yet”, but if anyone is able to vet my analysis then I would be more confident going forward.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-14T20:38:33+00:00Added an answer on June 14, 2026 at 8:38 pm

    So far I have not found any evidence of trouble, so I’m comfortable adopting “Method 5” that I outlined in my question update, which I’ll duplicate here with some additional explanation:

    // An additional constructor
    public ImageAndTextCell (IntPtr handle)
        : base(handle)
    {
    }
    
    // Cocoa Selectors
    static IntPtr selRetainCount = Selector.GetHandle("retainCount");
    static IntPtr selCopyWithZone = Selector.GetHandle("copyWithZone:");
    
    static List<ImageAndTextCell> _refPool = new List<ImageAndTextCell>();
    
    // Helper method to be called at some future point in managed code to release
    // managed instances that are no longer needed.
    public void PeriodicCleanup ()
    {
        List<ImageAndTextCell> markedForDelete = new List<ImageAndTextCell> ();
    
        foreach (ImageAndTextCell cell in _refPool) {
            uint count = Messaging.UInt32_objc_msgSend (cell.Handle, selRetainCount);
            if (count == 1)
                markedForDelete.Add (cell);
        }
    
        foreach (ImageAndTextCell cell in markedForDelete) {
            _refPool.Remove (cell);
            cell.Dispose ();
        }
    }
    
    // Overriding the copy method
    [Export("copyWithZone:")]
    public virtual NSObject CopyWithZone(IntPtr zone) {
        IntPtr copyHandle = Messaging.IntPtr_objc_msgSendSuper_IntPtr(SuperHandle, selCopyWithZone, zone);
        ImageAndTextCell cell = new ImageAndTextCell(copyHandle) {
            Image = Image,
        };
    
        _refPool.Add(cell);
    
        return cell;
    }
    

    By invoking the copyWithZone: selector on the base object (via SuperHandle), the underlying Cocoa subsystem will clone the unmanaged object and give back the handle to it, with its retain count already set to 1 (standard obj-c copy convention). It’s then possible to construct the derived C# object with the cloned object handle, so the cloned instance becomes the backing object. Then it’s a simple matter of cloning any managed C# goodies that belong to the derived type.

    As ta.speot.is pointed out, it’s also necessary to hold onto a reference of the managed type somewhere. Without the reference, the object is a candidate for garbage collection at the end of the method. The unmanaged portion of the object is safe on return because it has a positive retain count from the call to the copy selector. I’ve chosen to store references in a static List, and then periodically call a cleanup method from other parts of code which will traverse the list, check if the corresponding unmanaged objects have any other owners, and dispose the objects if not. Note that I’m checking for a count of 1 instead of 0, because our copied object was actually retained twice: once by the copy selector, and once by the NSObject constructor. The Monomac runtime system will take care of disposing the unmanaged object when the managed side is disposed/collected.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a small JavaScript validation script that validates inputs based on Regex. I
I want use html5's new tag to play a wav file (currently only supported
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I have an array which has BIG numbers and small numbers in it. I
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
link Im having trouble converting the html entites into html characters, (&# 8217;) i
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I want to count how many characters a certain string has in PHP, but
Configuring TinyMCE to allow for tags, based on a customer requirement. My config is
I am trying to understand how to use SyndicationItem to display feed which is

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.