Qocoa与微软相比如何?

bas*_*ibe 30 wpf comparison cocoa qt programming-languages

我用Qt完成了几个月的开发(仅以编程方式构建GUI),现在我开始使用Cocoa了.我不得不说,我喜欢可可.使用Cocoa,很多Qt中看起来很难的东西都很容易.Obj-C似乎远不如C++复杂.

这可能只是我,所以:你觉得这个吗?

Cocoa如何与WPF(是正确的框架?)相比?
Obj-C与C#与C++相比如何?
XCode/Interface Builder如何将Visual Studio与Qt Creator进行比较?
Documentations如何比较?

例如,我发现Cocoa的Outlets/Actions比Qt的Signals and Slots更有用,因为它们实际上似乎涵盖了大多数GUI交互,而我不得不在一半时间内处理Signals/Slots.(我只是错误地使用它们吗?)
另外,XCode的标准模板给我复制/粘贴,撤消/重做,保存/打开以及许多其他东西几乎是免费的,而这些是Qt中相当复杂的任务.

如果您对这些开发环境/框架/语言中至少有两个有实际了解,请回答.

Ray*_*rns 78

多年来,我一直与Cocoa/Obj-C合作.截至2010年,我发现与WPF/NET Framework相比,它非常有限.我将列出我发现的一些差异,你可以自己判断.

标记语言

当我在WPF中设计时,我得到的标记是非常简单的XML,我可以使用我自己编写的工具轻松地手工编辑或编辑.在Cocoa中,我必须使用xib文件,这些文件不是为简单的手工编辑或操作而设计的.这是WPF标记的一个简单示例:

<DockPanel>
  <Label>Select your favorite food:</Label>
  <ComboBox
    SelectedText="{Binding FavoriteFood}"
    SelectedItemsSource="{Binding AllFoods}" />
</DockPanel>
Run Code Online (Sandbox Code Playgroud)

这是整个标记,相当于大约50行难以编辑的.xib.

查看和编辑简单XAML的能力非常有价值:

  • 直接手动编辑
  • 与同伴沟通(例如StackOverflow)
  • 来源控制
  • 搜索
  • 自动转换

布局功能

In WPF I can use panels to automatically lay out my controls as the window size changes. I can use styles to define the spacing between my controls, or I can adjust margins to get the precise look I want, or both. In either case my UI will automatically adjust to changes in font sizes, window size, and screen resolution. In Cocoa, all controls are at specific x and y locations as with WinForms and the only thing I can do is auto-resize. This is extremely limiting. For example:

  • Controls cannot wrap around to a new row or column as the window gets smaller (WrapPanel)
  • Controls cannot add/remove detail based on available space
  • Controls cannot move around to make room for a control that has more text than was originally expected
  • Controls cannot selectively shrink or enlarge to fill available space
  • Interface Builder最初设置控件以符合界面指南,但应用新样式不能更改布局.

WPF布局的优点是您可以通过向面板添加控件的方式表达您的意图,然后稍后调整精确的布局.请注意,WPF也可以采用老式的方式,但是一旦你使用面板进行布局,你将永远不会回到X/Y布局.

例如,我所做的一个应用程序包含星级和评论框的行.通常情况下,该行只是星级的高度,但是当在文本框中键入长的通信时,TextBox变得更高,这使得行更高,因此以下行向下移动.使用WPF我可以免费获得这种行为 - 使用Cocoa,我不得不手工编写代码.

数据连接

使用Cocoa/Obj-C,您几乎只限于内置数据连接,其中包括基本数据库访问和与文件的序列化.使用WPF/.NET Framework,您可以直接将UI绑定到几乎任何阳光下的任何内容,包括:

  • 关系数据库(SQL,Oracle等)
  • 对象数据库(客观性,Versant等)
  • 遗留数据库(Access,dBase,R:Base等)
  • 大型机上的COBOL数据库
  • 专有数据库格式(数百)
  • 网页
  • Web服务(SOAP,REST等)
  • XML文件
  • 平面文件(逗号分隔,制表符分隔,固定宽度)
  • Office文档(Word,Excel等)
  • OpenOffice文档
  • PDF表单字段
  • GPS接收器数据(当前位置)
  • 物理开关,按钮,控制杆,旋钮,滑块等的位置
  • 时间(本地或网络)
  • 性能计数器(CPU利用率等)
  • 相机(摄像机,网络摄像头,静止图像相机等)
  • Analog electronic inputs
  • MIDI (musical instrument keyboards, pickups, etc)
  • OBD-II (vehicle monitoring)
  • LDAP and Active Directory (user account information)
  • WBEM and SNMP (network device status and configuration)

In fact, you can bind to practically anything that has had a driver written in any NET Framework language - and there are over a hundred NET Framework languages.

Repetitive code

In Cocoa your model consists of a .h and a .m file, your controller consists of a .h and a .m file, and your view consists of a .xib file. Every single field in every object in your model must be referenced every one of these places!

In WPF/NET, a single field generally only appears in two lines of code: Once where the model is defined, and once where it is presented by the view. For example, in my code I usually define simple model fields in XML:

<Property Name="City" Type="string" />
Run Code Online (Sandbox Code Playgroud)

then to create a text box to edit the city I simply drag the "City" property into my view and end up with this XAML:

<TextBox Text="{Binding City}" />
Run Code Online (Sandbox Code Playgroud)

So "City" is mentioned in only two lines of code in my entire application (unless I have another "City" text box elsewhere). In Cocoa "City" will be referenced at least five times.

Binding directly to the model

In Cocoa a single controller is really only suitable for a single view: If you create a new view for the same model you need a new controller. In WPF/NET there is a better way to do it, though you can still create controllers if you really want to.

In WPF/NET a view will typically bind most of its controls directly to the model (see my City example above). Other controls will be bound to a "View Model" that models the state information associated with the current view. For example, if you are searching the "View Model" would contain the search string so it can be used by the view both to filter the results and to hilight the search text.

In WPF/NET you can also bind multiple properties of a control to the same or different parts of your model (or view model):

<TextBox Text="{Binding AmountToTransfer}"
         Background="{edf:Binding UserIsHappy ? Green : White}" />
Run Code Online (Sandbox Code Playgroud)

The difference is that in WPF a view model is usually shareable between several screens that are similar in their behavior, so in a LOB application when you create a custom view all you need to do is edit a single file.

Command architecture

In Cocoa a button stores its target and action in a NSActionCell within the view, which means that it will invoke a specific method on a specific object (typically the controller). In WPF/NET a button has a Click event that works the same way, but it also has a Command property that allows you to invoke a command.

Commands in WPF are very powerful, since a single Command may be shared throughout the application. For example, WPF itself defines a Delete command. As long as your model responds to this command, adding a "Delete" button to your view is as simple as selecting the Delete command in the properties window, which creates this XAML:

<Button Command="Delete" />
Run Code Online (Sandbox Code Playgroud)

This is all you have to do to get a functional delete button that deletes the object from a list. Note the built-in Delete command also:

  • Has a key binding to the Delete key on the keyboard
  • Supplies language-appropriate text ("Delete" or "Eliminar" or "Löschen" or "Supprimer" or ...)
  • Includes a descriptive tool tip

A command is routed to ancestor objects and models, so in a typical application you almost never need to specify which object receives the command.

Style sheets

In Cocoa there is no mechanism to apply style sheets to panels and have them affect all the controls in the panel, either at design time or at run time. For example an application may want to:

  • Make all the TextBoxes in a given area read-only
  • Make all labels bold
  • Give all ComboBoxes a light green background
  • Add uniform spacing between a set of buttons
  • Use a large green checkmark for a set of checkboxes
  • Add a Delete button to all lists
  • Make all Delete buttons appear as a red "brushed" X instead of as a traditional button
  • Make the same settings on several separate items

WPF/NET makes all of these operations trivial through the use of styles. You can set any property of any object through a style. Styles can be set implicitly by object type or explicitly, for example:

<Button Style="{StaticResource DeleteButtonStyle}" />
Run Code Online (Sandbox Code Playgroud)

Style sheets can be defined anywhere you like: in a control libraries, at the application level, specific to a "theme", on a window, in a specific control's resource dicitionary, or directly on a control.

Control templates

In Cocoa you cannot do much to change the visual styling of controls except to subclass them, since they each draw their own appearance. In WPF/NET the appearance of a control is given by its template which can be freely replaced with pretty much anything you can think of.

For example:

  • You can use a ListBox in your drop-down menus and style it to look like regular menu items (with a checkbox beside the currently-selected item)
  • You can change a TreeView to appear as a sequence of ListBoxes instead of a tree
  • You can change a slider's "thumb" to appear as a business symbol or cartoon character depending on your target audience (slide a light bulb or Mickey Mouse back and forth)
  • You can change a slider to appear as a knob or to follow a non-linear path
  • You can change a CheckBox to appear as a click on/click off button, a lock icon that opens and closes, or a door that opens and shuts

Control templates and data templates may also include built-in animations, so for example your door can actually animate swinging open and closed when you click on it. This is trivially simple to do in Expression Blend: It takes about 20 clicks of the mouse. Just create two linear animations and attach them to event triggers.

Custom controls

Cocoa and WPF both allow you to subclass existing controls to create new ones. In Cocoa the new controls are serialized to the .xib/.nib file. In WPF they are part of the XAML just like the built-in controls:

<StackPanel>
  <TextBlock>
    Hello, <Run Text="{Binding FirstName}" />.
    <Bold>Good morning!</Bold>  How are you today?
  </TextBlock>
  <my:JoySelector Happiness="{Binding Happiness}" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

In this example JoySelector would be a control I defined and Happiness would be one of its properties.

A big difference between Cocoa and WPF is in the drawing of the custom controls. In Cocoa you must code calls to drawing primitives to create your control's appearance. While this is an option in WPF, it is usually much more easily done using a control template.

For example, in Cocoa you might write:

CGSize size = CGSizeMake(30, 20);
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 1.0, 1.0, 0.0, 0.0);
CGContextFillEllipseInRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
Run Code Online (Sandbox Code Playgroud)

whereas in WPF using XAML the equivalent would be:

<Ellipse Width="30" Height="20" Fill="Red" />
Run Code Online (Sandbox Code Playgroud)

or in WPF in code (C#):

return new Ellipse { Width=30, Height=30, Fill=Brushes.Red };
Run Code Online (Sandbox Code Playgroud)

A ControlTemplate may of course have multiple items:

<ControlTemplate TargetType="my:JoySelector">
  <Grid Width="50" Height="50">
    <Ellipse Width="30" Height="20" Fill="Red" VerticalAlignment="Left" />
    <Path Data="M0,0 L3,5 L8,8 L5,3 L0,0" Fill="Blue" />
    <ComboBox
      SelectedItem="{TemplateBinding Happiness}"
      Style="{StaticResource JoySelectorBoxStyle}" />
  </Grid>
</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)

This XAML would typically be created in Expression Blend by right-clicking a JoySelector, selecting Edit > Template > Create New, drawing the Ellipse, Path, and ComboBox using the drawing tools, and selecting the ComboBox binding and style from the Properties window.

Data templates

In Cocoa if you want a list or tree of items of various types, such as an equipment inventory in a game or a list of various types of accounts (investment, money market, savings), you pretty much have to code it all yourself. In WPF/NET you can use DataTemplates.

For example, if every weapon has a "hit strength" and a "defense strength" you might include a data template like this:

<DataTemplate TargetType="game:Weapon">
  <DockPanel TextElement.FontWeight="Bold">
    <Image Source="{StaticResource WeaponDrawing}" />
    <TextBlock Text="{Binding WeaponName}" DockPanel.Dock="Top" />
    <TextBlock Text="{Binding HitStrength}" Foreground="Red" />
    <TextBlock Text="{Binidng DefenseStrength}" Foreground="Blue" />
  </DockPanel>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

Other game objects would use different templates, then the inventory could be displayed using a ListBox using a WrapPanel to lay them out in reading order. (Note that in WPF, a ListBox doesn't have to present its items in a vertical list: Any panel can be used.)

This same technique is important in LOB applications: For example, you can have a default representation for an Invoice that is set in an application-wide DataTemplate, so any part of your application that presents lists of Invoices will automatically display them in the default format. This might include an icon, the invoice number, a tooltip popup with additional information, and a context menu that allows the invoice to be opened and/or edited.

Triggers and animations

In Cocoa you can do animations, but must write code both to create the animation and to apply the animation. In WPF you can define the animation using a timeline in Expression Blend, and set EventTriggers and PropertyTriggers in the view to control when it runs. To create an animation that shakes a button, just right-click to create a timeline, set the button's position, rotation or scale using the mouse at a few points on the time line, and change the automatically-created EventTrigger to the event you want to trigger the button.

Cocoa has no animation property store or coercion mechanism, so any changes made by the animation are permanent: You can't remove the animation and have the property values revert. Also you cannot animate properties of shared resources (such as brush colors) without manually copying them, and you can't animate to out-of-range values and have the control itself coerce to the appropriate value. In WPF the animation system has the ability to keep track of animation values, bound values, default values and coerced values separately so you don't run into these problems.

In WPF you can set animations to run on UI events like button clicks, property state changes (including data changes in the model), events generated by the model, to run continuously, or via code.

In WPF you can create custom animation classes and use these with Expression Blend as if they were part of WPF. You can also draw the Geometry objects used by the built-in PathAnimation rather than coding it yourself.

Note that WPF has the ability to construct and start animations in code if you really want to. Also note that embedding an animation from a separate application such as Quartz Composer, is not the same thing as animating properties of UI objects. Both Cocoa and WPF can embed animations created with other technologies but with WPF you can use Expression Blend to create a timeline that animates any part of your UI.

Conversions as part of binding

Cocoa has the ability to do conversions to and from from a single value using a NSFormatter. Anything more complicated must be done in the controller. In WPF you can use a StringFormat for the simple cases Cocoa's built-in NSFormatters cover, but you can also specify an IValueConverter or IMultiValueConverter to implement custom conversion of values. For example, you can add a custom converter to a bar chart data series to cause the data items in the bar chart to animate to their target values in rapid sequence (known as a "jelly" animation). WPF's converters can be used one-way or two-way and can convert a single value or multiple values.

Conversions also allow you to bind to multiple properties or calculations and to format the result, for example:

<TextBlock Text="{edf:Binding (Height + Width)/2, StringFormat=0.000}" />
Run Code Online (Sandbox Code Playgroud)

This sort of binding with conversion is not possible in Cocoa.

Third party controls

In Cocoa you can generally only include UI widgets designed for Cocoa in your application. In WPF you can include WPF controls but you can also include sections of your UI developed using WinForms, MFC, HTML, Java, Flash, and other technologies. WPF provides facilities for integrating these other technologies directly into WPF, even to the extent of using its markup system to construct the objects and set their properties, for example:

<StackPanel>
  <TextBlock>Here is a WinForms control:</TextBlock>
  <WindowsFormsHost>
    <tools:LegacyChartingControl
      Width="20" Height="30"
      Title="Graph of something"
      SeriesXMin="0"
      SeriesXMax="10" ... />
  </WindowsFormsHost>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

Externally-created media

Both Cocoa and WPF can include media such as videos, animations, and bitmaps that have been created in third-party tools. Each environment supports all such media types supported by the underlying operating system. WPF provides a bit more than Cocoa in terms of controlling the media, for example you if you set a button's command to "MediaCommands.NextTrack" or "MediaCommands.FastForward", the media will automatically respond appropriately. Also, WPF provides some improvements in the asynchronous loading of media.

WPF (through Silverlight) also supports several high quality video and audio codecs in a fully cross-platform manner so you can rely on your media working on any platform.

There are also tools that allow you to convert drawings created in tools like Illustrator or animations created in tools like Flash into native WPF drawings and animations, allowing you to manipulate and data-bind their properties. For example, you could take a bouncing ball animation created in Flash and data-bind its Y coordinate at apogee so that the ball bounces higher or lower based on the data value in your model.

Garbage collection

As of 2007 garbage collection is finally supported in Cocoa/Obj-C, but many libraries still can't handle it so most of the Cocoa code being written today is still using manual memory allocation with reference counting. Thus even today you still a lot of "[abc release]" sprinkled throughout Cocoa code! WPF/NET has had garbage collection from day one, so it does not have this problem.

Execution within web browser

Cocoa applications are currently limited to executing as desktop applications, whereas WPF can run just as easily within the web browser as on the desktop, using either XBAP or Silverlight technology.

Cross-platform capability

The story here is similar:

  • Cocoa applications run natively on Mac OS X, and can also run on Windows and Linux by using Cocotron or GNUstep and restricting yourself to a subset of the features.

  • WPF applications run natively on Windows, and can also run on Mac OS X and Linux by using Silverlight and restricting yourself to a subset of the features.

The only significant difference is that Silverlight can run in the browser and has much better vendor support and tooling than Cocotron or GNUstep.

Other advanced capabilities of WPF

So far I have not found any capability in Cocoa that is not also in WPF/NET, but I have found many in WPF/NET that are not in Cocoa, for example:

  • All controls such as buttons, textboxes, comboboxes, etc can operate just as well within 3D scenes as within 2D layouts. They can also be arbitrarily stretched, rotated, skewed, etc.
  • Advanced drawing capabilities such as PolyBeziers, combined geometries, RenderTransform vs LayoutTransform, alpha transparency control, etc
  • Advanced brushes such as gradient brushes, tiled image brushes, and "Visual brushes" which allow you to create an arbitrarily complex brush for painting, for example you can paint a reflection of your window including all its controls.
  • Animation subsystem allows practically every property to be animated, for example I animated a TextBox's "Text" property to make it appear that text was being typed in

Third party algorithms and drivers

Cocoa/Obj-C can call pre-compiled libraries that use C calling conventions and call invoke methods on objects defined in certain other languages. This means that a C-style API is generally required for third-party code that needs to be integrated into your application. WPF/NET can include code written in over 100 languages directly into your application and allows you to access all functionality directly. In addition, it can also call into precompiled code written in other languages using C, C++, COM, DCOM, Web Services, and other calling conventions. In addition, there are open-source shims allowing NET Framework code to call directly into a wide variety of other languages and systems. This means that WPF applications almost never have to include more than a tiny amount of glue code to connect to third party code, including device drivers.

Language comparison

Comparing Objective-C with C# is a major task, and one I will not attempt. Suffice it to say that as of version 4.0, C# contains all the features on Objective-C and many, many, many more. I learned Objective-C in 1989 - a long time before C# was even conceived of - and at the time it was an amazingly powerful language. Now when I use it I cringe, especially at the loss of LINQ and Generics.

Try this sort of data transformation in Objective-C:

DataContext =
  from lesson in AllLessons
  where lesson.Active
  groupby lesson.Category into category
  select new
  {
    categoryName = category.Key.Name,
    lessonsInCategory =
      from lesson in category
      select new
      {
        lesson,
        fullName = lesson.ShortName + " " + lesson.Suffix,
        priority = rand.Next(10)
      }
  };
Run Code Online (Sandbox Code Playgroud)

If AllLessons is provided dynamically, you can directly bind this result in WPF (with <ListBox ItemsSource="{Binding}" />) and have it dynamically update in real time.

When using LINQ with C# you can also do joins, sorting, etc. There is no back-end code to write at all, and Visual Studio's IntelliSense helps you complete the names of properties, etc as you edit and even underlines your mistakes.

I don't know of any good comparison between Objective-C and C#, but there is a good comparison between C# and Java on wikipedia that calls out many of C#'s features that are also missing from Objective-C.

Language bindings

Cocoa is not restricted to Objective-C, and WPF is not restricted to C#. Both are accessible from a number of other languages. The difference

  • 我发现你对WPF的评论非常有见地,因为我的背景主要是web开发,而且我确实有一些Cocoa经验.然而,即使我的经验水平相对较低,你提到很多关于Cocoa的事情都是非常错误的.例如,您提到使用5行代码从视图中访问属性.使用适当的Cocoa绑定,我可能只需要相同的两行代码(可能是3行).声明.h文件中的属性,在.m中合成它,然后将其绑定到Interface Builder中的NSObjectController. (14认同)
  • 但有一点让我感到惊讶:在很多情况下,Cocoa/Interface Builder限制了观察Apple人机界面指南中规则的原因.例如,在HIG中完全不鼓励使用自定义样式和自定义控件,因此很难在Cocoa中实现(允许自定义视图).这可能是OSX看起来比Windows更加一致的原因.尽管如此,就框架的功能而言,这当然是一个缺点. (6认同)
  • 附加说明:虽然比WPF更有限,但Cocoa并不像你在布局上所说的那样有限; Cocoa/Obj-C包括CoreData,它可以根据需要连接到关系SQL数据库; Cocoa不需要在三个地方引用每个对象中的每个字段,公共属性需要.h和.m但私有属性只能在.m中引用 - 公共属性可以被引用但是永远不会在一个.xib; Cocoa的键值编码机制可以在一定程度上进行转换,但是忽略了Obj-C中鸭子打字是一个基本特征; ... (5认同)
  • ...... ARC是垃圾收集的答案; 除了通过落后于真实版本的第三方工作之外,Silverlight不适用于Linux; 您列出的所有"WPF的其他高级功能"都可以在Cocoa上通过CoreAnimation(用于2d和3d变换)和Quartz(用于PDF等效绘图功能)获得; Obj-C可以链接并调用GCC或LLVM支持的任何语言. (5认同)
  • 哇!非常感谢!这太棒了!只需两个注意事项:(1)Cocoa中的布局可以轻松设置为使用窗口或框进行自动调整.(2)转换可以使用NSFormatter的子类包含在Cocoa中. (3认同)