在这篇文章中,我们将带领您了解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)
- delphi – 为什么不收集TInterfacedObject垃圾的后代?
- delphi – 为什么类(TInterfacedObject,IDropTarget)的实例不能自动释放?
- Interface Builder nib2objc ibtool
- interface-builder – 如何从Xcode 5中的Interface Builder中删除对象?
objective-c – 为什么Interface Builder会让我感觉不舒服?(c++ interface)
我目前的情况是我正在构建一个具有多个自定义控件和视图的应用程序.我开始在Interface Builder中构建应用程序,因为它最初很容易拖动并使用正确的颜色和正确的自动调整规则将它们放入正确的位置.然而,现在是开始构建我的自定义控件和视图的时候了 – 我无法在Interface Builder中很好地代表它,而无需完成构建IBPlugin的工作!我所知道的唯一另一个选择是拥有一个Interface Builder文档,其中包含一堆“自定义视图”,只更改了类.即使对IB感到麻烦,这似乎也毫无意义 – 尤其是考虑到这些控件和视图将具有需要设置的颜色等属性的事实 – 就像IB文档中已有的其他视图和控件一样.所以现在我已经在两个断开连接的位置设置了可视化属性,似乎与IB的一个潜在优势相反,这使得相对容易调整应用程序的UI而无需深入研究代码.
我还面临一种情况,即一些控件根据数据或当前选择更改属性(如颜色).所以现在我在Interface Builder中指定了控件的初始默认颜色,但是我必须在代码中指定数据驱动的颜色? Interface Builder似乎再次让我必须在它的世界和代码之间拆分一些表示设置.我想有可能通过一个了解我的数据或状态或其他的复杂插件来解决这个问题,但似乎我最终维护了大量的支持代码,因此Interface Builder的经验仍然是“正确的”.
我经常看到的其他一些内容是IB允许您轻松定义组件之间的绑定. “你可以不用编写任何代码就可以做到!”同样,我可能会遗漏一些东西,但据我所知,将一个属性绑定到另一个属性是一行代码.在IB中的框中设置几个属性真的比编写一行代码要好吗?为什么在表示层的规范中添加相当于应用程序逻辑的更好?
就像我在公开场合所说的那样,我对这个Cocoa的东西很新,但是我觉得我要么缺少一些关于如何使用Interface Builder的非常重要的东西,要么它主要是设计用于具有高“哇”的琐碎演示应用程序因子.
解决方法
delphi – 为什么不收集TInterfacedObject垃圾的后代?
TFacilityTreeItem=class(TInterfacedobject) private m_guidItem:TGUID; m_SomeOtherNode:TTreeNode; public end;
我创建了这个对象的许多实例&我认为因为他们的参考计数,我不应该释放他们.这很方便.
但是,在检查时,我打开了ReportMemoryLeaksOnShutdown,发现它们毕竟没有被释放.
这些对象是在放置在主窗体上的框架中创建的.在主窗体的FormClose中,我清除树节点,以便释放每个对象.
发生了什么?
感谢您的帮助!
解决方法
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)的实例不能自动释放?
大卫的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.
解决方法
RegisterDragDrop
的调用将计数引用传递给TDragDrop的新实例的实例.这增加了它的参考计数器. fdragDrop:= Nil指令减少了引用计数器,但仍然存在对生存对象的引用,该对象阻止对象自行销毁.
在删除对该实例的最后一个引用之前,需要调用RevokeDragDrop(FHandle)以使引用计数器降至零.
简而言之:在析构函数中调用RevokeDragDrop为时已晚.
Interface Builder nib2objc ibtool
做iphone开发就需要接触其中的xib文件。Interface Builder(IB)是Mac OS X平台下用于设计和测试用户界面(GUI)的应用程序,可以很直观的设计图形界面。实际上Mac OS X下所有的用户界面元素都可以使用代码直接生成;但IB能够使开发者简单快捷的开发出符合Mac OS X human-interface guidelines的GUI。通常你只需要通过简单的拖拽(drag-n-drop)操作来构建GUI就可以了。
IB使用Nib文件储存GUI资源,同时适用于Cocoa和Carbon程序。在需要的时候,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中删除对象?
另外,我不能以与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中删除对象?等更多相关知识的信息可以在本站进行查询。
本文标签: