独立编程(阅读:在家)可能具有挑战性(阅读:由于Netflix),所以当我在Uber的《纽约女性密码》活动中听到Susan LoVaglio的闪电演讲中的Pomodoro技术时,我立即被卖掉了。 简而言之,Pomodoro技术是一种生产率方法,您可以在25分钟的间隔内完成一个目标,在此间隔5分钟。 对于像我这样管理博客,工作搜索和构建自己的应用程序的人来说,这似乎是实现自己的每个目标的好方法。 为了创建一个倒数计数器,我创建了一个Timer对象的实例。 在情节提要上,我创建了一个工具栏,并向其中添加了3个按钮按钮项:播放,暂停和重置。 在第20行上,您将看到一个布尔属性,用于标识计时器何时开启。 var timerIsOn = false 然后,我为每个工具栏按钮创建了IBActions函数:“重置”-> resetTapped,“暂停”-> pauseBtnTapped,“播放”-> playBnTapped。 对于我的playBtnTapped函数,请执行以下操作: 显示以前隐藏的进度条 如果计时器当前未打开,则创建一个timeInterval为1秒的Timer对象,其对象为“ self”(当前视图控制器),并调用我的方法timerRunning() 由于我现在已经创建了一个计时器,该计时器现在正在运行,因此我将timerIsOn的布尔值更改为true。 @IBAction func playBtnTapped(_ sender:Any){ // 1 progressView.isHidden =否 // 2 如果!timerIsOn { timer = Timer.scheduledTimer(timeInterval:1.0,target:self,选择器:#selector(timerRunning),userInfo:nil,重复:true) // 3 timerIsOn = true } } 单击播放按钮时将调用此timerRunning方法。 当我的倒数计时器变为0(零)时,此方法负责填充进度栏。 func timerRunning(){ timeRemaining-= 1 让completePercentage = Int((((Float(totalTime)-Float(timeRemaining))/ Float(totalTime))* 100) progressView.setProgress(Float(timeRemaining)/ Float(totalTime),动画:false) […]
六个月前,当我检查一个Github存储库时,我意识到该存储库没有任何Storyboard,所有设计都在代码中定义。 首先,我认为以这种方式开发应用程序将是可视化UI和检查设计的噩梦,但我也看到了好处,合并Storyboard时不再有git冲突,应用样式将更容易通过代码进行,因此我决定尝试一下。 首先要做的是永久删除您的主故事板! 然后在您的AppDelegate定义一个新的根控制器: 在“部署信息”下的项目设置中,将主界面保留为空白: 完成此步骤后,您的应用将直接从代码(在本例中为MainViewController 当您需要使用情节提要板来放置布局工具时,我会通过CocoaPods使用SnapKit来帮助我进行布局。 这是代码中MainViewController定义的示例,看看对snp.makeConstraints方法的调用以及使用一些简单的Struct定义颜色和字体的Styles使用 以及对应的样式: 因此,最大的优点是我可以重用LoginViewControllers,SignUpViewControllers,关于,配置文件等,并且只需更改Styles.swift定义就可以通过应用程序重用许多代码。
不久前,我受命为iOS应用程序开发功能。 这是什么功能? 很简单,搜索,解析地址并连接到启用Bonjour的设备。 问题在于,设备本身仍处于原型阶段,尚未准备好使用iOS应用程序进行测试。 我将如何测试我的应用程序? 我将如何确保我构建的功能将实际支持新设备? 除了模拟Bonjour服务外,我别无选择。 但是如何? 在我深入研究解决方案之前,让我解释一下Bonjour是什么。 Bonjour是Apple开发的协议,可使用行业标准IP协议在本地网络上自动发现设备和服务。 Bonjour,也称为零配置网络,可通过复杂,易于使用的编程界面轻松发现,发布和解析网络服务。 有关更多详细信息,请参见https://developer.apple.com/bonjour/。 我对该问题的临时解决方案:使用Node.js NPM的库发布模拟服务。 例如: 假设您正在开发自己的发布自定义bonjour服务的应用程序或设备。 您将如何验证自己已成功遵守Bonjour协议? 当前,bonjour浏览器没有一种方法可以扫描网络上每个可能的服务。 他们具有要搜索的硬编码服务库。 如果您的服务不在其预建列表中,请祝您好运。 使用KozBon,您可以轻松创建自己的。 定制服务类型将自动添加到库中,使您可以发现定制的已发布服务。 此外,KozBon允许您发布任何类型的模拟服务。 想模拟空投服务吗? 您可以。 要发布自定义服务吗? 您可以。 有兴趣下载该应用程序吗? 从App Store免费下载该应用程序,网址为https://itunes.apple.com/ph/app/kozbon/id1193790136?mt=8。 有任何疑问或意见,请随时访问我的网站http://kozinga.net 干杯!
带有learn.co的Swift课“ Swift和iOS简介” “骰子卷”应用 这是使用视图控制器进行编码的很好的练习。 目的是制作一个显示掷骰子结果的应用程序: 黑色正方形显示滚动结果(数字1表示1正方形,依此类推),底部标签显示以前的滚动。 红色=最近滚动。 我存储了我的IBOutlet变量,之后可以存储 类ViewController:UIViewController { 声明。 到模具按钮的IBAction连接是为我编写的,但我必须决定如何执行必要的操作。 覆盖func viewDidLoad(){ super.viewDidLoad() hideViews() 隐藏标签() } @IBAction func dieButtonTapped(_ sender:AnyObject){ 让theRoll = randomDiceRoll() updateLabelWithRoll(roll:theRoll) RearrangeDie(roll:theRoll) } hideViews()最初隐藏黑色正方形(模具上的点)。 “滚动”存储一个随机数1-6。 updateLabelWithRoll(roll:theRoll)滚动模具以更新每个标签的文本。 第一个滚动结果显示在最左侧的标签中,第二个结果显示在橙色标签中,依此类推。 RearrangeDie函数更新黑色视图方块以显示最新滚动的结果。 然后,我定义了以上功能。 我想知道是否没有更好的方法来编写updateLabelwithRoll函数。 我敢打赌,有一种方法可以将标签链接到字典,并使用for循环对其进行迭代。 对于标签中的我: 如果labels [i] == nil { 标签[i] = theRoll } 这是一个有限的应用程序,因为六次滚动后,无法继续记录滚动结果。 我不知道如何编程以在最左边的红色标签中显示最新结果,并且每次滚动结果时,结果都会被推到右侧的一个标签上。 看看是否可以添加以下修改将非常有趣: 重置按钮 赋予视图动画 将视图形状更改为圆形 对标签进行动画处理,以使每个卷向右移动。 添加压模声。 //返回一个随机的Int(1、2、3、4、5或6) […]
我喜欢聊天和消息传递应用程序。 尤其是那些界面最简单的应用。 我尊重简单性的艺术,并且自己建立了一些UI / UX方面的考虑因素和“陷阱”,这似乎是一项巨大的努力,但是值得付出的每一行代码。 我感兴趣解决的难题之一是如何区分视频预览附件和图像预览附件 。 第一步很简单。 如果您使用相机拍摄照片,录制视频或从照片库中选取图片,则文本视图中会插入一个缩略图。 消息保存后,便开始解决问题。 返回消息列表时,如何区分可能的异类图像缩略图和带有可能的文本的视频图像缩略图? 一种选择是设置消息建模以区分类别(图像和视频),但是在模型上需要额外的类型。 这不是一件坏事,而是在扩展或修改以后的模型时要考虑的额外一层复杂性。 我想到的最直接的方法是修改图像上的EXIF数据,特别是kCGImagePropertyExifUserComment属性。 我会检查Message对象是否有任何附件。 如果类型是图像(其他类型包括GPS,链接和自定义),则读取并解析kCGImagePropertyExifUserComment属性。 当用户点击图像时,我知道如何处理随后的视图转换:图像预览或播放视频。 如果您还有其他方法可以处理这种情况,我很想听听。 吉斯运动场
委托是一种常用的设计模式,它允许一个对象通过协议将工作移交给另一个对象(可能是不同类型)。 另一方面, 反应式编程围绕应用程序生态系统中变化的扩散而进行的数据流和传输。 这是通过观察者,可观察对象和调度程序完成的,观察者在调度程序告诉它们运行的线程上寻找可观察对象的发射。 James Rochabrun的文章“在Swift中逐步实现委托”是我阅读的关于委托的第一篇文章之一。 这是一个使用两个视图控制器A和B的简单应用程序。视图控制器A符合视图控制器B的委托协议,其中视图控制器B告诉A显示用户选择的颜色。 我将使用James的委托示例与使用响应式编程(RxSwift)的相同实现进行比较。 // 1 覆盖func prepare(对于segue:UIStoryboardSegue,发件人:任何?){如果让nav = segue.destination为? UINavigationController,让viewControllerB = nav.topViewController为? ViewControllerB {// 2 viewControllerB.delegate = self}} // 3 func changeBackgroundColor(_ color:UIColor?){view.backgroundColor = color} 此代码块在ViewControllerA.swift 。 //1当用户单击“显示视图控制器B”时,将调用该代码以准备该序列。 //2由于在此代码块中有对ViewControllerB的引用,因此我们将B的委托变量分配给self ,即ViewControllerA 。 协议ViewControllerBDelegate:类{ func changeBackgroundColor(_ color:UIColor?)} 接下来,在ViewControllerB.swift文件中,声明ViewControllerB.swift的协议,该协议包含更改View Controller A中背景颜色的功能。 // 1 弱var委托:ViewControllerBDelegate?// 2 @objc func handleTap(_ tapGesture:UITapGestureRecognizer){// 3 view.backgroundColor = tapGesture.view?.backgroundColor […]
最近,我正在为一家组织活动的公司编写应用程序。 该应用程序的主屏幕之一显示了当天的日程。 我的视图控制器有一个gridView ,它建立在一个UIStackView之上,该UIStackView包含一个带有白天时间的网格,模拟了本机日历应用程序。 每个事件都是一个小视图,应该放在它所属的位置。 为此,我编写了一个小方法,该方法根据事件的开始时间计算从一天开始的偏移量,并编写另一个方法,根据事件的持续时间检索视图的高度: 使用不同的比例因子需要您的功能考虑到这一点,将尺寸规格化并计算像素的所有内容: 这个解决方案以及其他许多解决方案都是由真正的摇滚明星。D. Lutz带来的。
正如我在第一篇文章中所说,这没什么大不了的,以编程方式制作UI的原因很多,最大的原因之一是90%的公司不使用情节提要,知道让我们开始登录屏幕吧…… 在现实世界中,您将从设计师那里获得屏幕,或者,如果您自己完成所有工作,则可以在素描或photoshop中创建一些设计,或者只是在纸上绘图,知道我们将专注于此,那么我们将尝试使其更漂亮 首先,让我们在项目导航器中创建两个文件,一个将是LoginController,另一个将是我们的LoginView。这很简单,我们都知道要这样做… 在继承自UIView超级类的LoginView类中,让我们创建一些属性,密码和电子邮件文本字段,就像您已经猜到的那样,并使用一个按钮让我们稍后登录主屏幕,我们将像在下面的图片中一样进行操作⤵️ 让我解释一下,首先忘记手势识别器… 我们正在闭包中创建属性,如果您不熟悉闭包,建议您访问此链接https://docs.swift.org/swift-book/LanguageGuide/Closures.html ,请记住,闭包的好处是swift是为我们管理记忆… 在此闭包中,您可以设置属性的所有属性,例如文本字段左上角的小图标,向我们显示,这是密码字段。 您可以用相同的方式创建电子邮件文本字段,以及所需的内容,知道何时清除让我们更进一步。 进一步割草,我们需要在LoginView中创建一些函数……类似⤵️ 这是什么啊 TranslateAutoresizingMask是UIView属性,可以为true或false,如果要使用“自动布局”来动态计算视图的大小和位置,则必须将此属性设置为false。 下面的代码我们可以在视图中添加子视图 我们正在写的所有代码都知道,您可以在许多函数中进行区分,但是我们不会那样做。 如何设置这个约束? 一点也不难⤵️ 如该图所示,我们拥有创建视图约束所需的所有锚点…重要的是不要忘记将isActive属性添加为true,因此此约束可以立即处于活动状态……默认为false😒 这个丑陋的白色错误表明密码文本字段的顶部锚点与电子邮件底部锚点之间的常量设置为10,只是不要忘记您是否是第一次进行此操作,这可能会有些混乱…… 在我们的视图类中要做的最后一件事是设置初始化程序并调用我们的方法……⤵️ 知道容易的部分😀 让我们将视图设置为LoginController… 首先,我们需要创建登录视图的实例,此后,我们需要创建函数以添加视图⤵️ 这样就很容易,并且可以通过某些视图扩展,约束扩展,协议等来简化(容易得多)……但这是更高级的方法,我们将在以后的课程中进行介绍……并且不要忘记在setLoginView func中调用viewDidLoad,并在appDelegate文件中设置初始视图控制器
本地化是使您的应用支持其他语言的过程。 在许多情况下,您首先使用英语用户界面制作应用程序,然后将其本地化为其他语言,例如日语。 本地化的过程很繁琐,随着XCode的更新,本地化的步骤会一点一点地改变。 在这篇博客文章中,我将基于最新的XCode XCode 7解释整个步骤。3.1。 在开始本地化工作之前,请确保已选中“使用基础国际化”复选标记。 什么是“基础国际化”? 当您创建新的XCode项目时,XCode将自动生成资源和包括默认语言在内的文件结构。 这就是所谓的“基础”语言。 如果您要为全球市场开发应用程序,通常您希望在此“基本”语言资源中使用英文文本。 添加新的本地化 好的,默认情况下,我们具有基本语言资源结构。 让我们添加新的语言支持。 在项目浏览器中选择项目文件,然后在项目和目标列表中选择项目。 打开“ 信息”选项卡,然后单击“本地化”部分下的“ +”按钮。 然后从显示的下拉列表中选择您要支持的语言。 XCode将打开一个对话框,显示要为新语言添加的资源。 按“ 完成”按钮将在名为[New Language] .lproj的新语言项目文件夹下生成这些文件。 (在此示例中,我添加了日语支持,因此创建了ja.lproj文件夹。) 现在,我们在项目文件夹中具有以下文件结构。 Localizable.strings文件在哪里? 您可以在Localizable.strings文件中添加翻译数据作为键值对。 XCode的早期版本默认情况下用于生成Localizable.strings文件,并且我们能够轻松地为其他语言复制Localizable.strings文件。 默认情况下,最新版本的XCode不会创建Localizable.strings文件。 要添加Localizable.strings文件,请转到File-> New-> File ,在iOS的Resource选项卡下选择Strings File ,将其命名为Localizable.strings并创建文件。 现在,您有了基本语言的Localizable.strings文件,如下所示。 要为日语添加Localizable.strings ,请在文件检查器中单击日语 。 这将在ja.lproj文件夹下创建一个新的Localizable.strings文件。 现在,我们有两个Localizable.strings文件-一个在Base.lproj文件夹下,另一个在ja.lproj文件夹下。 让我们将应用程序中使用的单词和短语添加到Base的Localizable.strings文件中。 下面是添加“ Welcome” =“ Welcome”的示例; 左侧是所谓的Key,稍后由NSLocalizedString方法使用该键从右侧拉出文本。 这是数据的键值对类型。 下面是NSLocalizedString方法的示例。 我们将键设置为方法的第一个参数。 通过将键指定为第一个参数,该方法可以从Localizable.strings文件中提取相应的值并返回该值。 在此示例中,我获得了警报标题,消息和按钮的本地化字符串。 下一步,我们将日语文本添加到ja.lproj文件夹下的Localizable.strings文件中,如下所示。 我们使用相同的键,但用相应的日语翻译替换值。 […]
您和您的团队已经开始使用Xcode进行黑客入侵。 在第一次合并尝试中,您会看到那些被注定的单词-CONFLICT 。 没关系,您之前已经处理过合并冲突。 除非您没有处理情节提要合并冲突。 或奇怪的软件包命名冲突。 或每次都涉及不记得创建的隐藏目录的冲突。 为什么合作如此痛苦? 两个字: 情节提要。 故事板本身是一个巨大的xml文件。 所有内容,从放置按钮的位置到实际放置视图控制器的位置(甚至不包含其中的内容,仅是视图控制器的位置)都保存在其中。 这意味着,即使您的队友甚至稍微移动视图,也将发生合并冲突。 一旦情节提要中发生合并冲突,就无法再在Xcode中对其进行渲染。 您的应用无法启动。 什么都行不通。 合并这些冲突可能非常困难。 您必须确保xml有效,这意味着所有标记均已关闭。 当情节提要xml文件可能长达数千行时,尤其糟糕。 故事板显然并不适合人类的目光,而且冲突之所以可怕,是因为变化几乎是随机的,这意味着您可能会花费数小时来尝试找出最后的标记或错字。 一般的良好做法是避免使用大型情节提要 。 但是,即使只有几个视图控制器的情节提要也很难处理。 其他协作问题涉及Xcode如何打包您的应用程序,以便您可以在设备上运行它,以及用于维护项目设置,文件结构等的所有元数据。 但是,与情节提要不同,解决这些问题至少不会使您发疯。 因此,请记住以下一些策略,可以使您的生活更轻松。 正确设置Git回购 这是标准的。 确保您的项目具有良好的gitignore (https://github.com/github/gitignore/blob/master/Swift.gitignore),这将有助于解决许多隐藏文件夹问题。 但是,如果您实际使用拉取请求 ,也会有所帮助。 Xcode项目非常脆弱,小事情会导致整个事情停止运行。 如果每个人都推动掌握,即使他们的项目在本地工作,也很可能导致主人中断。 为了避免不得不处理时髦的git命令来回滚提交(基本上,使一切变得混乱),让某人管理master分支并测试pull请求将使您的10倍轻松。 这也假定您也使用分支 。 请。 使用它们。 为不相互依赖的功能建立分支。 模块化工作。 这将帮助您专注于开发,而不是每次需要拉动或推入时都要清理git repo。 处理情节提要 这是处理情节提要的几种不同方法,每种方法各有利弊。 用一台笔记本电脑制作情节提要。 然后请一个人(只有那个人)更改情节提要。 这非常适合小型团队,因为在情节提要之外还有很多事情要做(例如模型逻辑,编写助手等)。 在一个会话中,您可以设置基本的视图控制器,按钮和插座。 之后,只需告诉情节提要的人您需要什么,然后让他们将您的功能连接到视图即可。 您的情节提要人员将处理情节提要的更改,创建主题,IBOutlets等。如果您也关注MVC,那就很好。 电子邮件代码。 这真糟糕。 请。 您确实应该只采用上述策略。 […]