GVKun编程网logo

objective-c – 为什么Interface Builder会让我感觉不舒服?(c++ interface)

16

在这篇文章中,我们将带领您了解objective-c–为什么InterfaceBuilder会让我感觉不舒服?的全貌,包括c++interface的相关情况。同时,我们还将为您介绍有关delphi–为

在这篇文章中,我们将带领您了解objective-c – 为什么Interface Builder会让我感觉不舒服?的全貌,包括c++ interface的相关情况。同时,我们还将为您介绍有关delphi – 为什么不收集TInterfacedObject垃圾的后代?、delphi – 为什么类(TInterfacedObject,IDropTarget)的实例不能自动释放?、Interface Builder nib2objc ibtool、interface-builder – 如何从Xcode 5中的Interface Builder中删除对象?的知识,以帮助您更好地理解这个主题。

本文目录一览:

objective-c – 为什么Interface Builder会让我感觉不舒服?(c++ interface)

objective-c – 为什么Interface Builder会让我感觉不舒服?(c++ interface)

我对 Cocoa for MacOSX很新,但我不禁觉得我一直在与Interface Builder对抗.

我目前的情况是我正在构建一个具有多个自定义控件和视图的应用程序.我开始在Interface Builder中构建应用程序,因为它最初很容易拖动并使用正确的颜色和正确的自动调整规则将它们放入正确的位置.然而,现在是开始构建我的自定义控件和视图的时候了 – 我无法在Interface Builder中很好地代表它,而无需完成构建IBPlugin的工作!我所知道的唯一另一个选择是拥有一个Interface Builder文档,其中包含一堆“自定义视图”,只更改了类.即使对IB感到麻烦,这似乎也毫无意义 – 尤其是考虑到这些控件和视图将具有需要设置的颜色等属性的事实 – 就像IB文档中已有的其他视图和控件一样.所以现在我已经在两个断开连接的位置设置了可视化属性,似乎与IB的一个潜在优势相反,这使得相对容易调整应用程序的UI而无需深入研究代码.

我还面临一种情况,即一些控件根据数据或当前选择更改属性(如颜色).所以现在我在Interface Builder中指定了控件的初始默认颜色,但是我必须在代码中指定数据驱动的颜色? Interface Builder似乎再次让我必须在它的世界和代码之间拆分一些表示设置.我想有可能通过一个了解我的数据或状态或其他的复杂插件来解决这个问题,但似乎我最终维护了大量的支持代码,因此Interface Builder的经验仍然是“正确的”.

我经常看到的其他一些内容是IB允许您轻松定义组件之间的绑定. “你可以不用编写任何代码就可以做到!”同样,我可能会遗漏一些东西,但据我所知,将一个属性绑定到另一个属性是一行代码.在IB中的框中设置几个属性真的比编写一行代码要好吗?为什么在表示层的规范中添加相当于应用程序逻辑的更好?

就像我在公开场合所说的那样,我对这个Cocoa的东西很新,但是我觉得我要么缺少一些关于如何使用Interface Builder的非常重要的东西,要么它主要是设计用于具有高“哇”的琐碎演示应用程序因子.

解决方法

我发现Interface Builder非常适合获取应用程序的通用布局.对于像绑定这样的东西(在Mac上)也很棒.但是,您无法使用Interface Builder创建DelicIoUs Library.您的界面越复杂,您需要编写的代码就越多.

delphi – 为什么不收集TInterfacedObject垃圾的后代?

delphi – 为什么不收集TInterfacedObject垃圾的后代?

我有一个基于TInterfacedobject的类.我将它添加到TTreeNode的Data属性.
TFacilityTreeItem=class(TInterfacedobject)
private
  m_guidItem:TGUID;
  m_SomeOtherNode:TTreeNode;
public
end;

我创建了这个对象的许多实例&我认为因为他们的参考计数,我不应该释放他们.这很方便.

但是,在检查时,我打开了ReportMemoryLeaksOnShutdown,发现它们毕竟没有被释放.

这些对象是在放置在主窗体上的框架中创建的.在主窗体的FormClose中,我清除树节点,以便释放每个对象.

发生了什么?

感谢您的帮助!

解决方法

TInterfacedobject本身不是引用计数,只有接口.您可以使用TInterfacedobject实现接口,这基本上可以节省您自己实现引用计数方法的工作量.不幸的是,它仍然不适用于您的情况:编译器不知道您正在为TTreeNode.Data属性分配接口,因为它未被声明为接口而是作为指针.所以各种奇怪的事情都会发生:
MyInt := TFacilityTreeItem.Create; // ref count = 1
// Node.Data := MyInt; // won't compile
Node.Data := pointer(MyInt); // no interface assignment,ref count stays 1
...
end; // ref count reaches 0,your object gets freed

只要您尝试通过.Data属性访问对象,就会遇到访问冲突.

所以,在这种情况下不要打扰接口,你可以让它工作,但它将比它的价值更多的努力.

delphi – 为什么类(TInterfacedObject,IDropTarget)的实例不能自动释放?

delphi – 为什么类(TInterfacedObject,IDropTarget)的实例不能自动释放?

我正在实现我的IDropTarget: How can I allow a form to accept file dropping without handling Windows messages?

大卫的implementation工作得很好.但是IDropTarget(TInterfacedobject)对象不会自动释放,即使设置为’nil’也不会.

部分代码是:

{ TDropTarget }
constructor TDropTarget.Create(AHandle: HWND; const ADragDrop: IDragDrop);
begin
  inherited Create;
  FHandle := AHandle;
  fdragDrop := ADragDrop;
  OleCheck(RegisterDragDrop(FHandle,Self));
  //_Release;
end;

destructor TDropTarget.Destroy;
begin
  MessageBox(0,'TDropTarget.Destroy','',MB_TASKMODAL);
  RevokeDragDrop(FHandle);
  inherited;
end;
...

procedure TForm1.FormShow(Sender: TObject);
begin
  Assert(Panel1.HandleAllocated);
  fdropTarget := TDropTarget.Create(Panel1.Handle,nil) as IDropTarget;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  fdropTarget := nil; // This should free fdropTarget
end;

var
  NeedOleUninitialize: Boolean = False;

initialization
  NeedOleUninitialize := Succeeded(OleInitialize(nil));

finalization
  if (NeedOleUninitialize) then
    OleUninitialize;

end.

其中fdropTarget:IDropTarget;.

单击按钮时,不会显示MessageBox,也不会销毁对象.

如果我打电话给_Release; as suggested here在构造函数的末尾,当我点击按钮或程序终止时,fdropTarget被销毁(我对这个“解决方案”有疑问).

如果我省略RegisterDragDrop(FHandle,Self),则会按预期销毁fdropTarget.

我认为引用计数因某种原因被破坏了.我真的很困惑.如何正确释放TInterfacedobject?

编辑:

这是完整的代码:

unit Unit1;

interface

uses
  Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,VirtualTrees,ExtCtrls,StdCtrls,ActiveX,ComObj;

type    
  TDropTarget = class(TInterfacedobject,IDropTarget)
  private
    FHandle: HWND;
    fdropAllowed: Boolean;
    function GetTreeFromDataObject(const DataObject: IDataObject): TBaseVirtualTree;
    procedure SetEffect(var dwEffect: Integer);
    function dragenter(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult; stdcall;
    function DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;
    function DragLeave: HResult; stdcall;
    function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;
  public
    constructor Create(AHandle: HWND);
    destructor Destroy; override;
  end;

  TForm1 = class(TForm)
    Panel1: TPanel;
    VirtualStringTree1: TVirtualStringTree;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure VirtualStringTree1Dragallowed(Sender: TBaseVirtualTree;
      Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean);
    procedure Button1Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    fdropTarget: IDropTarget;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

{ TDropTarget }

constructor TDropTarget.Create(AHandle: HWND);
begin
  inherited Create;
  FHandle := AHandle;
  OleCheck(RegisterDragDrop(FHandle,MB_TASKMODAL);
  RevokeDragDrop(FHandle);
  inherited;
end;

function TDropTarget.GetTreeFromDataObject(const DataObject: IDataObject): TBaseVirtualTree;
// Returns the owner/sender of the given data object by means of a special clipboard format
// or nil if the sender is in another process or no virtual tree at all.
var
  Medium: TStgMedium;
  Data: PVTReference;
  formatetcIn: TFormatEtc;
begin
  Result := nil;
  if Assigned(DataObject) then
  begin
    formatetcIn.cfFormat := CF_VTREFERENCE;
    formatetcIn.ptd := nil;
    formatetcIn.dwaspect := DVASPECT_CONTENT;
    formatetcIn.lindex := -1;
    formatetcIn.tymed := TYMED_ISTREAM or TYMED_HGLOBAL;
    if DataObject.GetData(formatetcIn,Medium) = S_OK then
    begin
      Data := GlobalLock(Medium.hGlobal);
      if Assigned(Data) then
      begin
        if Data.Process = GetCurrentProcessID then
          Result := Data.Tree;
        GlobalUnlock(Medium.hGlobal);
      end;
      ReleaseStgMedium(Medium);
    end;
  end;
end;

procedure TDropTarget.SetEffect(var dwEffect: Integer);
begin
  if fdropAllowed then begin
    dwEffect := DROPEFFECT_copY;
  end else begin
    dwEffect := DROPEFFECT_NONE;
  end;
end;

function TDropTarget.dragenter(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
var
  Tree: TBaseVirtualTree;
begin
  Result := S_OK;
  try
    Tree := GetTreeFromDataObject(dataObj);
    fdropAllowed := Assigned(Tree);
    SetEffect(dwEffect);
  except
    Result := E_UNEXPECTED;
  end;
end;

function TDropTarget.DragLeave: HResult;
begin
  Result := S_OK;
end;

function TDropTarget.DragOver(grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
begin
  Result := S_OK;
  try
    SetEffect(dwEffect);
  except
    Result := E_UNEXPECTED;
  end;
end;

function TDropTarget.Drop(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
var
  Tree: TBaseVirtualTree;
begin
  Result := S_OK;
  try
    Tree := GetTreeFromDataObject(dataObj);
    fdropAllowed := Assigned(Tree);
    if fdropAllowed then
    begin
      Alert(Tree.Name);
    end;
  except
    Application.HandleException(Self);
  end;
end;

{----------------------------------------------------------------------------------------------------------------------}
procedure TForm1.FormCreate(Sender: TObject);
begin
  VirtualStringTree1.RootNodeCount := 10;
end;

procedure TForm1.VirtualStringTree1Dragallowed(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean);
begin
  Allowed := True;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  Assert(Panel1.HandleAllocated);
  fdropTarget := TDropTarget.Create(Panel1.Handle) as IDropTarget;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  fdropTarget := nil; // This should free fdropTarget
end;

var
  NeedOleUninitialize: Boolean = False;

initialization
  NeedOleUninitialize := Succeeded(OleInitialize(nil));

finalization
  if (NeedOleUninitialize) then
    OleUninitialize;

end.

DFM:

object Form1: TForm1
  Left = 192
  Top = 114
  Width = 567
  Height = 268
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Shell Dlg 2'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object Panel1: TPanel
    Left = 368
    Top = 8
    Width = 185
    Height = 73
    Caption = 'Panel1'
    TabOrder = 0
  end
  object VirtualStringTree1: TVirtualStringTree
    Left = 8
    Top = 8
    Width = 200
    Height = 217
    Header.AutoSizeIndex = 0
    Header.Font.Charset = DEFAULT_CHARSET
    Header.Font.Color = clWindowText
    Header.Font.Height = -11
    Header.Font.Name = 'MS Shell Dlg 2'
    Header.Font.Style = []
    Header.MainColumn = -1
    Header.Options = [hoColumnResize,hoDrag]
    TabOrder = 1
    TreeOptions.Selectionoptions = [toMultiSelect]
    OnDragallowed = VirtualStringTree1Dragallowed
    Columns = <>
  end
  object Button1: TButton
    Left = 280
    Top = 8
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 2
    OnClick = Button1Click
  end
end

结论:
From the docs:

RegisterDragDrop function also calls the IUnkNown::AddRef method on
the IDropTarget pointer

the answer I linked中的代码是固定的.

Note that reference counting on TDropTarget is suppressed. That is
because when RegisterDragDrop is called it increments the reference
count. This creates a circular reference and this code to suppress
reference counting breaks that. This means that you would use this
class through a class variable rather than an interface variable,in
order to avoid leaking.

解决方法

在TDragDrop.Create中对 RegisterDragDrop的调用将计数引用传递给TDragDrop的新实例的实例.这增加了它的参考计数器. fdragDrop:= Nil指令减少了引用计数器,但仍然存在对生存对象的引用,该对象阻止对象自行销毁.
在删除对该实例的最后一个引用之前,需要调用RevokeDragDrop(FHandle)以使引用计数器降至零.

简而言之:在析构函数中调用RevokeDragDrop为时已晚.

Interface Builder nib2objc ibtool

Interface Builder nib2objc ibtool

iphone开发就需要接触其中的xib文件。Interface BuilderIB)是Mac OS X平台下用于设计和测试用户界面(GUI)的应用程序,可以很直观的设计图形界面。实际上Mac OS X下所有的用户界面元素都可以使用代码直接生成;但IB能够使开发者简单快捷的开发出符合Mac OS X human-interface guidelinesGUI。通常你只需要通过简单的拖拽(drag-n-drop)操作来构建GUI就可以了。

IB使用Nib文件储存GUI资源,同时适用于CocoaCarbon程序。在需要的时候,Nib文件可以被快速地载入内存。

这里介绍一下ib相关的一点小技巧。

 

XIB文件转换为Objective-C源程序

 

nib2objc是一个小巧的转换工具,可以将XIB文件自动转换为Objective-C的源代码文件。

 

通常,考虑到程序的效率时,才将XIB直接转换为源代码文件。但是这样一来,通过Interface Builder设定的实例变量与行为方法的接续也没有了,需要从新手写。但是,该工具的源代码是公开的,稍加修饰,就能完成大部分工作。

 

使用的时候,首先下载的工程代码并用XCode编译一下,会生成一个命令行程序文件 nib2objc。然后如下所示执行转换:

$ nib2objc testnib2objc.xib > testnib2objc.m

这样就可以转换成代码。

 

Ibtool是一个nib资源文件本地化的小工具:

1.nib文件里面提取可以被本地化的字符串。 可以通过如下的命令在终端里面处理:

  ibtool --generate-stringsfile MyNib.strings MyNib.nib

2.等翻译好了字符串以后,就需要通过ibtool去把字符串合并到.nib文件里面去。 具体的命令如下:

  ibtool --strings-file MyNib.strings --write MyNewNib.nib MyNib.nib

其中MyNib.nib是你想修改的xib文件。

interface-builder – 如何从Xcode 5中的Interface Builder中删除对象?

interface-builder – 如何从Xcode 5中的Interface Builder中删除对象?

如何从对象库中删除添加到Interface Builder的对象?我通过简单地将对象拖出 Xcode外部的位置然后放下它来删除它.然而,当我以这种方式删除它并运行模拟器时,Xcode经常崩溃 – 所以也许,这不是我认为的理想方式.

另外,我不能以与this answer相同的方式删除它.为什么?或者Xcode 5不再支持它吗?

谢谢.

解决方法

选择对象,然后按删除键. 然后,您也可以单击编辑菜单并选择删除.

今天关于objective-c – 为什么Interface Builder会让我感觉不舒服?c++ interface的介绍到此结束,谢谢您的阅读,有关delphi – 为什么不收集TInterfacedObject垃圾的后代?、delphi – 为什么类(TInterfacedObject,IDropTarget)的实例不能自动释放?、Interface Builder nib2objc ibtool、interface-builder – 如何从Xcode 5中的Interface Builder中删除对象?等更多相关知识的信息可以在本站进行查询。

本文标签: