在备忘录中列出原始传感器数据

Dan*_*all 7 delphi android firemonkey delphi-xe8

我想在Memo for Android中列出所有可用的原始传感器数据.

以下代码在过去几年中起作用,但它不适用于XE8.可能存在内部编译器错误.我有什么办法可以让它再次运作,还是有替代解决方案?

uses
  TypInfo;

type
  TOrientationSensorAccessor = class(TCustomOrientationSensor);
  TLocationSensorAccessor = class(TCustomLocationSensor);

procedure TForm2.Button1Click(Sender: TObject);
var
  p_location: TCustomLocationSensor.TProperty;
  p_orientation: TCustomOrientationSensor.TProperty;
  n, v: string;
begin
  Memo1.Lines.Clear;

  if Assigned(OrientationSensor1.Sensor) then
  begin
    if not OrientationSensor1.Sensor.Started then OrientationSensor1.Sensor.Start;

    // Error (only in XE8): Incompatible types 'TCustomLocationSensor.TProperty' and 'TCustomOrientationSensor.TProperty'
    // In XE7 it works.
    for p_orientation in OrientationSensor1.Sensor.AvailableProperties do
    begin
      n := 'OrientationSensor.'+GetEnumName(TypeInfo(TCustomOrientationSensor.TProperty), integer(p_orientation)) ;
      v := FloatToStr(TOrientationSensorAccessor(OrientationSensor1.Sensor).GetDoubleProperty(p_orientation));
      Memo1.Lines.Values[n] := v;
    end;
  end;

  if Assigned(LocationSensor1.Sensor) then
  begin
    if not LocationSensor1.Sensor.Started then LocationSensor1.Sensor.Start;
    for p_location in LocationSensor1.Sensor.AvailableProperties do
    begin
      n := 'LocationSensor.'+GetEnumName(TypeInfo(TCustomLocationSensor.TProperty), integer(p_location)) ;
      v := FloatToStr(TLocationSensorAccessor(LocationSensor1.Sensor).GetDoubleProperty(p_location));
      Memo1.Lines.Values[n] := v;
    end;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

更新

一些实验:

(1)当我注释掉第一个"for"时,它将编译:

//    for p_orientation in OrientationSensor1.Sensor.AvailableProperties do
//    begin
      n := 'OrientationSensor.'+GetEnumName(TypeInfo(TCustomOrientationSensor.TProperty), integer(p_orientation)) ;
      v := FloatToStr(TOrientationSensorAccessor(OrientationSensor1.Sensor).GetDoubleProperty(p_orientation));
      Memo1.Lines.Values[n] := v;
//    end;
  end;
Run Code Online (Sandbox Code Playgroud)

(2)当我注释掉"n"和"v"的分配时,它也会编译:

    for p_orientation in OrientationSensor1.Sensor.AvailableProperties do
    begin
//      n := 'OrientationSensor.'+GetEnumName(TypeInfo(TCustomOrientationSensor.TProperty), integer(p_orientation)) ;
//      v := FloatToStr(TOrientationSensorAccessor(OrientationSensor1.Sensor).GetDoubleProperty(p_orientation));
//      Memo1.Lines.Values[n] := v;
    end;
  end;
Run Code Online (Sandbox Code Playgroud)

既然"for","n"和"v"都不是坏区,那么错误在哪里呢?

(3)当我注释掉第二个for循环时,它将再次编译.如果我注释掉第一个for循环,它也会编译.每个for循环都可以工作,但是它们组合起来不起作用.

看起来错误只发生在5个因素的组合中:

  • TypInfo
  • 访问器
  • for循环
  • TypInfo的用法(GetEnumName)
  • 使用两个for循环.

更新2

这是我能找到的最小的可重现代码.如果注释掉任何行,它将编译:

program ProjectCompilerBug;

{$APPTYPE CONSOLE}

uses
  System.Sensors, System.Sensors.Components;

var
  p_location: TCustomLocationSensor.TProperty;
  p_orientation: TCustomOrientationSensor.TProperty;
begin
  // Compilation Error (only in XE8):
  // "Incompatible types 'TCustomLocationSensor.TProperty' and 'TCustomOrientationSensor.TProperty'"
  // In XE7 it compiles
  for p_orientation in TOrientationSensor.Create(nil).Sensor.AvailableProperties do
  begin
    FloatToStr(1.23);
  end;

  for p_location in TLocationSensor.Create(nil).Sensor.AvailableProperties do
  begin
  end;
end.
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 5

是的,这看起来像是一个XE8编译器错误.我认为你已经做好了隔离工作,我赞扬你.您需要向Quality Portal提交错误报告.

为了解决这个问题,我认为你可以将循环放在不同的函数中.我的假设是关键是存在两个for循环,其中不同类型的循环变量是关键.避免这种情况,你应该能够避免这个问题.