Tag: 可可

与NSCollectionViewItem纠缠

如果我此时尝试运行该项目,将显示错误。 我最终进行了搜索,很多人以前都遇到过这个问题。 自2014年以来,它发生在大型API更新之前。 到目前为止,没有解决方案,只能删除它。 覆盖内容大小并不容易 我来自iOS开发背景,并且一直在使用UICollectionView。 一个常见的技巧是更改contentSize,以便获得更大的可滚动区域。 将偏移量设置为特定区域以进行显示很有用。 与UICollectionView不同,NSCollectionView中没有’contentSize’属性。 相反,可以使用NSCollectionViewLayout中的属性“ collectionViewContentSize”来更改contentSize。 这也存在于iOS的对应版本中。 这也意味着,该使用2015年更新中可用的新API了。 然后,假设我更喜欢流布局,我将创建NSCollectionViewFlowLayout的子类。 我现在可以覆盖该属性以允许更大的内容大小。 在替换布局时,我还将在代码中设置项目大小。 harryworld / NSCollectionViewItem 通过在GitHub上创建一个帐户为NSCollectionViewItem开发做出贡献。 github.com 创建项目的占位符可能会导致问题 每个项目都有一个大小。 有时,我不想使用数据源制作商品,而是想将其创建为占位符。 这是根据项目的内容执行一些尺寸计算的。 如果仅创建项目,则不会链接其中的UI组件。 通常,我们从对象连接那些组件。 当NSCollectionView制作项目时,它将正确链接它们。 但是,如果我使用构造函数初始化该项目,则这些组件不会连接。 有时,我什至会收到“视图未加载”的错误。 解决方案分为两部分。 第1部分:为了确保NSView在创建时可用,您应该将视图同时连接到文件的所有者和对象。 在这种情况下,我们将依靠文件的所有者连接来初始化视图。 第2部分:对于其他UI组件,它们充当Interface Builder中的子视图。 我们需要手动连接它们。 只需循环浏览所有子视图,并将它们与预定义的标识符进行匹配。 harryworld / NSCollectionViewItem 通过在GitHub上创建一个帐户为NSCollectionViewItem开发做出贡献。 github.com 我已经创建了解决所有这些问题的示例项目,您可以在此处找到源代码。

设置一个Xcode项目以开发可共享通用代码的Cocoa和Cocoa Touch框架,并为MacOS和iOS应用程序提供可重用和可重新分发的UI和非UI组件

缺少这样的教程,或者至少当我第一次尝试执行标题(尽可能长,但尽可能短)时,自己还没有找到。 我来到了来自C#编程的Apple开发生态系统,只是试图通过新的(很有希望的)macOS和iOS目标扩展我公司已经为Windows和Web开发提供的产品集(主要是组件库)。 由于我必须通过尝试和重试来学习所有内容,而且这并不容易(至少不应该像恕我直言,这本来应该如此简单),所以我认为写下已建立的步骤并没有什么害处(随后一些屏幕截图),也许他们也可以帮助其他人-谁知道? – 在将来。 因此,让我们开始吧。 一个项目,多个目标,没有显式工作区 我了解到的第一件事是(与.NET世界中Visual Studio解决方案通常将更多项目分组的情况不同),我不需要Xcode工作区来对多个项目进行分组。 仅仅是因为我不需要多个项目。 因为单个Xcode项目可以定义多个目标,所以每个目标都有其自己的类型和目标,并且每个目标都具有针对特定平台(例如macOS或iOS)构建的二进制文件。 (但是,顺便说一下,无论何时创建项目,无论如何都会为其创建内部工作区。) 在我的研究期间,我也没有发现对通用的跨平台层的真正技术需求(尽管我曾经习惯于在.NET中开发共享的跨平台类库。)仅仅是因为Xcode中的每个源代码文件项目可以是其一个或多个目标的一部分,而无需任何源代码重复,并且目标可以根据需要完全自定义。 因此,让我们在Xcode中创建我们的第一个项目。 我们可能会尝试从一个更具体的项目类型开始,但是我发现如果首先选择一个Empty模板(从“跨平台”选项卡下;为什么从那里选择)最简单,那是因为我们肯定会为多个平台)。 因为目标(和生成的产品)必须具有唯一的名称,所以我不得不将其中一个作为主要(我选择了macOS),将另一个作为iOS(辅助)。 对于后者的名字,我刚刚附加了“ Touch”来区分它(这个想法来自您可能已经猜到的苹果公司Cocoa和Cocoa Touch框架的名字。) 分组源代码文件 下一个挑战是找到一种在项目中考虑或不考虑其指定目标的好方法,将源代码文件分组。 我最终选择使用简单分组,并为每组源代码文件生成一个文件夹。 (Xcode确实支持不带文件夹的项目内分组,某种程度上类似于Visual Studio解决方案文件夹,但至少在我开始使用的版本9中,此功能存在一个丑陋的错误-拖动非文件夹分组的项目有时会崩溃。 ) 最终,考虑到它包含的源代码的功能区域,以及一个组包含的代码对于我的项目目标(macOS和iOS)是公共的还是特定于一个的,我决定进行多级分组。 请注意,默认情况下,为每个目标Xcode创建了一个组(和一个文件夹),我还希望将该分隔保留为我的主层次结构分组。 但是,这再次要求一个目标(我选择了macOS)成为主文件夹,并同时包含特定的和通用的源代码文件,而另一个目标(iOS目标)获得了仅保留特定源代码文件的辅助文件夹。 如果您想将其复制粘贴到您的Xcode中,这是实际的源代码: 不过,我在使用示例应用程序时发现的一个重要方面是,我们不应该尝试通过将它们移动到项目结构下的公共文件夹(在那里成为子文件夹)来对应用程序进行分组,因为它似乎有些Xcode应用程序设置不要在此过程中进行更新,并且会在构建时生成特定的警告。 但是,最终我能做的是解决这个问题,即创建一个不带名为“ Samples”的文件夹的组,然后将所有示例应用程序文件夹拖到该文件夹​​中,并将它们全部放在项目结构中的单个可折叠树节点下。 (重要的是文件路径保持不变。) 部署产品 对于每个目标,Xcode都会生成一个框架文件,其中包含为该目标构建的二进制文件和一些元数据,消费者可以使用这些元数据来访问您的组件。 您可以在项目结构中为您生成的Products文件夹中看到框架文件,并且可以通过Finder的上下文菜单在Finder中打开每个文件的位置。 然后,您可以从Finder复制框架文件并将其托管在任意位置,例如可以从Web服务器下载的文件,也可以通过您管理的任何分发渠道发布该文件。 发布配置 您可能已经看到输出框架是使用Debug配置构建的,并且您可能希望在实际部署它们之前切换到Release。 要改为选择发布配置,只需从Xcode的顶部菜单中单击目标组合框,然后单击“编辑方案”。 然后,对于“运行”选择,将“构建配置”从“调试”更改为“发行”,关闭对话框,然后重新构建目标。 体系结构:iOS模拟器不是ARM! 但是你不流行。 您最终会注意到,即使您使用Release配置构建了iOS框架(以Touch后缀命名),也无法在所有架构上正常运行。 例如,如果您使用真实设备(或具有ARM体系结构的通用设备)构建框架,则输出框架将不适用于以模拟器为目标(使用x86体系结构)的iOS应用。 反之亦然。 因此,您还需要定义一个聚合目标,以便能够运行脚本以将为不同体系结构构建的框架“合并”为一个聚合的“胖”对象。 为此,请在新目标对话框的“跨平台”选项卡中创建一个类型为Aggregate的新目标,为其命名,如“ FramisTouch-aggregate”,并为其添加一个新的运行脚本阶段(使用“ +”按钮目标的“构建阶段”部分),并定义一些命令来执行所需的操作: 然后,可以通过构建聚合目标(很重要:之后)轻松地执行上述命令:通过从目标中选择通用iOS设备和模拟器,您已经在Xcode中构建了设备和模拟器框架(即针对两种类型的体系结构)组合框,然后重复构建输出。 您当然想知道这些命令实际上会做什么: 创建一个新目录(例如“ Release-iphoneaggregated”)作为目标(在项目的构建目录中); 将基于设备的框架的结构复制到新目录中; […]

Swift 2.2中的面向对象设计原理– Christian Tietze –中

要真正掌握设计模式(如MVVM)和架构模式(如VIPER)的使用,了解Bob叔叔的面向对象设计原理(产生了SOLID原理)非常重要。 就像制作适当的面向对象软件的语法一样。 现在这是个好消息:这里有一个Swift游乐场(和Markdown文件可在线阅读),其中阐明了Bob叔叔的所有原则: Swift 2.2中的OOD原则 检查一下,做笔记,并让原则贴近您的内心。 他们有一天可以挽救您的生命。 通过Christian Tietze的工作日志 http://ift.tt/1U9tOay

直到您可以取消排队的GCD块– Christian Tietze –中

今天,我了解到您可以使用新的dispatch_block_cancel(从OS X 10.10 / iOS 8.0开始提供)取消延迟的dispatch_block_t。 感谢Matt的帖子—这是一个Swift示例: 让工作= dispatch_block_create(0){print(“ Hello!”)} #10s后执行 让delayTime = dispatch_time(DISPATCH_TIME_NOW,Int64(10 * Double(NSEC_PER_SEC))) dispatch_after(delayTime,dispatch_get_main_queue(),工作) dispatch_block_cancel(工作) #永远不会打印“你好!” 注意:如果正在执行该块,取消将不起作用。 如果我知道此API存在,那么我可能不会在Move!中使用下面非常麻烦的方法。 可取消延迟块的超古旧版本 出于历史目的,这是可取消调度块的改编,您可能会在互联网上找到我曾经为Swift改编的代码: typealias CancelableDispatchBlock =(取消:Bool)->虚空 func dispatch(cancelableBlock块:dispatch_block_t,atDate日期:NSDate)-> CancelableDispatchBlock? { //对同一块句柄使用两个指针 //块引用本身。 var cancelableBlock:CancelableDispatchBlock? =无 让delayBlock:CancelableDispatchBlock = {在 如果!cancel { dispatch_async(dispatch_get_main_queue(),阻止) } cancelableBlock =无 } cancelableBlock = delayBlock 让间隔= Int64(date.timeIntervalSinceNow) 让延迟=间隔* Int64(NSEC_PER_SEC) dispatch_after(dispatch_walltime(nil,delay),dispatch_get_main_queue()){ 守卫let cancelableBlock […]

具有Cocoa键值观察器的简单iOS MVVM

为什么使用MVVM 与使用MVC相比,使用MVVM体系结构构建iOS应用程序具有许多优势。 优势之一是通过将模型和视图分离到单独的MVVM对象来减少Massive View Controller问题,View Controller的职责是仅在ViewModel中 观察与视图相关的值,然后在值更改时更新视图。 这导致View Controller与模型之间的耦合较少 。 单元测试变得更加容易,因为我们可以将ViewModel与View Controller分开进行测试。 iOS应用中MVVM的当前状态 许多使用MVVM架构构建的iOS应用程序都使用第三方库(例如RxSwift和RxCocoa)来观察视图模型对视图控制器的更改。 RxSwift是一个非常强大的库,我们可以将其转换观察器与组合,合并,zip和许多其他强大的转换一起使用。 尽管RxSwift功能非常强大,但有时我们只想使用本机Cocoa Foundation框架构建没有第三方依赖性的简单小型应用程序。 使用不依赖第三方的MVVM Apple Foundation Framework提供了任何可用于在iOS体系结构中构建MVVM应用程序的内置解决方案吗? 是的,答案是Cocoa Key Value Observing 。 KVO是观察者模式 ,可用于观察以NSObject作为其超类的对象中的属性更改的值。 可可KVO是一种非常强大的机制,可用于在iOS中构建基于MVVM的体系结构。 缺点是语法使用起来非常冗长,我们必须手动保留和删除观察者, RxSwift提供了addToDisposeBag方法,该方法可用于自动删除观察者 。 实施KVO以构建基于iOS MVVM的应用 这是示例iOS应用程序,当用户在TextField中键入内容时,该应用程序实现了KVO以构建简单的电子邮件验证。 该应用程序分为3个主要组成部分: ViewController是一个UITableViewController ,它显示UITextField来输入电子邮件,而UILabel来显示电子邮件是否有效。 EmailModel是一个普通的Swift类 ,用于存储电子邮件的字符串和表示电子邮件是否有效的布尔值。 EmailViewModel是一个Cocoa NSObject超类,它提供了将显示电子邮件文本以及它是否为有效电子邮件格式的属性。 电子邮件模型 EmailModel存储电子邮件的值文本和表示电子邮件是否有效的isValid布尔值。 值更改时使用Swift属性观察器,使用包含有具有新值的userInfo的NotificationCenter来发布带有EmailModel.TextDidChange的Notification ,它还通过调用validateEmail来 设置isValid的值 ,并将电子邮件文本的newValue传递为使用RegEx表达式评估。 isValid布尔值中的更改也通过NotificationCenter发布。 EmailViewModel EmailViewModel是基于NSObject超类的MVVM , 该类接受EmailModel作为其构造函数。 它提供了使用objc动态关键字的 emailTextValue和isValidValue, […]

始终注意技术建议的含义

这个周末,我浏览了Medium,发现了一篇有关“从模型到控制器传递数据的3种方式”的文章。 评论表明人们喜欢它,因为它谈到了重要的基础知识:如何传递信息? 这可能是有史以来最重要的面向对象编程问题。 您如何耦合组件? 提到的3种方式是: 回调, 代表团, 和通知。 实际上,这是耦合任何组件的3种不同方式。 了解这些技巧(以及其他技巧)对编写代码非常重要。 然后我想到这篇文章可能会误导新的Swift开发人员,因为这些示例几乎没有显示如何创建一个好的模型。 采取示例代码进行委派: 类DataModel { 弱var委托:DataModelDelegate? func requestData(){ //接收到数据并将其解析为String 让数据=“来自任何地方的数据” 委托?.didRecieveDataUpdate(数据:数据) } } 这是一个基于委托的回调的网络请求。 当然,它说明了代表团。 但这是网络控制器代码。 这不是模型代码。 您在这里看到任何代表实体的东西吗? 实际上,您将发现的唯一具有模型风格的东西是数据。 模型对象是本质上是某种东西的对象。 上面看到的是仅封装序列的服务对象。 除了委托属性,它是无状态的。 它本身几乎不是应用程序状态的一部分。 在简单的情况下,从模型代码中提取网络请求代码可能没有回报。 但这不会扩展。 而且,如果您将此示例视为起义的iOS或Mac开发人员的第一件事,那么您将产生误导。 假设您的代码已经具有模型对象,并且您想应用上面概述的委托技术。 因此,您采用了这个简单的代码段,您可以将其粘贴到其中而没有任何冲突,然后就可以完成了。 成功的申请似乎足以证明。 但是现在您的代码变得更糟了。 因为您的模型对象现在也是网络请求网关。 它做了两个非常重要但又非常不同的事情。 也许危害仅会在几个月后显现出来,并且,如果您一开始就全力以赴地使自己陷入这种情况,那么您可能不知道问题的根源,并且将无法自己修复。 当您阅读以代码为中心的“ X最好的Y方式”时,请弄清楚作者正在(不知不觉中)向您出售什么样的世界观或术语。 只有相距甚远,您才能获得建议,而不会盲目地改变自己的想法。 如果您找不到作者为什么如此做的令人信服的理由,也许她只是做事草率而已,并不在乎。 您必须对所学内容的质量负责。 作者无法从Genesis入手,也无法解释整个人类历史如何在这种超级编码技巧中达到顶峰。 在写作时,您必须将某些事情视为理所当然。 问题是:如果您(读者)没有自己的见解,那么您首先看到的东西对您的影响最大。 如果遗漏的东西是您工艺的重要概念,那么很难知道发生了什么。 您不能收集一些代码片段,除非收集一些作者关于如何正确执行操作的观点。 如果您的收藏夹中的各个部分发生冲突,而您没有注意到它或不明白为什么,那么将很难编写具有凝聚力的代码并应用任何这些技巧。 因为最终,没有任何事情是孤立的。 您(人类)始终是过程的一部分,您的困惑将在代码中体现出来。 […]

在MKMapView上绘图

我在MKMapView上绘制折线和多边形的笔记 首先,将“地图视图”拖动到“视图控制器”并添加约束。 将此地图视图拖动到视图控制器以创建@IBOutlet。 切记要使View Controller符合MKMapViewDelegate并将委托函数添加到View Controller中,如下所示: 您可以根据自己的喜好设置颜色。 现在开始绘制。 在视图控制器中添加一个保存坐标的属性 变量点= [CLLocationCoordinate2D]() 在本教程中,将isUserInteractionEnabled设置为false,以便不会拖动地图。 @IBOutlet弱var mapView:MKMapView! 覆盖func viewDidLoad(){ super.viewDidLoad() mapView.isUserInteractionEnabled = false } 现在我们需要重写touchesBegan函数: 覆盖func touchesBegan(_ touches:Set ,事件:UIEvent?){ mapView.removeOverlays(mapView.overlays) 如果让touch = touches.first { 让坐标= mapView.convert(touch.location(in:mapView),toCoordinateFrom:mapView) points.append(坐标) } } 上面的代码在“地图视图”上检测触摸位置并进行隐式协调。 然后,将该坐标添加到点数组。 覆盖函数touchesMoved获取路径上的每个点: 覆盖func touchesMoved(_ touches:Set ,事件:UIEvent?){ 如果让touch = touches.first { 让坐标= mapView.convert(touch.location(in:mapView),toCoordinateFrom:mapView) points.append(坐标) 让折线= MKPolyline(坐标:点,计数:points.count) mapView.add(折线) } 最后,用MKPolygon完成绘图以突出显示选择区域。 […]

Xamarin.Mac和netstandard2

随着.NET Core 2.0的发布,今天是.NET社区激动人心的一天: 宣布.NET Core 2.0 NET Core 2.0现已作为最终版本提供。 您可以在… blogs.msdn.microsoft.com中从命令行开始使用它进行开发。 但是,如果您尝试将新的闪亮的netstandard2库与Xamarin.Mac(或iOS)一起使用,则可能会遇到一些问题,因为计划对我们的下一个主要版本d15-4(XM 3.8和XI 10.14)提供官方支持。 现在,通过安装正确的位并对csproj进行较小的调整,即可解决所有这些问题。 第一:安装在稳定频道中找到的最新d15–3版本 第二:安装.NET Core 2(您需要pkg下载) 第三:由于此错误,您需要调整Xamarin.Mac(或iOS)csproj,直到它得到修复。 将此行添加到您的参考部分: 下面 (或对于iOS,为) 但在同一个ItemGroup中。 当且仅当您针对Xamairn.Mac Full目标框架,您将需要另外添加以下行: v4.6.1 在顶部的PropertyGroup中(例如,在UseXamMacFullFramework之上)。 经过这些调整后,事情应该“正常”。 正如我提到的那样,全面支持将在下一个主要版本中进行,因此请提交遇到的所有错误。

CAPluginLayer和CABackdropLayer

最初发表在我的(新的)杂物房中。 私有标头中隐藏着很多很酷的CoreAnimation好吃的东西,但是确实吸引了我的三个私有CALayer类: CAProxyLayer , CALayerHost , CABackdropLayer和CAPluginLayer 。 CALayerHost设计与CARemoteLayerClient/Server相似,因此我将在以后的文章中介绍这两个类。 我对CAProxyLayer了一些实验,因为它用于视觉效果(想想NS/UIVisualEffectView ),或者我不知道正确的常量或没有正确使用它,但是我无法使它可靠地工作而没有麻烦windowserver 。 我将使用代码示例来讨论其余两个。 这个名字很怪异,但是看起来它是为支持windowserver插件而设计的-甚至还有一个vtable,但是到目前为止,仅支持com.apple.WindowServer.CGSWindow 。 这是一个代码示例: let layer = CAPluginLayer() layer.frame = CGRect(x: 50, y: 50, width: 200, height: 200) layer.pluginType = “com.apple.WindowServer.CGSWindow” layer.pluginId = UInt64(self.window.windowNumber) layer.pluginGravity = kCAGravityResizeAspect //layer.pluginFlags = 0x4 // display without a shadow 因此,最大的CAPluginLayer是,现在您只能使用CAPluginLayer实时镜像窗口(其所有UI更改和交互都反映在图层内容中)。 您可以像设置pluginGravity一样设置pluginGravity ,并且唯一已知的pluginFlags值为0x4 ,Dock使用pluginFlags值来显示没有阴影的窗口。 pluginId实际上是指windowNumber (或_realWindowNumber具体取决于您的窗口类型,但这通常不必担心),并且实际上可以是*屏幕上可用的任何窗口! 没错–您可以镜像任何窗口,而不仅仅是自己应用程序的窗口。 为了娱乐,我使用CGWindowListCopyWindowInfo来获取最前面的窗口(不是我自己的应用程序),并使用该ID将其镜像到我的应用程序层中。 […]

Project6.2的借调

今天是Project6的第二天,事情开始融合在一起。 在使用NSplitView和Autolayout解决了将近3个小时之后,我终于找到了一个可行的解决方案,并且拥有Twain的裸露功能版本。 甚至更好的是,我们有基本的操作转换代码存储到Realm并编译以记录内容。 到目前为止,它在构造和解构所记录的笔记时效果很好。 还剩什么? 搜索,智能标记(将URL转换为卡片,嵌入图像,样式功能)和一些UI修饰。 注释标题尚未实时更新,并且updateAt时间戳未在父注释模型上同步。 仍然工作了2天,看到一个半可用的原型还是很令人信服的。 不好的事情:Realm不支持Swift本机类型,我忘了在类vars中添加动态功能,并且遇到了一个奇怪的问题,即打印对象将显示正确的值,但是直接读取var总是提供默认值。 NSSplitView是一个无法比拟的时间消耗。 今天花费的时间:3个小时的NSSplitView,2个小时的功能开发 总开发时间:7小时