如何识别viewController上添加了一个按钮?

时间:2018-06-01 19:31:50

标签: ios swift logging uiviewcontroller uibutton

我想知道按钮被点击的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是否为此提供了更简单的解决方案?

1 个答案:

答案 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.