Tag: 目标C

更好的表格视图数据源:捕获和传达状态

关于本机应用程序中更健壮的表和集合视图的实用指南 我构建的几乎每个本机UI都植根于表或集合视图。 我已经写了关于 表视图及其数据源的方法 ,这是高级入门。 这篇文章概述了开发人员编写代码时面临的常见问题; 倾向于将边缘案例处理推迟到以后的日期,这永远不会发生。 我关注的主要情况是加载,加载错误和无数据,但是我下面介绍的方法可以满足您的任何需要。 并非所有人都忽略了这些极端情况,但是我注意到,如果对它们进行处理,它们通常是在表视图之前处理并通过UI的生命周期进行管理(例如,当前视图控制器,启动加载,显示旋转磁盘,从DA返回,隐藏旋转磁盘,重新加载表)。 我更喜欢将加载/错误/无数据UI直接合并到表视图本身中,更重要的是,我希望数据访问和状态捕获独立于UI及其生命周期。 当您具有由依赖于可能处于不同加载状态的不同数据源的节组成的表视图时,这将带来很多好处。 当数据可用时(逐节)呈现数据通常很重要,而不是等待所有数据全部可用。 而且只有通过内联生命周期通信才有可能。 表格视图是数据访问失败和错误无声消失的地方 场景 :您出差在外的3G连接糟糕,当您意识到应用程序远离加利福尼亚州的高速LTE连接时感觉如何破损时,您会感到羞愧和厌恶。 问题 :通信基于网络的数据加载并启用故障重试对于专业构建的应用程序和UI至关重要。 请记住,这是一个面临连接挑战的移动平台。 如果您的表视图中充满了// TODO:handle error ,则可以尝试以下方法来改善它们 方法 :在数据源中创建数据类型的标准枚举,并让表视图处理每个枚举案例。 这是我的: 您的大多数数据块的类型都是“自定义”,但其他数据块则值得 当数据源通过从模型层读取数据进行组装时,它还可以向您的数据访问对象询问任何相关暂挂请求的状态。 当前正在加载东西吗? 有错误吗? 这是什么错误? 如果数据源对这些问题有任何有趣的答案,则可以使用相应的类型枚举值将数据块组装并附加到其自己的内部数据哈希中。 假设模型层为空,数据访问对象说请求仍在进行中。 数据源可以在加载块或加载错误块后附加相关的错误对象。 您会注意到,我对数据访问服务对象使用了类似的枚举,以便在状态枚举的上下文中轻松地传达状态 当向数据源请求给定索引(路径)处的数据块时,表格视图便能够快速切换所有可能的块类型,并做出相应的响应。 通过在应用程序范围内设置一些简单的加载和重试单元格,并将其注册到表格视图中,处理这些状态便成为样板代码。 也有机会自定义每种情况,但至关重要的是,它提供了一种快速一致的方式来传达这些经常被忽略的状态:加载,加载错误(具有重试能力)和无数据。 视图还可以选择完全忽略这些枚举值,并且数据源(例如,如果它不依赖于加载)可以明确表示从不使用它们。 我的视图控制器严重依赖数据管理器及其返回的块的类型 我构建的标准LoadError单元需要使用Load Error Retry Delegate进行初始化,然后视图控制器将其分派回数据管理器。 您可以看到如何将我们在cellForRowAtIndexPath中使用的相同开关逻辑应用于所有其他表视图委托和数据源协议实现方法。 在viewDidLoad中的单元格注册可实现对每个状态的良好,标准,简单的处理,它位于util中,如下所示: 将简单的可重用生命周期单元格注册到任何表视图 结论 我到处都使用这种模式。 它的维护成本低,这意味着我可以将开发工作重点放在我们要在要构建的表中呈现给用户的产品和UI上。 但这使我充满信心,在连接不畅或数据访问有问题的情况下,我正在构建的应用程序的用户将知道正在发生的事情(正在加载),并有权采取行动(重试错误) 。 永远不会出现这样的情况:他们不得不强制关闭应用程序以重试失败的数据访问,或者来回导航以尝试重新启动某些数据访问。 注意:不要在块类型切换语句中使用默认处理程序。 如果添加新的枚举值,则希望编译器向我提醒我需要添加对新状态的支持的位置,它可以帮助您建立对使用这些数据块的所有方式的信心。 […]

有趣的位掩码

有很多类型检查方法。 您可以将其定义为常量字符串以供日后检查,也可以使用enum进行便捷的方式(这种方式最多可以使用)…但是有一种类型检查的方法,即使用Bitmask 。 本文将引导您深入了解如何在Objective C中使用Bitmask 。 我们可以很容易地看到,Apple在SDK中使用了大量Bitmask ,例如: UIViewAutoresizing , UIInterfaceOrientation … 我们将创建自己的示例,让我们看看: typedef NS_OPTIONS (NSUInteger,PLandayEngineerTeam){ PLandayEngineerTeam_Mobile = 1 << 0, PLandayEngineerTeam_Backend = 1 << 1, PLandayEngineerTeam_Frontend = 1 << 2 }; 我们实际上使用了按位运算符,在这种情况下称为“ 移位” ,因为在此操作中,数字被移动或移位 。 在我们的示例中,数字向左移动。 欲了解更多信息,您可以查看一下有关位操作的信息:https://en.wikipedia.org/wiki/Bitwise_operation 因此,现在我们在Binary中提供示例: typedef NS_OPTIONS (NSUInteger,PLandayEngineerTeam){ PLandayEngineerTeam_Mobile = 1 << 0, // => 00000001 PLandayEngineerTeam_Backend = 1 << 1, […]

iOS中的动态单元格

UITableView在我们的iOS应用程序中很普遍。 我们可以在应用程序中的任何位置看到它。 但是作为新生,在发展中看起来很麻烦。 我想分享一些方法来在UITableView中执行动态单元格。 第一种方法是在协议方法中返回高度- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath每行- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 通常,我强烈建议您在设置TableView的EstimateRowHeight值之前,不建议使用此方法计算高度值。 如果您使用的是MVC或MVVM体系结构模式,则将计算过程写入Model类会更好。 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { NSDictionary *属性= @ {NSFontAttributeName:[UIFont systemFontOfSize:18]}; 返回[self.array [indexPath.row] boundingRectWithSize:CGSizeMake(300,MAXFLOAT)选项:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading属性:属性上下文:nil] .size.height + [self.subArray [indexPath.row] boundingRectWithSize:CGSizeMake(300,MAXFLOAT)选项:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading属性:属性上下文:nil] .size.height +15; } 警告:设置estimateRowHeight会更好。 第二种方法是在单元格的布局中使用约束。 在此方法中,我们不应调用协议方法来返回单元格的高度。 我们应注意其布局,其垂直约束应是完整而具体的。 顶部的单元格的顶部应具有约束,而最后一个单元格的底部也应具有约束。 在这种情况下,标题标签的单元格顶部有5个空格,子标签也有5个空格。 为满足此要求,子标签的单元格底部有5个空格。 (我用砖石来限制布局) 码: -(instancetype)initWithStyle:(UITableViewCellStyle)样式复用标识符:(NSString *)reuseIdentifier { 如果(self = [super […]

停业:通过比较和推理得出清晰性–巴拉特·纳丹帕利–中等

闭包:通过比较和推理清晰明了… 对于大多数主要的编程语言,闭包已经成为一流的公民。 这是尝试比较不同编程语言中的相似之处。 我们正在使用C,C ++,目标C和Swift编程语言。 在闭包的声明,定义和用法方面查看它们之间的相似之处。 宣言: 大多数闭包语法都源自“ C”中好的旧函数指针 “C” : returnType(* funcPointerName)(参数) C ++ :( lambda函数) [ 捕获 ] ( params ) throw() -> ret { body } objective-c: returnType(^ blockName)(参数) 迅速: {[捕获列表](参数)->返回类型 陈述 } 定义/用途: 实际上,在进行项目时,我们可以有一条规则 ,即@ 转义的任何闭包都必须在其捕获列表中包含[弱自我] 。 注意:-所有以闭包为参数的函数默认情况下均为非转义。 因此,如果您确定在函数返回之前将要调用闭包,则无需使用[弱自我]。 我想在下一篇文章中介绍一个主题。 @转义真的有什么帮助? 就内存管理(又名ARC)而言,编译器优化是什么? 参考文献 : 24.3函数指针和原型 通常,每次调用函数时在作用域中都有函数原型是一个好主意。 功能原型…… www.eskimo.com Swift.org Swift是一种通用的编程语言,使用安全性,性能和软件的现代方法构建而成…… swift.org […]

您是否在写Objective-Swift?

Objective-Swift [名词]:以Objective-C的约定和约束编写的Swift代码 在学习Swift的早期,我可能不知道或根本太害怕使用该语言的强大功能。 我以Objective-C的形式编写了Swift代码,导致不必要的可变性和多余的额外行。 以下是一些我最终不懂得好处的习惯。 出队细胞 客观快速 迅速 避免cell变量 没有可选的cell可以强制展开 行数少 命名空间常数 客观快速 扫一扫 改进了相关常量的可读性 富有表现力的枚举 物镜转换 迅速 没有重复的字符串; 字符串与枚举大小写相同 添加诸如OPTIONS类的另一种方法仅需要添加另一种情况 阵列运算 客观快速 迅速 没有创建其他变量 富有表现力的代码读起来就像一句话; “获取姓名并映射到其大写版本,并为每个姓名打印出来” 类型检查 客观快速 迅速 没有力量解开 结论 从Objective C背景学习Swift可能会导致称为Objective-Swift的代码。 Swift比Objective C具有许多优势,因此,恳请您发现利用这些语言的高级功能的方法。

创建一个iOS基础项目

该项目的想法是在开始新项目时用作模板。 它将包含3个构建配置: Debug , AdHoc和Release 。 我们将使用Fabric集成CocoaPods以分发应用程序,然后使用FBTweaks和来自Facebook的很棒的库。 我们将从创建一个应用程序ID开始。 在会员中心 转到证书,标识符和配置文件 : 然后转到“ iOS应用内的标识符”部分: 然后点击屏幕右侧的加号(+) , 并输入应用ID说明。 为您的应用ID使用正确的描述。 您以后可以更改它。 然后,输入一个App ID后缀: 这将是永久的,因此请三思而后行,因为您以后将无法更改它。 然后,选择完所有功能后,点击Submit 。 现在,我们将创建三个配置文件:一个用于开发 ,另一个用于AdHoc分发我们的应用程序(例如与QA团队内部分发该应用程序,并向我们的客户进行每周构建),最后一个用于Release 。 转到“ 供应配置文件”部分,然后单击加号(+) 。 然后,选择iOS App开发选项,然后点击继续 。 然后,选择先前创建的应用ID,然后点击继续 。 然后,选择要包括在“配置文件”中的证书,然后单击“ 继续” 。 然后,选择要包括在Provisioning Profile中的设备,然后单击Continue 。 最后,为Provisioning Profile选择一个名称,然后单击Generate 。 我们将对AdHoc和Release配置文件执行相同的操作。 再次单击加号(+) 。 现在,选择“ 临时”选项,然后单击“ 继续” 。 再次选择先前创建的应用程序ID,然后单击继续 。 现在选择一个有效的分发证书,然后单击继续 。 然后,选择要包括在Provisioning […]

隐藏窗口,而不是单击关闭按钮时将其关闭

开发单个窗口式,非基于文档的Cocoa应用程序时出现问题。 也就是说,当用户单击窗口上的关闭按钮时,它将关闭,但是无法将其恢复。 为了解决这个问题,我们应该“隐藏”窗口,而不是在用户尝试关闭窗口时将其关闭。 Xcode模板的最新版本针对单个窗口应用程序使用情节提要和窗口控制器,除其窗口控制器外,无法将窗口的委托连接到其他对象。 因此,这给了我们两个选择:1.子类化NSWindowController; 2.用代码将窗口的委托连接到目标对象,例如一个NSViewController对象。 解决方案1.子类化NSWindowController 创建一个新的NSWindowController子类,并在头文件中添加协议一致性(如果使用Swift,则不这样): 目标C: @interface VCWindowController:NSWindowController @结束 在实现文件中: #import“ VCWindowController.h” @interface VCWindowController() @结束 @implementation VCWindowController -(void)windowDidLoad { [super windowDidLoad]; //实现此方法以处理从其nib文件加载窗口控制器的窗口之后的所有初始化。 } -(BOOL)windowShouldClose:(id)sender { [NSApp hide:nil]; 返回否; } @结束 迅速: 进口可可 VCWindowController类:NSWindowController,NSWindowDelegate { 是否需要初始化?(编码器:NSCoder){ super.init(编码器:编码器) } func windowShouldClose(sender:AnyObject)-> Bool { NSApp.hide(无) 返回假 } } 创建类后,现在可以将代码连接到窗口。 一种。 将窗口控制器设置为自定义NSWindowController子类: b。 右键单击Window,将“代理”连接到Window Controller对象: 现在构建并运行您的应用程序,单击“关闭”按钮将仅隐藏您的应用程序,而不是关闭它。 […]

Objective-C内存管理[备忘]

[1]。手动内存管理 所有Objective-C类子类NSObject 1.NSObject类被引用计数 2.当引用计数== 0时,释放内存 初始化或复制:引用计数= 1 发布:参考计数— 保留:引用计数++ 约定:以init或copy开头的方法开头的方法: 返回“自动释放的对象” autorelease :引用计数-(稍后) ARC前 1.属性可以标记为保留 在超级释放中清理 演示版 现在关闭ARC 新文件/可可触摸类/将类名设置为Sweater和NSObject的子类 检查xcode中的内存泄漏 产品/资料/ 源代码 [2]。使用ARC进行内存管理 1.当打开ARC时,您不能使用keep,release,autorelease,dealloc 2.ARC!=垃圾回收 3.将指针变量声明为__strong(默认)和__weak 开启ARC 使用ARC的潜在问题:保留周期 将代码添加到演示保留周期 源代码 数据来自 编辑历史记录: 20171123添加

如何为任何iOS项目自动化CI

任何为什么每个项目都应该拥有它 生成状态标志是从README显示项目当前状态的好方法。 您可能已经注意到一些受欢迎的开源Pod在其README上有此功能。 要添加一个,请在Travis CI上转到您的项目,然后选择项目名称旁边的“ build pass”徽章。 徽章将代表哪个分支以及徽章的类型。 对于类型,选择Markdown以将其添加到自述文件中。 生成的文本无需修改即可将其添加到自述文件中。 如果有任何问题,可以单击该徽标以帮助将开发人员路由到Travis CI构建页面。 现在,我们已经向项目添加了CI构建服务,我们可以放心地构建新功能。 创建新的“拉取请求”时,Github将在Travis CI上自动创建新的构建。 生成状态将显示在“拉取请求”中,如下图所示。 有关如何设置和自定义.travis.yml文件的更多信息,可以在这里找到: 建立一个Objective-C或Swift项目– Travis CI 重要的是,您的设备目标在Xcode知道的设备中唯一地标识您的设备。 以来… docs.travis-ci.com 如果您有任何疑问,意见或对以后文章的要求,请在下面发表评论!

定制别针

func mapView(mapView:MKMapView,viewForAnnotation注解:MKAnnotation)-> MKAnnotationView? { 我正在使用MKMapViewDelegate的方法来自定义引脚。 后卫!annotation.isKindOfClass(MKUserLocation)排除了用户位置,因此我仍然拥有当前位置的标准蓝点。 我们需要创建一个销钉实例,稍后将其应用于地图上的位置。 让我们从分配标识符开始: 让注解标识符=“ AnnotationIdentifier” 然后在其上调用dequeuedAnnotationView 然后,我们需要配置将分配给该引脚的图像: commentView.canShowCallout = true以显示图像。 然后,您可以将UIImage分配给notesView.image 但是,每次地图加载时,我需要将多个图像随机分配给引脚。 为了实现它,我创建了一个图像数组,并借助arc4random_uniform方法从该数组中以随机索引分配了一个图像: 如果让注解=注解{ //在此处配置注释视图 subscriptionView.canShowCallout = true 让unicorn = UIImage(名称:“ unicorn.png”) 让熊猫= UIImage(名称:“ redpanda3d.png”) 让arr = [独角兽,熊猫] 让randomIndex = Int(arc4random_uniform(UInt32(arr.count))) commentView.image = arr [randomIndex] }