Подсчет ссылок для объектов

Я прошел через множество ресурсов и, наконец, получил причину. Так или иначе, мое разрешение на манифест не получило разрешения на написание внешнего разрешения, как показано ниже.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Итак, что я сделал, я добавил разрешение времени выполнения для внешней записи, и оно работает нормально. я использую PermissionsAndroid из реактивный-родной .

коды ниже =>

try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
      {
        title: "Cool Photo App Camera Permission",
        message:
          "Cool Photo App needs access to your camera " +
          "so you can take awesome pictures.",
        buttonNeutral: "Ask Me Later",
        buttonNegative: "Cancel",
        buttonPositive: "OK"
      }
    );
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      console.log("You can use the camera");

      const data = await this.camera.takePictureAsync();
      let saveResult = CameraRoll.saveToCameraRoll(data.uri);
      console.warn("takePicture ", saveResult);
      console.warn("picture url ", data.uri);
    } else {
      console.log("Camera permission denied");
    }
  } catch (err) {
    console.warn(err);
  }
8
задан Community 23 May 2017 в 11:52
поделиться

7 ответов

К сожалению, компилятор Delphi генерирует необходимый код для подсчета ссылок inc / dec только при использовании интерфейсов (в вашем случае пользовательский интерфейс IFileInfo). Более того, если интерфейсы приводятся к указателю (или TObject в этом отношении), опять же, подсчет ссылок невозможен. Например, предполагая, что список глобальных переменных: TList:

var ifi : IFileInfo;
begin
  ifi := TFileInfo.Create;
  list.Add(TFileInfo(ifi));
end;

после того, как метод возвращает список, [list.Count - 1] будет содержать висячий указатель.

Таким образом, интерфейсы нельзя использовать в хэш-карте, которая приводит их к указателям, реализация хэш-карты должен держать их как II-интерфейс.

6
ответ дан 5 December 2019 в 06:39
поделиться

Подсчет ссылок в Delphi работает, только если у вас есть ссылка на ваш экземпляр через интерфейс. Как только вы смешаете ссылки на интерфейсы и ссылки на классы, у вас возникнут проблемы.

По сути, вам нужен подсчет ссылок без необходимости создавать интерфейс со всеми методами и свойствами, определенными в нем. Есть три способа сделать это, и они примерно в том порядке, в котором я бы их порекомендовал.

  1. Барри Келли написал пост о умных указателях . Он использует Generics в Delphi 2009, но я вполне уверен, что вы можете жестко закодировать его для конкретных версий типа, который вы используете, если вы еще не используете 2009 (это отличный выпуск BTW).

  2. Другой способ, который работает с большим количеством версий Delphi и меньшей модификацией является оболочка типа значения от Janez Atmapuri Makovsek. Это пример, реализованный для TStringList, но вы можете адаптировать его для любого типа.

  3. Третий способ - создать интерфейсный указатель (аналогично Smart Pointer Барри, но не такой умный). Я считаю, что в JCL есть такой, но я точно не помню деталей. По сути, это интерфейс, который принимает ссылку TObject при создании. Затем, когда счетчик ссылок достигает нуля, он вызывает free для объекта, который вы ему передали. Этот метод действительно работает только для кратковременных экземпляров, которые вы не передаете в качестве параметров, поскольку вы отделяете ссылку с подсчетом ссылок от фактически используемой ссылки. Вместо этого я бы порекомендовал один из двух других методов, но если вы предпочитаете этот метод и хотите больше информации, просто дайте мне знать.

В этом и заключается проблема Delphi, есть бесплатные способы выполнения задач. Вариант № 1, на мой взгляд, лучший - приобретите Delphi 2009 и используйте этот метод, если можете.

Удачи!

8
ответ дан 5 December 2019 в 06:39
поделиться

Не смешивайте ссылки на объекты и ссылки на интерфейсы.

var
  Intf: IInterface;
  Obj: TFileInfo;

begin
  // Interface Reference
  Intf := TFileInfo.Create; // Intf is freed by reference counting, 
                            // because it's an interface reference
  // Object Reference
  Obj := TFileInfo.Create;
  Obj.Free; // Free is necessary

  // Dangerous: Mixing
  Obj := TFileInfo.Create;
  Intf := Obj; // Intf takes over ownership and destroys Obj when nil!
  Intf := nil; // reference is destroyed here, and Obj now points to garbage
  Obj.Free; // this will crash (AV) as Obj is not nil, but the underlying object
            // is already destroyed
end;
4
ответ дан 5 December 2019 в 06:39
поделиться

Эта функциональность предоставляется для интерфейсов, но не для объектов.

Вы можете создать что-то подобное, но вам нужно переопределить некоторую структуру TObject:

TRefCountObject = class (TObject)
private
  FRefCount : Integer;
public
  constructor Create;

  procedure Free; reintroduce;

  function RefCountedCopy: TRefCountObject;
end;


constructor TRefCountObject.Create;
begin
  inherited;
  FRefCount := 1;
end;

procedure TRefCountObject.Free;
begin
  if self=nil then Exit;
  Dec(FRefCount);
  if FRefCount<=0 then
    Destroy;
end;

function TRefCountObject.RefCountedCopy: TRefCountObject;
begin
  Inc(FRefCount);
  Result := self;
end;

Вам нужен RefCountingCopy, чтобы назначить объект другой переменной. Но тогда у вас есть пересчитанный объект.

Как это использовать:

var1 := TRefCountObject.Create;   // rc = 1
var2 := var1.RefCountedCopy;      // rc = 2
var3 := var1.RefCountedCopy;      // rc = 3
var2.Free;                        // rc = 2
var1.Free;                        // rc = 1
var4 := var3.RefCountedCopy;      // rc = 2
var3.Free;                        // rc = 1
var4.Free;                        // rc = 0
3
ответ дан 5 December 2019 в 06:39
поделиться

Чтобы добавить к тому, что уже было сказано, если вы хотите хранить ссылки на интерфейсы, вместо использования TList используйте TInterfaceList . Счетчик ссылок будет работать последовательно.

1
ответ дан 5 December 2019 в 06:39
поделиться

Для этого есть длинное объяснение, но вкратце: наследования от TInterfacedObject (и не вызова Free самостоятельно) недостаточно, вам нужно использовать object-factory-dynamic для создания объектов для вас, и используйте интерфейсные указатели на объект повсюду, а не просто объект-ссылка-переменные. (Да, это означает, что вы не можете просто переключить «старый код», не просматривая его)

0
ответ дан 5 December 2019 в 06:39
поделиться

Если вы хотите исключить вызовы free в экземплярах TObject, то вам, возможно, стоит взглянуть на сборщик мусора для нативного Delphi. Я знаю о 2 разных сборщиках мусора и технике сбора мусора, каждый со своими плюсами и минусами.

Один из них, вероятно, подойдет вам.

3
ответ дан 5 December 2019 в 06:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: