Merhabalar bir uygulamamda IOS ta çoklu resim seçme işlemi gerçekleştirmek istiyorum fakat kodda derleyici hatası alıyorum. Calling Convention (cdecl) kullanmam gerekiyor fakat derleyici bunun kullanarak
bu satırı çalıştırmamı engelliyor. Calling Convention (cdecl) kaldırdığımda ise kod derleniyor resim listesi açılıyor fakat seçip tamam butonuna tıklayınca uygulama çöküyor. Galiba Calling Convention (cdecl) kullanarak bu işlemi gerçekleştirmem gerekiyor. Calling Convention (cdecl) kullanarak
1) Beklenen işlemden farklı bir iş parçacığında kod yürütülmesi arasındaki çakışma nedeniyle olası çökme. Başka bir deyişle, mobil cihazlar genellikle eşzamansız iş parçacıklarında çalışır, oysa uygulama penceresi tarafından kullanılan iş parçacığı eşzamanlıdır (ana iş parçacığı). Bu nedenle, bu tutarsızlık kodunuzda meydana gelebilir!
2) Bir diğer faktör ise ARC'dir, yani kodda hala hayatta olmaları gereken noktadan önce ölen nesneler. Bu nedenle, mobil nesneler genellikle "arayüzler" olduğundan, kodunuz bağlam kapsamından ayrıldığı için nesneyi erken öldürüyor olabilir.
3) Kullanılan nesneleri ve iş parçacıklarını gözden geçirin!
procedure TPHPickerDelegate.LoadCompleted(Item: Pointer; Error: NSError); cdecl;
var
IOSImage: UIImage;
begin
if (Item = nil) or (Error <> nil) then
Exit;
IOSImage := TUIImage.Wrap(Item);
// Kullanıcı arayüzünün ana iş parçacığında güncellenmesini sağlamak için TThread.Synchronize kullanıyoruz.
TThread.Synchronize(nil, procedure
var
Dump: TBitmap;
begin
Inc(FResimNo);
Dump := UIImageToBitmap(IOSImage, 0, TSize.Create(1920, 1080));
if Dump <> nil then
begin
FOwner.Resim_list.Items.Add.Text := 'Resim ' + FResimNo.ToString;
FOwner.Resim_list.Items[FOwner.Resim_list.ItemCount - 1].Bitmap := Dump;
Dump.Free; // Oluşturulan bitmap'i serbest bırakmak önemlidir.
end;
FOwner.Bekleme_Durumu(False);
end);
end;
Dikkate Alınması Gereken Ek Noktalar:
Bellek Yönetimi: UIImageToBitmap yeni bir TBitmap nesnesi oluşturur. Bunu serbest bırakmazsanız (Dump.Free), seçilen her fotoğraf için ciddi bir bellek sızıntısı yaşarsınız.
Saklama: PHPicker aktifken TPHPickerDelegate nesnesinin serbest bırakılmadığından emin olun. PHPicker genellikle delegeyi saklar, ancak onu oluşturan değişkenin doğru kapsamda olduğundan emin olmak iyi bir uygulamadır.
MSWindows, Android, RAD Studio 13 Florenceve kafamda bir fikir
(07-07-2026, Saat: 23:06)emailx45 Adlı Kullanıcıdan Alıntı: 1) Beklenen işlemden farklı bir iş parçacığında kod yürütülmesi arasındaki çakışma nedeniyle olası çökme. Başka bir deyişle, mobil cihazlar genellikle eşzamansız iş parçacıklarında çalışır, oysa uygulama penceresi tarafından kullanılan iş parçacığı eşzamanlıdır (ana iş parçacığı). Bu nedenle, bu tutarsızlık kodunuzda meydana gelebilir!
2) Bir diğer faktör ise ARC'dir, yani kodda hala hayatta olmaları gereken noktadan önce ölen nesneler. Bu nedenle, mobil nesneler genellikle "arayüzler" olduğundan, kodunuz bağlam kapsamından ayrıldığı için nesneyi erken öldürüyor olabilir.
3) Kullanılan nesneleri ve iş parçacıklarını gözden geçirin!
procedure TPHPickerDelegate.LoadCompleted(Item: Pointer; Error: NSError); cdecl;
var
IOSImage: UIImage;
begin
if (Item = nil) or (Error <> nil) then
Exit;
IOSImage := TUIImage.Wrap(Item);
// Kullanıcı arayüzünün ana iş parçacığında güncellenmesini sağlamak için TThread.Synchronize kullanıyoruz.
TThread.Synchronize(nil, procedure
var
Dump: TBitmap;
begin
Inc(FResimNo);
Dump := UIImageToBitmap(IOSImage, 0, TSize.Create(1920, 1080));
if Dump <> nil then
begin
FOwner.Resim_list.Items.Add.Text := 'Resim ' + FResimNo.ToString;
FOwner.Resim_list.Items[FOwner.Resim_list.ItemCount - 1].Bitmap := Dump;
Dump.Free; // Oluşturulan bitmap'i serbest bırakmak önemlidir.
end;
FOwner.Bekleme_Durumu(False);
end);
end;
Dikkate Alınması Gereken Ek Noktalar:
Bellek Yönetimi: UIImageToBitmap yeni bir TBitmap nesnesi oluşturur. Bunu serbest bırakmazsanız (Dump.Free), seçilen her fotoğraf için ciddi bir bellek sızıntısı yaşarsınız.
Saklama: PHPicker aktifken TPHPickerDelegate nesnesinin serbest bırakılmadığından emin olun. PHPicker genellikle delegeyi saklar, ancak onu oluşturan değişkenin doğru kapsamda olduğundan emin olmak iyi bir uygulamadır.
Hocam cevabınız için çok teşekkürederim. Koddaki değişiklikleri söylediğiniz gibi yaptım. Çökmeyi hangi kısımın yaptığınıda buldum fakat hala çözüme yaklaşamadım maalesef
Çökmeye altta paylaştığım sorgu sebep oluyor.
Bu sorguyu comment yapıp test ettiğimde ise tamam butonu çalışmıyor ve resimler seçilemiyor. Aktif ettiğimde ise direk uygulama kapanıyor ama her iki durumdada iptal butonu aktif çalışıyor buda picker procedure sinin tetiklendiği anlamına geliyor.
iOS'in iç işleyişi hakkında derinlemesine bilgiye sahip değilim ancak bunun, kullanılan API fonksiyonlarının döndürdüğü nesne türüyle ilgili olabileceğinden şüpheleniyorum.
Başka bir deyişle, döndürülen nesne henüz görselin kendisi olmayabilir; bunun yerine, asıl bitmap'i oluşturmak için işlenmesi gereken ham veri olabilir.
PHPicker ile çalışırken, bir görselin yüklenip yüklenemeyeceğini kontrol etmek için Apple'ın önerdiği yaklaşım, doğrudan `UIImage` sınıfını kontrol etmek yerine `kUTTypeImage` (veya eşdeğer iOS tanımlayıcısı) kullanmaktır. Bunun nedeni, `itemProvider`ın görseli henüz bellekte `UIImage` formatında olmayan ancak `UIImage`e dönüştürülebilir bir formatta tutuyor olabilmesidir.
Önerilen çözüm: `canLoadObjectOfClass(TUIImage.OCClass)` kullanmak yerine, standart görsel türüyle birlikte `hasItemConformingToTypeIdentifier` kullanmalıyız.
// iOSapi.UniformTypeIdentifiers veya iOSapi.MobileCoreServices birimini kullanın.
uses
iOSapi.UniformTypeIdentifiers, iOSapi.Foundation;
// ... döngünüzün içinde:
if (ResultItem <> nil) and (ResultItem.itemProvider <> nil) then
begin
// canLoadObjectOfClass yerine bir UTI (Uniform Type Identifier) kontrolü kullanın.
if ResultItem.itemProvider.hasItemConformingToTypeIdentifier(UTTypeImage) then
ResultItem.itemProvider.loadObjectOfClass(TUIImage.OCClass, LoadCompleted);
// else ...
end;
Bunun sorununuzu neden çözmesi gerektiği:
Çalışma Zamanı Güvenliği: `hasItemConformingToTypeIdentifier`, bir öğenin dönüştürülebilir olduğundan emin olmak için kullanılan Apple'ın yerel (native) metodudur. Delphi'deki doğrudan `canLoadObjectOfClass` kontrolüne kıyasla çok daha sağlamdır ve bellek erişim ihlallerine yol açma ihtimali daha düşüktür.
Uyumluluk: `UTTypeImage`, PHPicker tarafından sağlanan tüm görsel türlerini kapsayan doğru sabittir (constant).
Önemli uygulama noktaları:
Bellek Yönetimi: İkinci denemenizde `Dump.Free` ekleyerek doğru olanı yaptınız. Bunu yapmaya devam edin.
Yürütme İş Parçacığı (Thread): `TThread.Synchronize` kullanma fikriniz doğru. `loadObjectOfClass` asenkrondur ve arka plan iş parçacığında çalışır. Ana iş parçacığı dışından Delphi görsel bileşenlerine (örneğin `FOwner.Resim_list`) erişmeye çalışmak, FMX'teki çökmelerin bir numaralı nedenidir.
Nil Kontrolleri: Mevcut nil kontrollerinizi koruyun; çünkü Delphi köprüsü (bridge) aracılığıyla iOS üzerindeki nesne yaşam döngüsü değişken olabilir.
NOT: Portekizceden Türkçeye çeviri için Google Translate kullanılmıştır.
Yerel Android Fotoğraf Seçici'yi (Photo Picker) kullanarak Android için hazırladığım bir örnek var; belki iOS konusunda size yardımcı olabilir.
Genel olarak Delphi hakkındaki kanalıma abone olmaktan ve videolarımı beğenmekten çekinmeyin. Mümkünse, lütfen diğer yazılımcı arkadaşlarınıza da tavsiye edin!
(08-07-2026, Saat: 18:08)emailx45 Adlı Kullanıcıdan Alıntı: iOS'in iç işleyişi hakkında derinlemesine bilgiye sahip değilim ancak bunun, kullanılan API fonksiyonlarının döndürdüğü nesne türüyle ilgili olabileceğinden şüpheleniyorum.
Başka bir deyişle, döndürülen nesne henüz görselin kendisi olmayabilir; bunun yerine, asıl bitmap'i oluşturmak için işlenmesi gereken ham veri olabilir.
PHPicker ile çalışırken, bir görselin yüklenip yüklenemeyeceğini kontrol etmek için Apple'ın önerdiği yaklaşım, doğrudan `UIImage` sınıfını kontrol etmek yerine `kUTTypeImage` (veya eşdeğer iOS tanımlayıcısı) kullanmaktır. Bunun nedeni, `itemProvider`ın görseli henüz bellekte `UIImage` formatında olmayan ancak `UIImage`e dönüştürülebilir bir formatta tutuyor olabilmesidir.
Önerilen çözüm: `canLoadObjectOfClass(TUIImage.OCClass)` kullanmak yerine, standart görsel türüyle birlikte `hasItemConformingToTypeIdentifier` kullanmalıyız.
// iOSapi.UniformTypeIdentifiers veya iOSapi.MobileCoreServices birimini kullanın.
uses
iOSapi.UniformTypeIdentifiers, iOSapi.Foundation;
// ... döngünüzün içinde:
if (ResultItem <> nil) and (ResultItem.itemProvider <> nil) then
begin
// canLoadObjectOfClass yerine bir UTI (Uniform Type Identifier) kontrolü kullanın.
if ResultItem.itemProvider.hasItemConformingToTypeIdentifier(UTTypeImage) then
ResultItem.itemProvider.loadObjectOfClass(TUIImage.OCClass, LoadCompleted);
// else ...
end;
Bunun sorununuzu neden çözmesi gerektiği:
Çalışma Zamanı Güvenliği: `hasItemConformingToTypeIdentifier`, bir öğenin dönüştürülebilir olduğundan emin olmak için kullanılan Apple'ın yerel (native) metodudur. Delphi'deki doğrudan `canLoadObjectOfClass` kontrolüne kıyasla çok daha sağlamdır ve bellek erişim ihlallerine yol açma ihtimali daha düşüktür.
Uyumluluk: `UTTypeImage`, PHPicker tarafından sağlanan tüm görsel türlerini kapsayan doğru sabittir (constant).
Önemli uygulama noktaları:
Bellek Yönetimi: İkinci denemenizde `Dump.Free` ekleyerek doğru olanı yaptınız. Bunu yapmaya devam edin.
Yürütme İş Parçacığı (Thread): `TThread.Synchronize` kullanma fikriniz doğru. `loadObjectOfClass` asenkrondur ve arka plan iş parçacığında çalışır. Ana iş parçacığı dışından Delphi görsel bileşenlerine (örneğin `FOwner.Resim_list`) erişmeye çalışmak, FMX'teki çökmelerin bir numaralı nedenidir.
Nil Kontrolleri: Mevcut nil kontrollerinizi koruyun; çünkü Delphi köprüsü (bridge) aracılığıyla iOS üzerindeki nesne yaşam döngüsü değişken olabilir.
NOT: Portekizceden Türkçeye çeviri için Google Translate kullanılmıştır.
Yerel Android Fotoğraf Seçici'yi (Photo Picker) kullanarak Android için hazırladığım bir örnek var; belki iOS konusunda size yardımcı olabilir.
Genel olarak Delphi hakkındaki kanalıma abone olmaktan ve videolarımı beğenmekten çekinmeyin. Mümkünse, lütfen diğer yazılımcı arkadaşlarınıza da tavsiye edin!
if ResultItem.itemProvider.hasItemConformingToTypeIdentifier(UTTypeImage) then
kodu bu şekil düzenlediğim zaman
UTTypeImage
bu terimi ide görmedi bende o kısmı düzenledim aşağıdaki gibi :
if ResultItem.itemProvider.hasItemConformingToTypeIdentifier( StrToNSStr('public.image') ) then
begin
ResultItem.itemProvider.loadObjectOfClass(TUIImage.OCClass, LoadCompleted );
end;
ama bu seferde hocam resimleri şeçtikten sonra tamam butonuna bastığımızda hiç bir işlem gerçekleşmiyor ve o şekil ekran bekliyor ama uygulama bu sefer çökmedi.
"Look up the symbol (kUTTypeImage) and locate the image/library it should exist in (MobileCoreServices.framework in this case). Then link your binary with that framework." ....
kullanım alanları
/ // Tekdüzen Tip Tanımlayıcılarına dayalı API'lar için (iOS 14+)
iOSapi.UniformTypeIdentifiers,
/ // Eski API'lar ve sabitler için (klasik UTI mekanizması)
iOSapi.MobileCoreServices;
Eğer amacınız sadece resimleri filtrelemek için standart Apple tanımlayıcısını iletmekse (örneğin, UIDocumentPickerViewController veya UIImagePickerController yapılandırırken), API köprüsünü içe aktarmadan doğrudan yerel iOS dizesini kullanabilirsiniz: https://stackoverflow.com/questions/6431...monkey-app
UTTypeImage'e karşılık gelen metinsel değer 'public.image'dir. Bu dizeyi Delphi yapılarına ayıklamanız veya dönüştürmeniz gerekiyorsa, yerel yönteme bağlı olarak StringToGUID fonksiyonunu kullanarak dönüştürmeyi veya NSValue/NSString olarak ele almayı unutmayın.
"Look up the symbol (kUTTypeImage) and locate the image/library it should exist in (MobileCoreServices.framework in this case). Then link your binary with that framework." ....
kullanım alanları
/ // Tekdüzen Tip Tanımlayıcılarına dayalı API'lar için (iOS 14+)
iOSapi.UniformTypeIdentifiers,
/ // Eski API'lar ve sabitler için (klasik UTI mekanizması)
iOSapi.MobileCoreServices;
Eğer amacınız sadece resimleri filtrelemek için standart Apple tanımlayıcısını iletmekse (örneğin, UIDocumentPickerViewController veya UIImagePickerController yapılandırırken), API köprüsünü içe aktarmadan doğrudan yerel iOS dizesini kullanabilirsiniz: https://stackoverflow.com/questions/6431...monkey-app
UTTypeImage'e karşılık gelen metinsel değer 'public.image'dir. Bu dizeyi Delphi yapılarına ayıklamanız veya dönüştürmeniz gerekiyorsa, yerel yönteme bağlı olarak StringToGUID fonksiyonunu kullanarak dönüştürmeyi veya NSValue/NSString olarak ele almayı unutmayın.
Hocam amacım galariden kullanıcının belirlediği resimleri alıp uygulama içindeki listview eklemek bunu uygulamamın android versiyonunda yapmaktayım. Uygulamamı ios sürüm çıkarmak istiyorum ama maalesef hala bu sorunu aşmış değilim.
Son denemelerimde hocam önerdiğiniz gibi sorgu kısmına uyguladığımda sorgudaki problemi çözdüm ve sorunsuz sorguyu geçiyorum fakat asıl resimleri aldığımız kodda hata veriyor.
if ResultItem.itemProvider.hasItemConformingToTypeIdentifier( StrToNSStr('public.image') ) then
begin
try
// burada kalıyor !!!
ResultItem.itemProvider.loadObjectOfClass( TUIImage.OCClass, LoadCompleted );
except on e : Exception do
begin
FOwner.Bekleme_Durumu(False);
FOwner.Bildirim_Mesaji(e.Message, True, False);
end;
Burada hocam AV hatası (Access Violation) alıyorum. LoadComleted prosedürü içinden olduğunu sanmıyorum çünkü prosedürü komple comment yapsam dahi yinede av hatası almaya devam ediyorum.
AI sorduğumda ise procedurenin cdecl; bu şekil başlaması gerektiğini derleme sorunu olduğunu söylüyor ama loadObjectOfClass içinde bu şekil derleme yapılamıyor IDE hatası veriyor.
1) İhlal hatası: olası nedenler:
a) nesne oluşturulmamış
b) nesne yok edilmiş
Her iki durumda da, "Arayüzler" (mobil cihazlarda yaygın) kullanırken, nesnenin ihtiyaç duyulana kadar "canlı kalmasını" sağlamalısınız. Bu nedenle, nesnenin yaşamaya devam etmesini "garanti etmek" için bir değişken kullanabilirsiniz!
Bu konuda yapay zekaya danıştığımda, prosedürün `cdecl` ile başlaması gerektiğini ve bunun bir derleme sorunu olduğunu öne sürdüler; ancak, `loadObjectOfClass` içinde bu şekilde derlemeye çalıştığımda IDE bir hata üretiyor.
1) "CDECL" türü bildirimi genellikle "C" dilinde yazılmış DLL/O (nesne) fonksiyonlarına erişmek içindir; bu durumda, Android, iOS ve MSWindows kütüphaneleri bu tür bir bildirimi kullanır.
Bu nedenle, API dokümantasyonuna başvurmalısınız. Çünkü orada nasıl kullanılacağına dair daha fazla bilgi bulacaksınız.
Örneğin, MSWindows'ta Delphi'nin bildirim türünün "C" standardında olduğunu belirtmesi gerekir; bu nedenle harici sistem fonksiyonlarına erişmek için, fonksiyon veya prosedür çağrısının sonunda şu yönergeyi kullanmalısınız:
function xxxxx( xxxxxxx ):integer; cdecl;
Ancak, bu fonksiyon yalnızca Delphi'nin dahili birimlerinde başlık bildirimi zaten tanımlanmışsa kullanılabilir olacaktır. Bunu yapmak için, CBuilder için başlık dosyalarını veya Delphi için .Pas birimlerini kontrol edebilirsiniz. Normalde, "USES" veya "INCLUDE" maddesini kullandığınızda, bu fonksiyonun hangi birimde bulunduğuna dair bir fikriniz zaten vardır. Örneğin, "Winapi.Windows.pas" biriminde, Delphi'nin Embarcadero'dan tanımlanarak kullandığı tüm MSWindows API fonksiyonlarını göreceksiniz.
iOS kullanmıyorum, bu yüzden Xcode ve benzeri programlara çok aşina değilim...
Ama genel olarak tavsiyem şu:
a) Anlaması kolay bir bölüm oluşturun, iOS'a kurun ve temel testler yapın!
b) Her yeni dağıtımda kademeli olarak özellikler ekleyin ve test edin.
c) Sadece yapay zeka kodunu kopyalamaya çalışmayın; onlardan her seferinde bir bölümü açıklamalarını isteyin. Genellikle size her şeyi birden vereceklerdir. Bu öğrenme için iyi değil. Onlardan küçük parçalar göstermelerini isteyin ve kodun neden çalışıp çalışmadığını anlayana kadar soru sormaya devam edin!
d) Programlama kesin bir bilim değil; yavaş yavaş bilgi edinme ve pratik yapma meselesidir. Sonunda her şey yoluna girer, ancak çok fazla emek gerektirir.
e) Unutmayın: On yıllarca deneyime sahip yazılım mühendisleri bile maliyetli olan temel hatalar yaparlar!
var
MyObjX : TObject; // your "object type" ...
MyObjInterface: IInterface; // your "interface x"
procedure Hello1( AObj: TObject );
begin
// to do something ...
AObj.Free; // DONT DO IT!!! = exception or access violation after get out here!
//
end;
procedure Hello2( MyObjInterface: IInterface );
begin
// to do something ...
//
MyObjInterface := nil; // DONT DO IT!!! = exception or access violation after get out here!
end;
procedure TForm1.Button1Click( Sender: TObject );
begin
MyObjX := TObject.Create; // my object is alive here....
try
Hello1( MyObjX ); // my object is alive here....
//
finally
MyObjX.Free; // my object is free here....
end;
//
MyObjInterface := TMyObj_Interfaced.Create; // my object is alive here....
try
Hello2( MyObjInterface ); // my object is alive here....
//
finally
MyObjX := nil; // my object is free here....
end;
end;
Özellikle "arayüzlerin" kullanımının yoğun olduğu sistemlerde, nesnenin hala canlı olup olmadığını her zaman kontrol etmelisiniz!!!
if (MyObj<>nil) and ( MyObj.PropXXX <> nil) then ....
veya // duruma bağlı olarak
if Assigned(MyObj) and Assigned( MyObj.PropXXX ) then ....
Assigned( ... ) genellikle değişken bir metodu veya nesneyi tanımladığında kullanılır, örneğin, bir olay metodunu tanımlayan sınıf alanları:
(17-07-2026, Saat: 05:30)emozgun Adlı Kullanıcıdan Alıntı: Merhabalar
Kastri Files Selector veya ShareItems hatasız çalışıyor. ios'ta Kastri yüklemek için buradan bilgi alabilirsiniz
Hocam cevabınız için teşekkürler. Fakat bu kullanıcı izni istiyor öyle değil mi ?
Picker yöntemi kullanıcı izni gerektirmiyor android de ki gibi bunu yapabilirsem daha kullanışlı olacak ama olmaz sa Files Selector örneğindeki yöntemi deneyeceğim maalesef