FindFirst() бъги ли под XE2/Firemonkey с iOS?

За приложение на iPhone Firemonkey съхранявам файлове (изображения) в папката „tmp“ и ги използвам в моето приложение. Искам да мога да изчистя кеша, като изтрия да речем всички „.jpg“ файлове при поискване, но изглежда не мога да ги съпоставя програмно в извикване FindFirst().

Използвам прост цикъл FindFirst() / FindNext() / FindClose() за изброяване (и изтриване) на съдържанието на папка.

Под Windows кодът работи перфектно. Същото приложение под iOS (iPhone) винаги връща стойност -1 (грешка) за извикването FindFirst() и SearchRec.Name е празно. Опитах да използвам различни шаблони на файлове, включително '.' без успех.

Знам, че файловете съществуват, защото мога да ги чета и пиша (под iOS и Windows) без грешка и съдържанието им е правилно. Проверката FileExists() също връща True.

Освен това, ако посоча шаблон на файл без заместващ знак, за да проверя за известен файл (което наистина не е смисълът на извикване FindFirst()), извикването никога не се връща (отново това е добре под прозорците)!

Някой имал ли е успех с това под iOS и може ли да предложи някакви мисли?

Благодаря,

РЕДАКТИРАНЕ: Кодов фрагмент според искането, който демонстрира проблема. Забележка: _sFolderName съдържа името на папката в кеша, което потвърдих, че определено е правилно.

function GetCacheFileList : string;
var
  iResult: integer;
  sr: TSearchRec;
  sPath,
  sTemp: string;
  sFilename : TFilename;
begin
  sTemp     := '';
  sFilename := _sFolderName + '*.jpg';
  //
  iResult := FindFirst(sFilename, faAnyFile, sr);  // ALWAYS RETURNS -1 under iOS
  while (iResult = 0) do
  begin
    sTemp := sTemp + sr.Name + sLineBreak;
    iResult := FindNext(sr)
  end; { while }
  //
  FindClose(sr);
  Result := sTemp
end;

person Peter    schedule 21.11.2011    source източник
comment
Бихте ли публикували код за възпроизвеждане на проблема? Използвахте ли специфичния POSIX разделител на пътя „/“ вместо „\“? Не съм убеден, че папката 'tmp' е мястото за внедряване на кеш. Опитахте ли в друга папка?   -  person Arnaud Bouchez    schedule 21.11.2011
comment
Здравейте AB, да, разделителите на пътя са правилни (и за Windows, и за iOS). Оттогава открих, че има папка /library/caches/, която сега използвам, но резултатът е същият. Ще публикувам малко код по-горе, но това е доста незабележимо нещо. Също така бях информиран, че е имало грешка в обработката на файлове на FreePascal в iOS, която може да бъде коригирана във 2.6.0rc1, което ще опитам на следващия ден или така, когато се върна към него. Благодаря за вашите предложения (+1).   -  person Peter    schedule 23.11.2011


Отговори (3)


Не знам доколко FindFirst и т.н. се поддържат на различни от Windows платформи, но си спомням, че някой от екипа на Delphi каза веднъж, че рутинните процедури в модула IOUtils са специално проектирани, за да накарат файловия I/O да работи правилно за кръстосани кодиране на платформата. Опитахте ли да използвате методите за търсене на файлове на TDirectory?

person Mason Wheeler    schedule 21.11.2011
comment
Добра мисъл (+1), но както при много от по-новите функции на Delphi, те всъщност не се поддържат между платформи, тъй като в случая на iOS компилацията се извършва под XCode с помощта на безплатния компилатор Pascal, който не поддържат тези функции. - person Peter; 21.11.2011
comment
Findfirst работи добре като цяло на FPC. Но не използвам iOS, така че може да е нещо специфично за iOS. Не знам дали iOS поддържа функция като ktrace/strace/truss, но това би било нещото, което трябва да опитам. Afaik повечето от псевдо ООП рутинните процедури в последните Delphi наричат ​​старите процедурни версии. - person Marco van de Voort; 24.11.2011

Не знам дали Delphi XE 2 се доставя със заглавки от iOS SDK, но можете да ги генерирате за FreePascal(прочетете тук). И след това използвайте този метод чрез стандартен API:

{$modeswitch objectivec1}

uses
  iPhoneAll, CFBase, CFString;

type
  TFileList = record
    Count : Integer;
    Items : array of String;
end;

procedure file_Find( const Directory : String; var List : TFileList; FindDir : Boolean = FALSE );
  var
    i           : Integer;
    fileManager : NSFileManager;
    dirContent  : NSArray;
    path        : NSString;
    fileName    : array[ 0..255 ] of Char;
    error       : NSErrorPointer;
    isDirectory : Boolean;
begin
  fileManager := NSFileManager.alloc().init();
  path        := NSString( CFStr( PChar( Directory ) ) );
  dirContent  := fileManager.contentsOfDirectoryAtPath_error( path, error );
  List.Count  := 0;
  fileManager.changeCurrentDirectoryPath( path );
  for i := 0 to dirContent.count() - 1 do
    begin
      if FindDir Then
        begin
          if ( fileManager.fileExistsAtPath_isDirectory( dirContent.objectAtIndex( i ), @isDirectory ) ) and ( not isDirectory ) Then continue;
        end else
          if ( fileManager.fileExistsAtPath_isDirectory( dirContent.objectAtIndex( i ), @isDirectory ) ) and ( isDirectory ) Then continue;

      SetLength( List.Items, List.Count + 1 );
      FillChar( fileName[ 0 ], 256, 0 );
      CFStringGetCString( CFStringRef( dirContent.objectAtIndex( i ) ), @fileName[ 0 ], 255, kCFStringEncodingUTF8 );
      List.Items[ List.Count ] := PChar( @fileName[ 0 ] );
      INC( List.Count );
    end;
  fileManager.dealloc();
end;

Тази функция връща запис TFileList с масив от всички намерени файлове (или директории). След това можете просто да анализирате имената на файловете и да направите нещо с jpg файлове.

person Andru    schedule 23.11.2011
comment
Здравей Андру, Благодаря за коментара и връзката към уебсайта на Фил (който преди това бях отбелязал с отметка - той изглежда е любимият човек на FPC и iOS). Първият ми избор е да използвам стандартните Pascal извиквания, тъй като в крайна сметка искам възможно най-голяма независимост от платформата (за Windows и евентуално android поддръжка в XE3 да кажем). Използването на какао (с малко условна компилация), както описахте, обаче е моята резервна позиция и е много вероятно такава, която ще запазя. Оценявам помощта ви (+1). - person Peter; 24.11.2011

Това е поправено в XE2 актуализация 3

person Peter    schedule 10.01.2012