Сохранить UIImage как png из другого потока - PullRequest
3 голосов
/ 31 января 2012

Код довольно прост, он должен загрузить из файла настроек все существующие ссылки на изображения, масштабировать их до 250x250 и сохранить их под другим именем.

Проблема в том, что на устройстве (протестированном на iPhone 3g и iPad) оно через некоторое время вылетает с предупреждениями памяти. На симуляторе работает отлично.

У меня есть UIViewController, который имеет на ViewDidПоявиться этот код:

ThreadPool.QueueUserWorkItem( delegate{ 
    make_thumbs(); 
}); 

Функция make_thumbs:

void make_thumbs() 
{ 
    using( var ns = new NSAutoreleasePool() ) 
    { 
        foreach( var c in Settings.Instance.Categories ) 
        { 
            for( var i = 0; i < c.Pictures.Count; i++ ) 
            { 
                //this is the existing bundled image path 
                string     path = c.Pictures[i].PicturePath; 
                string   folder = Environment.GetFolderPath( Environment.SpecialFolder.Personal ); 
                //this is the destination image file name 
                string filename = Path.Combine( folder, c.Name + i + ".png"); 
                if( !File.Exists( filename ) ) 
                { 
                    NSError err;
                    using(UIImage img = UIImage.FromFile( path ).Scale( 250,250 ))
                    {
                        img.AsPNG().Save( filename, true, out err );
                    }
                } 
            } 
        } 
    } 
}

Ответы [ 2 ]

4 голосов
/ 31 января 2012

Вам потребуется расширить мое предложение (из списка рассылки ) для всего, что реализует IDisposable в вашем цикле (поскольку оно может распределять память гораздо быстрее, чем ГК сможет его забрать).

Как сказал @Rolf, в комментариях img.AsPNG() возвращает NSData, который реализует IDisposable.

Также вызов метода Scale также возвращает новый UIImage.

 using(UIImage img = UIImage.FromFile( path )) {
     using (var scaled_img = img.Scale( 250,250 )) {
         using (var data = img.AsPNG ()) {
             data.Save( filename, true, out err );
         }
     }
 }

Это должно охватывать этот блок, т. Е. Обеспечить восстановление всей памяти как можно скорее, что должно помочь вашему устройству (в нем не так много памяти).

2 голосов
/ 01 февраля 2012

Thx @poupou, ваш ответ был почти хорош, с небольшим завершением: мне пришлось поместить использование (var ns = new NSAutoreleasePool ()) в цикл for.Итак, мой код теперь такой, и он работает:

if( !File.Exists( filename ) )
{
    using( var ns = new NSAutoreleasePool() )
    {
        NSError err;
        using(UIImage img = UIImage.FromFile( path )) {
            using (var scaled_img = img.Scale( 250,250 )) 
            {
                //i also add a reflection effect                             
                using( var reflected_img = scaled_img.AddImageReflection( 0.6f ) )
                {
                    using (var data = reflected_img.AsPNG ()) 
                    {
                        data.Save( filename, true, out err );
                    }
                }
             }
        }
    }
}
...