使用 MonoTouch Core Graphics 的应用程序神秘崩溃

发布于 2024-09-02 15:30:32 字数 10317 浏览 5 评论 0原文

我的应用程序启动时带有一个视图控制器和一个由按钮和子视图组成的简单视图。当用户触摸按钮时,子视图将填充滚动视图,显示电子表格的列标题、行标题和单元格。为了绘制单元格,我使用 CGBitmapContext 绘制单元格,生成图像,然后将图像放入显示单元格的滚动视图中包含的图像视图中。

当我在 iPad 上运行该应用程序时,它可以很好地显示单元格,并且滚动视图可以让用户在电子表格中滚动,不会出现任何问题。如果用户第二次触摸该按钮,电子表格将重新绘制并继续正常工作,但是,如果用户第三次触摸该按钮,应用程序就会崩溃。应用程序输出窗口中没有异常信息显示。

我的第一个想法是连续按下按钮耗尽了所有可用内存,因此我覆盖了视图控制器中的 DidReceiveMemoryWarning 方法,并使用断点来确认该方法没有被调用。我的下一个想法是 CGBitmapContext 没有被释放,并寻找与 Objective C 的 CGContextRelease() 函数等效的 Monotouch。我能找到的最接近的是 CGBitmapContext 实例方法 Dispose(),我调用了它,但没有解决问题。

为了释放尽可能多的内存(以防万一我在没有发出警告的情况下内存不足),我尝试在每次使用完 CGBitmapContext 时强制进行垃圾回收。这让问题变得更糟。现在,程序在第一次显示电子表格后不久就会崩溃。这让我想知道垃圾收集器是否以某种方式收集了在屏幕上继续显示图形所必需的东西。

对于调查这些事故原因的进一步途径的任何建议,我将不胜感激。我已经包含了 SpreadsheetView 类的源代码。相关方法是DrawSpreadsheet(),当触摸按钮时调用该方法。

感谢您对此事的协助。

斯蒂芬·阿什利

  public class SpreadsheetView : UIView

 {
  public ISpreadsheetMessenger spreadsheetMessenger = null;
  public UIScrollView cellsScrollView = null;
  public UIImageView cellsImageView = null;

  public SpreadsheetView(RectangleF frame) : base()
  {
   Frame = frame;
   BackgroundColor = Constants.backgroundBlack;
   AutosizesSubviews = true;
  }

  public void DrawSpreadsheet()
  {
   UInt16 RowHeaderWidth = spreadsheetMessenger.RowHeaderWidth;
   UInt16 RowHeaderHeight = spreadsheetMessenger.RowHeaderHeight;
   UInt16 RowCount = spreadsheetMessenger.RowCount;
   UInt16 ColumnHeaderWidth = spreadsheetMessenger.ColumnHeaderWidth;
   UInt16 ColumnHeaderHeight = spreadsheetMessenger.ColumnHeaderHeight;
   UInt16 ColumnCount = spreadsheetMessenger.ColumnCount;

   // Add the corner
   UIImageView cornerView = new UIImageView(new RectangleF(0f, 0f,
      RowHeaderWidth, ColumnHeaderHeight));
   cornerView.BackgroundColor = Constants.headingColor;

   CGColorSpace cornerColorSpace = null;
   CGBitmapContext cornerContext = null;
   IntPtr buffer = Marshal.AllocHGlobal(RowHeaderWidth * ColumnHeaderHeight * 4);
   if (buffer == IntPtr.Zero)
    throw new OutOfMemoryException("Out of memory.");
   try
   {
    cornerColorSpace = CGColorSpace.CreateDeviceRGB();
    cornerContext = new CGBitmapContext
     (buffer, RowHeaderWidth, ColumnHeaderHeight, 8, 4 * RowHeaderWidth,
      cornerColorSpace, CGImageAlphaInfo.PremultipliedFirst);
    cornerContext.SetFillColorWithColor(Constants.headingColor.CGColor);
    cornerContext.FillRect(new RectangleF(0f, 0f, RowHeaderWidth, ColumnHeaderHeight));
    cornerView.Image = UIImage.FromImage(cornerContext.ToImage());
   }
   finally
   {
    Marshal.FreeHGlobal(buffer);
    if (cornerContext != null)
    {
     cornerContext.Dispose();
     cornerContext = null;
    }
    if (cornerColorSpace != null)
    {
     cornerColorSpace.Dispose();
     cornerColorSpace = null;
    }
   }
   cornerView.Image = DrawBottomRightCorner(cornerView.Image);
   AddSubview(cornerView);

   // Add the cellsScrollView
   cellsScrollView = new UIScrollView
    (new RectangleF(RowHeaderWidth, ColumnHeaderHeight,
     Frame.Width - RowHeaderWidth,
     Frame.Height - ColumnHeaderHeight));
   cellsScrollView.ContentSize = new SizeF
    (ColumnCount * ColumnHeaderWidth,
     RowCount * RowHeaderHeight);
   Size iContentSize = new Size((int)cellsScrollView.ContentSize.Width, 
                        (int)cellsScrollView.ContentSize.Height);
   cellsScrollView.BackgroundColor = UIColor.Black;
   AddSubview(cellsScrollView);

   CGColorSpace colorSpace = null;
   CGBitmapContext context = null;
   CGGradient gradient = null;
   UIImage image = null;
   int bytesPerRow = 4 * iContentSize.Width;
   int byteCount = bytesPerRow * iContentSize.Height;
   buffer = Marshal.AllocHGlobal(byteCount);
   if (buffer == IntPtr.Zero)
    throw new OutOfMemoryException("Out of memory.");

   try
   {
    colorSpace = CGColorSpace.CreateDeviceRGB();
    context = new CGBitmapContext
     (buffer, iContentSize.Width, 
      iContentSize.Height, 8, 4 * iContentSize.Width, 
      colorSpace, CGImageAlphaInfo.PremultipliedFirst);
    float[] components = new float[]
    {.75f, .75f, .75f, 1f,
     .25f, .25f, .25f, 1f};
    float[] locations = new float[]{0f, 1f};
    gradient = new CGGradient(colorSpace, components, locations);
    PointF startPoint = new PointF(0f, (float)iContentSize.Height);
    PointF endPoint = new PointF((float)iContentSize.Width, 0f);
    context.DrawLinearGradient(gradient, startPoint, endPoint, 0);
    context.SetLineWidth(Constants.lineWidth);
    context.BeginPath();
    for (UInt16 i = 1; i <= RowCount; i++)
    {
     context.MoveTo
      (0f, iContentSize.Height - i * RowHeaderHeight + (Constants.lineWidth/2));
     context.AddLineToPoint((float)iContentSize.Width, 
        iContentSize.Height - i * RowHeaderHeight + (Constants.lineWidth/2));
    }
    for (UInt16 j = 1; j <= ColumnCount; j++)
    {
     context.MoveTo((float)j * ColumnHeaderWidth - Constants.lineWidth/2, 
                    (float)iContentSize.Height);
     context.AddLineToPoint((float)j * ColumnHeaderWidth - Constants.lineWidth/2, 0f);
    }
    context.StrokePath();
    image = UIImage.FromImage(context.ToImage());
   }
   finally
   {
    Marshal.FreeHGlobal(buffer);
    if (gradient != null)
    {
     gradient.Dispose();
     gradient = null;
    }
    if (context != null)
    {
     context.Dispose();
     context = null;
    }
    if (colorSpace != null)
    {
     colorSpace.Dispose();
     colorSpace = null;
    }
    // GC.Collect();
    //GC.WaitForPendingFinalizers();
   }

   UIImage finalImage = ActivateCell(1, 1, image);
   finalImage = ActivateCell(0, 0, finalImage);
   cellsImageView = new UIImageView(finalImage);
   cellsImageView.Frame = new RectangleF(0f, 0f,
      iContentSize.Width, iContentSize.Height);
   cellsScrollView.AddSubview(cellsImageView);

  }

  private UIImage ActivateCell(UInt16 column, UInt16 row, UIImage backgroundImage)
  {
   UInt16 ColumnHeaderWidth = (UInt16)spreadsheetMessenger.ColumnHeaderWidth;
   UInt16 RowHeaderHeight = (UInt16)spreadsheetMessenger.RowHeaderHeight;

   CGColorSpace cellColorSpace = null;
   CGBitmapContext cellContext = null;
   UIImage cellImage = null;
   IntPtr buffer = Marshal.AllocHGlobal(4 * ColumnHeaderWidth * RowHeaderHeight);
   if (buffer == IntPtr.Zero)
    throw new OutOfMemoryException("Out of memory: ActivateCell()");
   try
   {
    cellColorSpace = CGColorSpace.CreateDeviceRGB();
    // Create a bitmap the size of a cell
    cellContext = new CGBitmapContext
     (buffer, ColumnHeaderWidth, RowHeaderHeight, 8,
      4 * ColumnHeaderWidth, cellColorSpace, CGImageAlphaInfo.PremultipliedFirst);
    // Paint it white
    cellContext.SetFillColorWithColor(UIColor.White.CGColor);
    cellContext.FillRect(new RectangleF(0f, 0f, ColumnHeaderWidth, RowHeaderHeight));
    // Convert it to an image
    cellImage = UIImage.FromImage(cellContext.ToImage());
   }
   finally
   {
    Marshal.FreeHGlobal(buffer);
    if (cellContext != null) 
    {
     cellContext.Dispose();
     cellContext = null;
    }
    if (cellColorSpace != null)
    {
     cellColorSpace.Dispose();
     cellColorSpace = null;
    }
    // GC.Collect();
    //GC.WaitForPendingFinalizers();
   }
   // Draw the border on the cell image
   cellImage = DrawBottomRightCorner(cellImage);

   CGColorSpace colorSpace = null;
   CGBitmapContext context = null;
   Size iContentSize = new Size((int)backgroundImage.Size.Width,
                                (int)backgroundImage.Size.Height);
   buffer = Marshal.AllocHGlobal(4 * iContentSize.Width * iContentSize.Height);
   if (buffer == IntPtr.Zero)
    throw new OutOfMemoryException("Out of memory: ActivateCell().");
   try
   {
    colorSpace = CGColorSpace.CreateDeviceRGB();
    // Set up a bitmap context the size of the whole grid
    context = new CGBitmapContext
     (buffer, iContentSize.Width, 
      iContentSize.Height, 8, 4 * iContentSize.Width, 
      colorSpace, CGImageAlphaInfo.PremultipliedFirst);
    // Draw the original grid into the bitmap
    context.DrawImage(new RectangleF(0f, 0f, iContentSize.Width, iContentSize.Height),
                      backgroundImage.CGImage);
    // Draw the cell image into the bitmap
    context.DrawImage(new RectangleF(column * ColumnHeaderWidth, 
                                     iContentSize.Height - (row + 1) * RowHeaderHeight,
                                     ColumnHeaderWidth, RowHeaderHeight),
                      cellImage.CGImage);
    // Convert the bitmap back to an image
    backgroundImage = UIImage.FromImage(context.ToImage());
   }
   finally
   {
    Marshal.FreeHGlobal(buffer);
    if (context != null)
    {
     context.Dispose();
     context = null;
    }
    if (colorSpace != null)
    {
     colorSpace.Dispose();
     colorSpace = null;
    }
    // GC.Collect();
    //GC.WaitForPendingFinalizers();
   }
   return backgroundImage;
  }

  private UIImage DrawBottomRightCorner(UIImage image)
  {
   int width = (int)image.Size.Width;
   int height = (int)image.Size.Height;
   float lineWidth = Constants.lineWidth;

   CGColorSpace colorSpace = null;
   CGBitmapContext context = null;
   UIImage returnImage = null;
   IntPtr buffer = Marshal.AllocHGlobal(4 * width * height);
   if (buffer == IntPtr.Zero)
    throw new OutOfMemoryException("Out of memory: DrawBottomRightCorner().");
   try
   {
    colorSpace = CGColorSpace.CreateDeviceRGB();
    context = new CGBitmapContext
     (buffer, width, height, 8, 4 * width, colorSpace, 
      CGImageAlphaInfo.PremultipliedFirst);
    context.DrawImage(new RectangleF(0f, 0f, width, height),
                      image.CGImage);
    context.BeginPath();
    context.MoveTo(0f, (int)(lineWidth/2f));

    context.AddLineToPoint(width - (int)(lineWidth/2f), (int)(lineWidth/2f));

    context.AddLineToPoint(width - (int)(lineWidth/2f), height);
    context.SetLineWidth(Constants.lineWidth);
    context.SetStrokeColorWithColor(UIColor.Black.CGColor);
    context.StrokePath();
    returnImage = UIImage.FromImage(context.ToImage());
   }
   finally
   {
    Marshal.FreeHGlobal(buffer);
    if (context != null){
     context.Dispose();
     context = null;}
    if (colorSpace != null){
     colorSpace.Dispose();
     colorSpace = null;}
    // GC.Collect();
    //GC.WaitForPendingFinalizers();
   }
   return returnImage;
  }
 }

My app launches with a view controller and a simple view consisting of a button and a subview. When the user touches the button, the subview is populated with scrollviews that display the column headers, row headers, and cells of a spreadsheet. To draw the cells, I use CGBitmapContext to draw the cells, generate an image, and then put the image into the imageview contained in the scrollview that displays the cells.

When I run the app on the iPad, it displays the cells just fine, and the scrollview lets the user scroll around in the spreadsheet without any problems. If the user touches the button a second time, the spreadsheet redraws and continues to work perfectly, If, however, the user touches the button a third time, the app crashes. There is no exception information display in the Application Output window.

My first thought was that the successive button pushes were using up all the available memory, so I overrode the DidReceiveMemoryWarning method in the view controller and used a breakpoint to confirm that this method was not getting called. My next thought was that the CGBitmapContext was not getting released and looked for a Monotouch equivalent of Objective C's CGContextRelease() function. The closest I could find was the CGBitmapContext instance method Dispose(), which I called, without solving the problem.

In order to free up as much memory as possible (in case I was somehow running out of memory without tripping a warning), I tried forcing garbage collection each time I finished using a CGBitmapContext. This made the problem worse. Now the program would crash moments after displaying the spreadsheet the first time. This caused me to wonder whether the Garbage Collector was somehow collecting something necessary to the continued display of graphics on the screen.

I would be grateful for any suggestions on further avenues to investigate for the cause of these crashes. I have included the source code for the SpreadsheetView class. The relevant method is DrawSpreadsheet(), which is called when the button is touched.

Thank you for your assistance on this matter.

Stephen Ashley

  public class SpreadsheetView : UIView

 {
  public ISpreadsheetMessenger spreadsheetMessenger = null;
  public UIScrollView cellsScrollView = null;
  public UIImageView cellsImageView = null;

  public SpreadsheetView(RectangleF frame) : base()
  {
   Frame = frame;
   BackgroundColor = Constants.backgroundBlack;
   AutosizesSubviews = true;
  }

  public void DrawSpreadsheet()
  {
   UInt16 RowHeaderWidth = spreadsheetMessenger.RowHeaderWidth;
   UInt16 RowHeaderHeight = spreadsheetMessenger.RowHeaderHeight;
   UInt16 RowCount = spreadsheetMessenger.RowCount;
   UInt16 ColumnHeaderWidth = spreadsheetMessenger.ColumnHeaderWidth;
   UInt16 ColumnHeaderHeight = spreadsheetMessenger.ColumnHeaderHeight;
   UInt16 ColumnCount = spreadsheetMessenger.ColumnCount;

   // Add the corner
   UIImageView cornerView = new UIImageView(new RectangleF(0f, 0f,
      RowHeaderWidth, ColumnHeaderHeight));
   cornerView.BackgroundColor = Constants.headingColor;

   CGColorSpace cornerColorSpace = null;
   CGBitmapContext cornerContext = null;
   IntPtr buffer = Marshal.AllocHGlobal(RowHeaderWidth * ColumnHeaderHeight * 4);
   if (buffer == IntPtr.Zero)
    throw new OutOfMemoryException("Out of memory.");
   try
   {
    cornerColorSpace = CGColorSpace.CreateDeviceRGB();
    cornerContext = new CGBitmapContext
     (buffer, RowHeaderWidth, ColumnHeaderHeight, 8, 4 * RowHeaderWidth,
      cornerColorSpace, CGImageAlphaInfo.PremultipliedFirst);
    cornerContext.SetFillColorWithColor(Constants.headingColor.CGColor);
    cornerContext.FillRect(new RectangleF(0f, 0f, RowHeaderWidth, ColumnHeaderHeight));
    cornerView.Image = UIImage.FromImage(cornerContext.ToImage());
   }
   finally
   {
    Marshal.FreeHGlobal(buffer);
    if (cornerContext != null)
    {
     cornerContext.Dispose();
     cornerContext = null;
    }
    if (cornerColorSpace != null)
    {
     cornerColorSpace.Dispose();
     cornerColorSpace = null;
    }
   }
   cornerView.Image = DrawBottomRightCorner(cornerView.Image);
   AddSubview(cornerView);

   // Add the cellsScrollView
   cellsScrollView = new UIScrollView
    (new RectangleF(RowHeaderWidth, ColumnHeaderHeight,
     Frame.Width - RowHeaderWidth,
     Frame.Height - ColumnHeaderHeight));
   cellsScrollView.ContentSize = new SizeF
    (ColumnCount * ColumnHeaderWidth,
     RowCount * RowHeaderHeight);
   Size iContentSize = new Size((int)cellsScrollView.ContentSize.Width, 
                        (int)cellsScrollView.ContentSize.Height);
   cellsScrollView.BackgroundColor = UIColor.Black;
   AddSubview(cellsScrollView);

   CGColorSpace colorSpace = null;
   CGBitmapContext context = null;
   CGGradient gradient = null;
   UIImage image = null;
   int bytesPerRow = 4 * iContentSize.Width;
   int byteCount = bytesPerRow * iContentSize.Height;
   buffer = Marshal.AllocHGlobal(byteCount);
   if (buffer == IntPtr.Zero)
    throw new OutOfMemoryException("Out of memory.");

   try
   {
    colorSpace = CGColorSpace.CreateDeviceRGB();
    context = new CGBitmapContext
     (buffer, iContentSize.Width, 
      iContentSize.Height, 8, 4 * iContentSize.Width, 
      colorSpace, CGImageAlphaInfo.PremultipliedFirst);
    float[] components = new float[]
    {.75f, .75f, .75f, 1f,
     .25f, .25f, .25f, 1f};
    float[] locations = new float[]{0f, 1f};
    gradient = new CGGradient(colorSpace, components, locations);
    PointF startPoint = new PointF(0f, (float)iContentSize.Height);
    PointF endPoint = new PointF((float)iContentSize.Width, 0f);
    context.DrawLinearGradient(gradient, startPoint, endPoint, 0);
    context.SetLineWidth(Constants.lineWidth);
    context.BeginPath();
    for (UInt16 i = 1; i <= RowCount; i++)
    {
     context.MoveTo
      (0f, iContentSize.Height - i * RowHeaderHeight + (Constants.lineWidth/2));
     context.AddLineToPoint((float)iContentSize.Width, 
        iContentSize.Height - i * RowHeaderHeight + (Constants.lineWidth/2));
    }
    for (UInt16 j = 1; j <= ColumnCount; j++)
    {
     context.MoveTo((float)j * ColumnHeaderWidth - Constants.lineWidth/2, 
                    (float)iContentSize.Height);
     context.AddLineToPoint((float)j * ColumnHeaderWidth - Constants.lineWidth/2, 0f);
    }
    context.StrokePath();
    image = UIImage.FromImage(context.ToImage());
   }
   finally
   {
    Marshal.FreeHGlobal(buffer);
    if (gradient != null)
    {
     gradient.Dispose();
     gradient = null;
    }
    if (context != null)
    {
     context.Dispose();
     context = null;
    }
    if (colorSpace != null)
    {
     colorSpace.Dispose();
     colorSpace = null;
    }
    // GC.Collect();
    //GC.WaitForPendingFinalizers();
   }

   UIImage finalImage = ActivateCell(1, 1, image);
   finalImage = ActivateCell(0, 0, finalImage);
   cellsImageView = new UIImageView(finalImage);
   cellsImageView.Frame = new RectangleF(0f, 0f,
      iContentSize.Width, iContentSize.Height);
   cellsScrollView.AddSubview(cellsImageView);

  }

  private UIImage ActivateCell(UInt16 column, UInt16 row, UIImage backgroundImage)
  {
   UInt16 ColumnHeaderWidth = (UInt16)spreadsheetMessenger.ColumnHeaderWidth;
   UInt16 RowHeaderHeight = (UInt16)spreadsheetMessenger.RowHeaderHeight;

   CGColorSpace cellColorSpace = null;
   CGBitmapContext cellContext = null;
   UIImage cellImage = null;
   IntPtr buffer = Marshal.AllocHGlobal(4 * ColumnHeaderWidth * RowHeaderHeight);
   if (buffer == IntPtr.Zero)
    throw new OutOfMemoryException("Out of memory: ActivateCell()");
   try
   {
    cellColorSpace = CGColorSpace.CreateDeviceRGB();
    // Create a bitmap the size of a cell
    cellContext = new CGBitmapContext
     (buffer, ColumnHeaderWidth, RowHeaderHeight, 8,
      4 * ColumnHeaderWidth, cellColorSpace, CGImageAlphaInfo.PremultipliedFirst);
    // Paint it white
    cellContext.SetFillColorWithColor(UIColor.White.CGColor);
    cellContext.FillRect(new RectangleF(0f, 0f, ColumnHeaderWidth, RowHeaderHeight));
    // Convert it to an image
    cellImage = UIImage.FromImage(cellContext.ToImage());
   }
   finally
   {
    Marshal.FreeHGlobal(buffer);
    if (cellContext != null) 
    {
     cellContext.Dispose();
     cellContext = null;
    }
    if (cellColorSpace != null)
    {
     cellColorSpace.Dispose();
     cellColorSpace = null;
    }
    // GC.Collect();
    //GC.WaitForPendingFinalizers();
   }
   // Draw the border on the cell image
   cellImage = DrawBottomRightCorner(cellImage);

   CGColorSpace colorSpace = null;
   CGBitmapContext context = null;
   Size iContentSize = new Size((int)backgroundImage.Size.Width,
                                (int)backgroundImage.Size.Height);
   buffer = Marshal.AllocHGlobal(4 * iContentSize.Width * iContentSize.Height);
   if (buffer == IntPtr.Zero)
    throw new OutOfMemoryException("Out of memory: ActivateCell().");
   try
   {
    colorSpace = CGColorSpace.CreateDeviceRGB();
    // Set up a bitmap context the size of the whole grid
    context = new CGBitmapContext
     (buffer, iContentSize.Width, 
      iContentSize.Height, 8, 4 * iContentSize.Width, 
      colorSpace, CGImageAlphaInfo.PremultipliedFirst);
    // Draw the original grid into the bitmap
    context.DrawImage(new RectangleF(0f, 0f, iContentSize.Width, iContentSize.Height),
                      backgroundImage.CGImage);
    // Draw the cell image into the bitmap
    context.DrawImage(new RectangleF(column * ColumnHeaderWidth, 
                                     iContentSize.Height - (row + 1) * RowHeaderHeight,
                                     ColumnHeaderWidth, RowHeaderHeight),
                      cellImage.CGImage);
    // Convert the bitmap back to an image
    backgroundImage = UIImage.FromImage(context.ToImage());
   }
   finally
   {
    Marshal.FreeHGlobal(buffer);
    if (context != null)
    {
     context.Dispose();
     context = null;
    }
    if (colorSpace != null)
    {
     colorSpace.Dispose();
     colorSpace = null;
    }
    // GC.Collect();
    //GC.WaitForPendingFinalizers();
   }
   return backgroundImage;
  }

  private UIImage DrawBottomRightCorner(UIImage image)
  {
   int width = (int)image.Size.Width;
   int height = (int)image.Size.Height;
   float lineWidth = Constants.lineWidth;

   CGColorSpace colorSpace = null;
   CGBitmapContext context = null;
   UIImage returnImage = null;
   IntPtr buffer = Marshal.AllocHGlobal(4 * width * height);
   if (buffer == IntPtr.Zero)
    throw new OutOfMemoryException("Out of memory: DrawBottomRightCorner().");
   try
   {
    colorSpace = CGColorSpace.CreateDeviceRGB();
    context = new CGBitmapContext
     (buffer, width, height, 8, 4 * width, colorSpace, 
      CGImageAlphaInfo.PremultipliedFirst);
    context.DrawImage(new RectangleF(0f, 0f, width, height),
                      image.CGImage);
    context.BeginPath();
    context.MoveTo(0f, (int)(lineWidth/2f));

    context.AddLineToPoint(width - (int)(lineWidth/2f), (int)(lineWidth/2f));

    context.AddLineToPoint(width - (int)(lineWidth/2f), height);
    context.SetLineWidth(Constants.lineWidth);
    context.SetStrokeColorWithColor(UIColor.Black.CGColor);
    context.StrokePath();
    returnImage = UIImage.FromImage(context.ToImage());
   }
   finally
   {
    Marshal.FreeHGlobal(buffer);
    if (context != null){
     context.Dispose();
     context = null;}
    if (colorSpace != null){
     colorSpace.Dispose();
     colorSpace = null;}
    // GC.Collect();
    //GC.WaitForPendingFinalizers();
   }
   return returnImage;
  }
 }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

喜爱纠缠 2024-09-09 15:30:32

不确定这是否能解决您的问题(我对此比您还新),但似乎来自 这个答案表明 MonoTouch 更喜欢使用不同的范例来创建/释放图形上下文,大致如下:

UIGraphics.BeginImageContext(rect.Size)
var context = UIContext.GetCurrentContext();
// ... do stuff ...
UIImage image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
// ... do something with image ...

我不知道它是否正确释放了所有内容,但除此之外它似乎有效。

Not sure if this will solve your problem (I'm even newer to this than you are), but it seems from this answer that MonoTouch prefers a different paradigm for creating/releasing graphics contexts, along the lines of:

UIGraphics.BeginImageContext(rect.Size)
var context = UIContext.GetCurrentContext();
// ... do stuff ...
UIImage image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
// ... do something with image ...

I don't know if it's releasing everything properly, but otherwise it seems to work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文