iOS审核被拒绝-Delphi开发的APP在暗黑主题模式下的处理

前段时间,我的门业APP审核被拒,苹果审核团队说APP在登录的时候显示有问题。

We discovered one or more bugs in your app. Specifically, your app displayed an error message during the login.

还附了一张截图给我,

Screenshot-0503-170834

咦,账号密码输入框的提示怎么不见了?不应该呀?我这里都好好的呀。

IMG_256

是不是苹果那边审核团队的手机有问题?难道是我们Delphi支持新版的IOS不够完善?

这个输入框如果没有输入内容,那么至少“请输入验证码”这些提示应该在的吧。现在提示都没有显示,说明是输入了内容的。

那文本框的内容怎么变成透明了呢?再一想,会不会是文本框的字体颜色变成了白色了?难道是最近苹果系统出的暗黑模式搞的鬼?

说完,在测试手机上开启暗黑模式:

9CCB691B9773501EE7B6D7CF344C3462

果不其然!问题重现了!

那怎么办?难道我得把我的APP也跟着苹果一样搞个深色主题?那工作量还是有点大的,怎么办?客户急着用,APP得赶紧更新上去才行呀。

如何解决呢?在暗黑模式下,字体是如何变成白色的呢?或者说,Edit如何被切换成黑底白字的样式的呢?

这些都是FireMonkey自动处理的。自从苹果13.0系统出了深色主题之后,FireMonkey也做了相应的处理。

首先FMX.Platform.pas中定义了IFMXSystemAppearanceService 接口:

/// <summary>Service provides information about operation system theme.</summary>

IFMXSystemAppearanceService = interface

[‘{AB6A83D9-0118-4C5F-95CC-351DBB5EA943}’]

/// <summary>Returns system theme kind.</summary>

function GetSystemThemeKind: TSystemThemeKind;

/// <summary>Returns system color for specified type.</summary>

function GetSystemColor(const AType: TSystemColorType): TAlphaColor;

/// <summary>System theme kind.</summary>

property ThemeKind: TSystemThemeKind read GetSystemThemeKind;

end;

这个接口用于实现在每个平台下能获取当前系统的样式信息,比如样式类型,是浅色样式还是暗黑样式,还有就是系统主题颜色。

每个平台的TPlatform*****类都要实现IFMXSystemAppearanceService接口,

比如IOS平台,是在FMX.Platform.iOS.pas中的TPlatformCocoaTouch被实现的:

function TPlatformCocoaTouch.GetSystemThemeKind: TSystemThemeKind;

begin

case GetUserInterfaceStyle of

UIUserInterfaceStyleLight:

Result := TSystemThemeKind.Light;

UIUserInterfaceStyleDark:

Result := TSystemThemeKind.Dark;

else

Result := TSystemThemeKind.Unspecified;

end;

end;

那只只要根据SystemThemeKind搜索代码,Delphi肯定在某个地方根据SystemThemeKind来决定用什么样式,太简单了!

可是,我在Delphi的代码中找了半天,没有发现它在哪里切换的样式,只是在IOS下面,发现在TFMXViewController.traitCollectionDidChange事件中发送了样式切换消息TStyleChangedMessage以及系统主题样式更改消息TSystemAppearanceChangedMessage:

procedure TFMXViewController.traitCollectionDidChange(previousTraitCollection: UITraitCollection);

var

Message: TSystemAppearanceChangedMessage;

begin

UITraitEnvironment(Super).traitCollectionDidChange(previousTraitCollection);

TMessageManager.DefaultManager.SendMessage(nil, TStyleChangedMessage.Create(nil, nil), True);

PlatformCocoaTouch.WindowManager.UpdateStatusBar;

Message := TSystemAppearanceChangedMessage.Create(TSystemAppearance.Create, True);

TMessageManager.DefaultManager.SendMessage(nil, Message, True);

end;

难道我关键词找错了?

在TPlatformCocoaTouch.GetSystemThemeKind方法中它是调用的GetUserInterfaceStyle函数返回系统主题样式,那么Delphi是不是直接使用这个方法来判断使用的样式呢?

果然,在FMX.Controls.iOS单元中发现了关键的代码:

首先,这个单元定义了两个样式,

const

iOSLightStyle = ‘iosstyle’;

iOSDarkStyle = ‘ios13darkstyle’;

iosstyle表示浅色样式,而ios13darkstyle则就是暗黑样式的名称了,

然后又定义了一个iOSStyleSelection方法,根据当前的系统样式来返回对应的FireMonkey样式名称。

function iOSStyleSelection(const APlatform: TOSPlatform): string;

begin

{$IFDEF WIN32}

Result := iOSLightStyle;

{$ELSE}

if GetUserInterfaceStyle = UIUserInterfaceStyleDark then

Result := iOSDarkStyle

else

Result := iOSLightStyle;

{$ENDIF}

end;

再继续摸,会发现iOSStyleSelection这个方法是在FMX.Styles.pas中被调用的,

TStyleManager.StyleResourceForContext会返回当前的样式名称,:

class function TStyleManager.StyleResourceForContext(const Context: TFmxObject): string;

var

DeviceInfo: IDeviceBehavior;

OSPlatform: TOSPlatform;

PlatformSelection: TPlatformStyleSelectionProc;

begin

if TBehaviorServices.Current.SupportsBehaviorService(IDeviceBehavior, DeviceInfo, Context) then

OSPlatform := DeviceInfo.GetOSPlatform(Context)

else

raise EStyleException.CreateRes(@SNoIDeviceBehaviorBehavior);

if (FSelections <> nil) and FSelections.TryGetValue(OSPlatform, PlatformSelection) then

Result := PlatformSelection(OSPlatform)

else

Result := FindDefaultStyleResource(OSPlatform);

end;

然后TStyleManager.ActiveStyle从资源中加载出样式并返回:

class function TStyleManager.ActiveStyle(const Context: TFmxObject): TFmxObject;

var

StyleResource: string;

begin

StyleResource := StyleResourceForContext(Context);

Result := GetStyleResource(StyleResource);

end;

我有点好奇想看看这个样式,尝试将这个样式资源取出来,并将它保存到C盘:

报错了,

那应该是样式在Windows下没有编译进去,我想应该是一个res文件,所以我在安装目录搜,

1.72M,体积还蛮大,应该就是它了,

用{$R FMX.Controls.iOS.res}将这个资源编译进去

这次可以了,

用记事本打开看一下,

看着里面一堆控件样式的名字,那应该是对了,

再在窗体上放一个TStyleBook组件,加载这个样式文件,看看是什么样式的,

找到Edit的样式“editstyle”,背景是黑的,那就是了!

那么Edit的字体颜色是受样式中哪个元素控制的呢?

看了一下StyleEdit的代码,

默认,文本框Edit的默认字体颜色是取的样式中foreground元素的画刷颜色,

我们在StyleBook中来看一下这个foreground元素,

字体原来就是这么变白的。

那么如何解决这个问题呢?那就让Edit的字体颜色不受style控制就行了,去掉Edit.StyledSettings中的FontColor的勾即可。

好了,问题搞定,提交审核,等苹果审核通过即可。

下面放几张截图吧,OrangeUI开发的一款门业助手APP:

QQ图片20220530150543

QQ图片20220530150548

QQ图片20220530150612

QQ图片20220530150606 QQ图片20220530150600 QQ图片20220530150555

打算使用Delphi开发APP的朋友,欢迎加入我的QQ群10900297,来一起交流学习: