我想知道按钮被点击的viewController的名称是什么。我已经查看了here提供的答案。但我相信如果我在屏幕上有不同的容器视图,那么它将无法工作......每个按钮的viewController可能会有所不同。因此,我需要一个不同的解决方案。
所以我写了这个函数来递归查看,直到找到 tokyo berlin beijing orlando paris city
0 0 0 0 0 1 paris
1 0 0 0 0 0 sydney
2 0 0 0 1 0 orlando
3 0 0 0 0 0 milwaukee
。
UIViewController
唯一的问题是这一行:
extension UIView{
func getTypeOfMyViewController() -> UIViewController.Type?{
if let _super = superview as? UIViewController{ // logically wrong!
return type(of:_super)
}else if let _super = superview{
return _super.getTypeOfMyViewController()
}else{
assertionFailure("everything should end up being on some viewController")
return nil
}
}
}
它给了我以下警告:
来自UIView?'到不相关的类型' UIViewController'总是失败
if let _super = superview as? UIViewController{
是superview
,我不知道如何提取' viewController'其中包含'视图' 。
问题1:那我该怎么做?
此外,我想使用UIView
函数:
getTypeOfMyViewController
我这样做是因为我想为我的日志记录系统中的所有按钮水龙头创建一个唯一的标识符。
问题2: Swift是否为此提供了更简单的解决方案?
答案 0 :(得分:2)
视图控制器不是视图,因此它永远不能成为超级视图。你有正确的想法,但你看错了层次结构。您想要的不是视图层次结构,而是响应者链。
走上响应者链,直到你来到视图控制器:
program TestIntfMethodResolutions;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Variants,
System.Classes,
TypInfo,
RTTI{,
uRTTIHelper};
type
ITestInterface = interface
['{61553B5F-574A-4B0F-AB6F-0560E324B463}']
function GetA:integer;
procedure SetA(const AVal:integer);
property A:integer read GetA write SetA;
end;
{$RTTI EXPLICIT METHODS([vcPrivate,vcPublic])}
TTintimpl1 = class(TInterfacedObject,ITestInterface)
private
FA:integer;
function GetA: integer;
procedure SetA(const Value: integer);virtual; // Does not need to be virtual
public
property A:integer read GetA write SetA;
end;
{$RTTI EXPLICIT METHODS([vcPrivate,vcPublic])}
//Explicit RTTI settings causes the Private methods to show up in the method list
TIntimpl2 = class(TTIntimpl1,ITestInterface)
private
procedure MySetA(const Value:integer);virtual;
public
procedure ITestInterface.SetA = MySetA;
end;
TMain = class
private
{ Private declarations }
public
{ Public declarations }
procedure FormCreate;
end;
var
Form5: TMain;
procedure TMain.FormCreate;
var
ctx:TRttiContext;
avalue,bvalue:tvalue;
atype,bastyp:TRttiType;
aproplist:Tarray<TRttiProperty>;
amethlist:Tarray<TRttiMethod>;
isinst:boolean;
aninst:TRttiInstanceType;
anintf:TRttiInterfaceType;
intflist:Tarray<TRttiInterfaceType>;
inst:pointer;
anint:ITestInterface;
aprop:TRttiProperty;
codeptr:pointer;
asetmeth:TRTTIMethod;
begin
ctx:=TRttiContext.Create;
//Faxisloopthr:=TIntimpl2.Create;
anint:=TIntimpl2.Create;
avalue:=anint as TObject;
atype:=ctx.GetType(avalue.TypeInfo);
if atype.IsInstance then
begin
aninst:=atype.AsInstance;
aproplist:=aninst.GetProperties;
amethlist:=aninst.GetMethods;
bvalue:=TValue.FromOrdinal(aproplist[0].PropertyType.Handle,1);
inst:=avalue.AsObject;
aprop:=aproplist[0]; //I could have called aproplist[0].SetValue(...
aprop.SetValue(inst,bvalue);
end;
writeln('RTTI result '+anint.A.ToString); //Should give me 20 but I get 10 everytime
//asetmeth:=aprop.SetterMethod(inst); // returns SetA and not MySetA - need uRTTIhelper unit. https://github.com/RRUZ/blog/tree/master/RTTI
// setpropvalue(inst,aprop.PropInfo,bvalue.AsVariant); // calls SetA and not MySetA
//Manually setting the value calls the correct method
anint.A:=1;
writeln('Direct setting '+anint.A.ToString);
end;
{ T2ndIntf }
{ TTintimpl1 }
function TTintimpl1.GetA: integer;
begin
Result:=FA;
end;
procedure TTintimpl1.SetA(const Value: integer);
var
a:integer;
begin
FA:=Value*10;
writeln('In SetA ',FA);
end;
{ TIntimpl2 }
//Should get called - but the 1st implementing parent gets called
procedure TIntimpl2.MySetA(const Value: integer);
begin
FA:=Value*20;
writeln('In MySetA ',FA);
end;
begin
Form5:=TMain.Create;
try
Form5.FormCreate;
finally
Form5.Free;
readln;
end;
end.