Tag: Objective C

将图像制作成圆形或圆形的iOS

此示例显示如何制作一个用如下半径四舍五入的UIView或UIImageView: 目标C someImageView.layer.cornerRadius = CGRectGetHeight(someImageView.frame)/ 2; someImageView.clipsToBounds = YES; 迅速 someImageView.layer.cornerRadius = someImageView.frame.height / 2 someImageView.layer.shouldRasterize = true someImageView.clipsToBounds = true 建议如果使用自动布局,则将someImageView.layer.cornerRadius代码放入viewDidLayoutSubviews中。 如果图像更改大小,这将允许更新图像的cornerRadius。 覆盖func viewDidLayoutSubviews(){ super.viewDidLayoutSubviews() someImageView.layer.cornerRadius = someImageView.frame.size.width / 2 someImageView.layer.masksToBounds = true }

Swift / Objective-C桥接中的循环引用

任何拥有两年以上历史的iOS / MacOS项目都必须处理Swift和Objective-C的混搭 ,在这种环境中,不同的语言会试图共存。 但是,这种和平可能会受到某些特殊条件的威胁,在某些特殊条件下,由于歧义性,无法正确建立两种语言之间的桥梁,例如在循环引用的情况下。 以这种情况为例: ObjcMainClass由符合Swift编写的ComponentProtocol的对象组成,因此需要导入ProjectName-Swift.h生成的文件 ObjcMainClassTests是用于测试ObjcMainClass组件的Objective-C单元测试类。 它将使用符合ComponentProtocol的StubComponent对象,以控制要测试的公共方法的执行流程。 StubComponent是在单元测试目标中定义的,并且需要包含@testable import ProjectName代码才能找到协议定义。 由于StubComponent位于单元目标中,并且是用Swift编写的,因此ObjcMainClassTests必须导入ProjectNameTests-Swift.h生成的文件。 尝试运行单元测试,您得到的是“在ProjectNameTests-Swift.h中找不到模块ProjectName”错误: 在采用模拟单元测试方法的项目中,这种情况可能很常见,其中将新Swift接口的具体存根传递到现有的Objective-C实体。 最好的解决方案是减少Objective-C和Swift代码之间所需的桥梁数量。 尝试将模块或对象图迁移到Swift,或在计划迁移本身之前在Objective-C中临时编写协议和存根。 第二种方法显示在Github上的演示项目中,您可以在此处找到失败和通过的场景:https://github.com/matsoftware/TestObjcSwiftCircularReference。 桥接愉快☺

iOS面试问题(快速)-第2部分

1.在Swift中解释泛型? 利用GENICS,您可以编写可与任何类型一起使用的灵活,可重用的函数和类型 。 您可以编写避免重复的代码,并以清晰抽象的方式表达其意图。 Swift的Array和Dictionary类型都是通用集合。 在下面的代码中,用于交换两个值的泛型函数用于字符串和整数。 这是可重用代码的示例。 func swapTwoValues (_ a:inout T,_ b:inout T){ 让临时A = a a = b b =临时A } var num1 = 4 var num2 = 5 var str1 =“ a” var str2 =“ b” swapTwoValues(&num1,&num2) swapTwoValues(&str1,&str2) print(“ num1:”,num1) //输出:5 print(“ num2:”,num2) //输出:4 print(“ str1:”,str1) //输出:b print(“ str2:”,str2) //输出:a 2. swift中的可选内容是什么?何时使用可选内容? […]

Swift中的回调

回叫是一个非常有趣的话题,我们经常在Swift /目标C中遇到。在本文中,我们不仅会从理论上了解回叫,而且还将能够理解何时以及如何在代码中使用它们。 在开始之前,让我们先了解一下每次阅读回调时经常遇到的单词。 处理程序/完成处理程序 积木 代表们 关闭 以上所有术语表示同一事物,即“回调”。 它们只是在语法上有所不同。 块/闭包或委托具有不同的语法,但工作方式相同。 注意:我们将在稍后更加详细地了解Blocks,委托和闭包。 什么是回叫? 回调是一个函数或代码块,它将在某个时间点作为参数传递到另一个函数中。 func callback(){ // 做点什么 } func executeCallBack(回调){ //做点什么 } 现在的问题是,我们在哪里以及为什么需要回调。 假设要求我们构建一个应用程序以从服务器下载文件,并以下载百分比或下载完成后更新界面。 有了一个向服务器发出请求并下载文件的功能。 我们不能只是调用该函数并期望它在下载完成后返回,因为下载过程可能需要几分钟到几小时的时间,并且在那之前我们不能阻止UI。 在这种情况下,回调可以挽救。 我们可以使下载功能异步运行,尽管它会在下载完成之前立即运行,但是下载状态可以在实际完成后稍晚更新。因此,您要做的就是将下载功能传递给回调函数,以在下载完成后调用或更新进度百分比。 同样,让我们​​考虑另一种情况。 假设有一个要求,我们希望将数据从弹出窗口传递到呈现视图控制器。 请参考下图。 在这种情况下,还需要回调以将数据从弹出窗口传递到视图控制器,同时将其关闭。 简而言之,我们可以在以下情况下应用回调: 将数据传递到上一个视图控制器或更新UI。 当一个任务正在启动时,它将异步完成(即,将在调用函数返回后的一段时间内完成)。 让我们看一下带有多个回调(Swift 4.0)的以下示例: func downloadMethod(_ params:String, successHandler :@escaping(_ arg:String)-> Void, failureHandler :@escaping(_ error:Error?)-> Void) { //下载文件后成功回调 successHandler (“已成功下载。”) 如果让err =错误{ //如果发生某些错误,则调用失败回调 […]

架构A / B实验(iOS)

对产品进行实验是公司获得其客户最佳响应的最强大的技术之一。 但是有时候,尤其是当它们同时超过2个或3个时,对于在整个项目中找到实验块的开发人员来说,这可能会有些沮丧。 在本文中,我将解释一种简单的体系结构方法来保持我们的代码干净和动态。 什么是A / B测试? 假设我们要改善应用程序的功能,以吸引更多用户使用它。 我们几乎没有改善它的想法(涉及设计,可见性等),但是我们不确切知道哪一个最能使用户获得最大响应。 解决方案是设置A / B测试 。 A / B测试是根据特定版本随机分配用户的实验。 让我们看看它是如何工作的: 假设我们想知道哪个是最好的价格,我们应该出售我们的高级会员才能获得最高的收入。 我们决定设置3种变化: 原始价格变化 :15,00 $; 变化A :25,00 $; 方案B :40,00 $。 通过特定API(即Apptimize API)使用我们应用程序的每个用户都将被分配为这些变体之一,并且该服务将向我们的客户返回已分配用户的变体。 此时,根据选择的变体,我们将执行一段代码而不是另一段代码。 在上面的示例中,用户将看到为其分配的变体选择的价格。请注意, 实验必须始终包含原始变体 ,换句话说,就是开始实验之前存在的变体,否则我们永远不会知道这是否是最好的解决方案,或者实际上是否还不够好。 做得好,实验正在运行! 现在,我们只需要等待任意时间即可获得结果。 好的,已经过去了一周,我们发现了以下结果: 原始变体: 1000个用户支付了15,00 $-> 15.000,00 $的收入 ; 变体A: 800个用户支付了25,00 $-> 20.000,00 $的收入 ; 变体B: 300个用户支付了40,00美元-> 12.000,00美元的收入 ; 请注意,最低价或最高价均未赢得! 实际上, 变体A […]

为iOS工程师的工作做好准备

移动应用工程师的要求很高。 同时,它被认为是很难获得的工作之一。 我将介绍您可以采取的基本策略和流程,为您将来的工作做好准备。 我需要知道些什么? 如果您在线搜索面试问题,您会发现奇怪的逻辑难题问题,例如旧金山有多少个窗户。 现在,大多数公司都不再浪费时间在这些问题上,不要花时间在这些问题上。 这就是Google停止询问奇怪,疯狂的面试问题的原因 当您考虑要被Google聘用需要什么时,您可能会记得它臭名昭著的艰难面试…… www.businessinsider.com 标准面试流程如下 电话筛选 编码电话筛选 行为面试 编码面试 这次,我将专注于编码电话筛选和编码采访。 那你需要知道什么? 答案很简单,iOS应用程序开发。 大多数面试官想了解您是否是一名出色的iOS应用工程师。 即使有些公司会要求您回答疯狂的算法问题,但这些问题通常与优化等日常工作相关。 准备面试 我通常会建议初级开发人员花一些时间来复习他们的知识。 目标C 可可SDK OO基本原则 阅读Apple的Objective-C指南以了解您的知识差距。 通过面试问题示例来复习Cocoa SDK知识也是一个好主意。 20个iOS开发人员面试问题| 编码器 有即将面世的iOS开发人员职位面试吗? Codementor Matt一直在进行12年的技术面试…… www.codementor.io 当您回答这些问题时,请切实考虑。 例如,对于诸如“解释强,弱和复制之间的区别?”之类的问题,将其改为“在什么情况下,您会使用强,弱或复制?”。 这将帮助您不记住但以实际的方式理解该概念。 基本的OO原则有助于证明您可以编写良好的代码。 没有人愿意雇用任何弄乱代码库的人。 一如既往的好起点是Head First系列。 首先,面向对象的分析和设计涵盖了如何开始思考面向对象。 当我申请目前的工作时,Robert Martin的敏捷软件开发,原理,模式和实践也非常有帮助。 本书通过大量示例代码介绍了OO原理。 我是否需要了解尖端技术和算法 我个人认为,除非公司正在使用诸如RFP,Swift等之类的尖端技术,否则您无需审查这些尖端技术。这仅仅是因为它们会显示出您的好奇心和兴趣,却没有显示出您编程技能的基本基础。 对于那些尖端技术,我不会太担心。 算法很重要,但在完善iOS知识之后才出现。 对于Google和Microsoft等大公司来说,算法变得越来越重要。 本文有助于为那些大公司做准备。 编码训练营结束后,我花了3个月时间申请工作。 这是我学到的。 刚毕业时发生的事情很少谈论Bootcamper的旅程-当您搜索… medium.freecodecamp.com 本文为iOS工程师提供了很好的问题清单。 […]

VIPERtasarımpaterni nedir?

吉里斯 Apple iOS的MVC模式,可以帮助您解决MVC的问题。 1996年MVC足球比赛将在MUL 1996举行。 Microsoft网络模型Web窗体Web窗体MVC模式2009年窗体的窗体。 iOS的MVC模式的MVC模式的ihtiyaçlarıkarşılamamayabaşladı。 位置视图控制器的位置已过时。 业务逻辑模型业务模型模型业务层数据库—数据模型sade hale getirildi。 她的母亲是孩子,是孩子,是孩子,是孩子,是孩子,她的孩子,孩子,孩子,孩子,孩子,孩子,孩子,孩子,孩子。 an MVC haricinde MVP,MVVM和VIPERtasarımpaternleri var。 在iOS上的应用程序在VIPER上运行的时候,会出现inceleyelim。 VIPER mimarisi nelerdenoluşur? VIPER mimarisiadını视图,交互者,演示者,实体路由器(线框)’ılkharflerindenalıyor。 Bukavramlarınneolduğunakısacabakalım。 视图: VIPER mimarisinde视图被动演示者演示者被动演示。 HangiiçeriğingösterileceğiView’ebağlıdır。 Kullanıcıactionlarıpresenter’ayönlendirir。 交互器:业务逻辑işlemlerininyapıldığıkısımdırveuygulamanınomurgasınıoluşturur。 Bu katmandayapılanişlemlertamamen UI danbağımsızolmalıdır。 主持人:主持人esas olarak查看il ilgili logic’iiçerenkoduiçerir。 用户交互作用的用户数据查看用户交互作用。 查看ile Interactorarasındabirköprügörevigörür。 Bu katmanda视图ile ilgili veyauygulamanın商业kurallarıylailgili kodbulunmamalıdır。 实体:交互模型tarafındankullanılan模型nesneleriniiçerir。 Entity’lerin sadece Interactortarafındankullanılmasıçokönemlidir。 Interactor asla演示者层’实体模型lerinigöndermez。 路由器: Hangiekranlarınne zamangösterileceğinibelirlendiğiuygulamageçişakışınbulunduğukatmandır。 […]

实现UIRefreshControl

前几天我在和朋友聊天,他提到了一些很有趣的事情。 他正在一个项目中,他们根本不使用任何开源代码(即,没有直接依赖项)。 这让我开始思考,如果我在相同的约束下运作,我的项目会是什么样子。 因此,当我最近被要求实施“按需刷新”功能时,我认为我可以在不咨询开源霸主的情况下试一试。 总览 实现可刷新的样式刷新控件,该控件可以附加到UITableView上,而不会泄漏太多实现细节。 需要使用可响应状态更改的文本和图像进行自定义。 源代码可以在这里找到。 由于很快就把它放在一起,所以还没有经过充分的测试,但是似乎可以正常工作。 如果您有任何改进方法,请告诉我。 第一站,UIRefreshControl 我在这里写了很长的篇幅谈论股票更新控制,但是我看到了它们的利弊时选择了: +易于使用,可直接放入解决方案 –难以定制 –非全萤幕检视画面上的视觉错误,例如跳动的动画 如果您对股票动画没问题,正在使用全尺寸的表格视图以及使用UITableViewController,那么这将是一个完美的控件。 不幸的是,这些都不适用于我试图做的事情。 在使用UIRefreshControl进行了一些修改之后,我放弃了自己的程序并推出了自己的程序。 我真正喜欢的是Apple的刷新控制界面。 它们仅公开一个动作(UIControlEventValueDidChange)和一组方法(beginRefreshing和endRefreshing)。 这使得管理表视图编码时如何与控件交互以及将所有实现精巧地保留在刷新控件本身中变得非常容易。 因此,我从他们的设计中得到了启发,以启发我自己的版本。 但是在我们开始之前 UIRefreshControl如何工作? UIRefreshControl的核心极其简单,但与其他所有细节一样,魔鬼也是如此。 我无法确切地说出苹果实施的工作原理,但我必须想象流程如下。 要记住的关键是我们将使用tableView子类的scrollView —因此,当我在下面引用tableView时,它实际上是其scrollView超类的属性。 观察tableView内容的偏移量 当contentOffset.y> pullDistance时,触发刷新 调整tableView contentInset和contentOffset以解决以下状态: 默认值(用户完全没有与tableview进行交互) 拉(用户已拖动表格视图,并且控件尚未完全显示) 拉动(用户已拉动表格视图,并且控件已完全显示,但尚未达到刷新距离) 拉动和刷新(用户已拉出足够的距离以达到刷新距离) 已发布(用户在刷新距离之前已释放表) 已发布(用户在刷新距离后已释放表) 我们实际上并不会专门针对所有这些状态进行编程,但是最好记住控件将负责处理哪些状态,并为我们提供如何对这些状态做出反应的良好框架。 另一个有趣的地方是来自Apple的文档:“拥有刷新控件的UITableViewController对象还负责设置该控件的框架矩形。 因此,您不需要直接在视图层次结构中管理刷新控件的大小或位置。”因此,我们将尝试做同样的事情,并使它对于最终视图控制器尽可能地无缝。 自定义刷新控件 设置此控件将是了解滚动视图的contentOffset和contentInset如何工作的问题,然后如上所述适当地调整为不同的状态。 让我们遍历每种状态并了解视图的外观,以便我们对需要做的事情有很好的了解。 内容偏移 苹果将​​其描述为“内容视图的原点与滚动视图的原点之间的偏移量”,这实际上是很有意义的。 contentOffset只是任何滚动视图上的一个属性,它是一个精确描述了此CGPoint的属性。 contentOffset可以告诉我们用户将滚动视图从其原始位置拖动(或偏移)了多远。 该点将从(0,0)开始,并在您向下拖动滚动视图时,偏移量将开始增大(0,-1),(0,-2)。一直到用户拖动的程度。 回想一下,负数表示用户在视图上向下拖动。 因此,这样做的目的是提供一种简单的方法来查看滚动视图被拖动到多远,并且一旦有了,我们就可以通过执行类似这样的操作来响应contentOffset.y。 我们使pullDistance保持正值,以便以后使用时更容易。 -(void)scrollViewDidScroll:(UIScrollView *)scrollView […]

具有构建模块化SDK的经验

在conichi中,我们正在努力改善酒店的客人体验:加快入住和退房流程,带来移动支付的可能性等。 为了构建此基础架构,我们一直在研究三个主要项目,其中最重要的一个是我们的移动SDK,我们正在将其集成到合作伙伴的应用程序中。 我们一直在构建SDK时,要牢记它应该是模块化的。 所谓模块化,是指每个合作伙伴都应该可以使用他们所需的唯一功能来构建其SDK。 我们如何使代码成为可能 首先,我们分离了核心功能,并基于对配置对象的依赖注入进行了初始化过程: @interface CNISDKConfiguration:NSObject @属性(非原子,副本,只读)NSString * apiKey; @属性(非原子,副本,只读)NSString * apiSecret; @property(非原子,赋值,只读)CNISDKLogLevel logLevel; +(instancetype)configurationWithBlock:(void(^)(id 配置))configurationBlock; @结束 该对象允许基于块的可变初始化,并且遵循NSCoding协议,以避免任何引用的相关问题。 我从Parse框架实现中汲取了这个想法。 下一步是为“工具包”创建统一的界面: @protocol CNISDKKit +(void)enableWithConfiguration:(CNISDKConfiguration *)配置; +(instancetype)sharedInstance; -(无效)开始; @结束 该协议要求使用以下方法来启用Kit并对其进行配置,启动基础Kit的任务以及能够访问共享实例。 每个Kit都有自己的初始化参数,开发人员还可以在初始化期间将其作为依赖项注入传递 @protocol CNISDKKitConfiguration @结束 不幸的是,我还没有为Kit的配置对象提供任何统一的属性或方法,但是这个简单的协议至少可以为我们提供类型安全性和有关此对象外观的高级信息。 由于唯一的核心模块应该初始化Kit,因此我们创建了一个对象,该对象表示Kit及其配置之间的一对一关系 @interface CNISDKKitBundle:NSObject @property(非原子,强,只读)Class 套件; @property(非原子,强,可为空,只读)id 配置; +(instancetype)bundleWithKit:(Class )工具包配置:(nullable id )配置; @结束 并为核心配置添加了一个新属性-一系列工具 @interface CNISDKConfiguration:NSObject 。 。 。 @property(非原子,强,只读,可为空)NSArray * […]

揭秘iOS应用的编码–一个完整的新手!

我只编码过一个应用,EVER,而且我不是程序员。 我的前一个职业是从事建筑设计的设计建筑师长达11年。 作为设计了大部分生命(包括uni在内的17年)的人,我看到和记住代码的方式可能与典型的程序员完全不同。 那么我怎么看代码呢? 与典型程序员的主要区别是: 我只是在开车,而不是在学习如何设计汽车。 我不了解编程的所有概念。 就像我会说广东话,但不会读或写。 对于新手编码员来说,说话就足够了。 为什么这对非编码人员有利? 关于编码,任何人都会告诉您的最重要的事情只是开始编码。 阅读教程并了解相关理论非常好,但是作为一个新手,为什么不从头开始呢? 但是,当然不是那么容易吗? 开始一些已知的事情,尤其是像编码这样令人生畏的事情,最主要的是恐惧。 只是您会学会忍受编码的恐惧。 在代码中总会有一些您不知道的东西。 这是我了解使用Objective C进行编码的一些方法,从长远来看将为您提供帮助。 目标C是一种基于对象的编程语言。 它的意思是: 就像罐中的软糖一样,您编写的每个小脚本都是一个软糖。 一些软糖具有相同的颜色,它们可能属于同一类别,即黄色与绿色软糖类别。 此描述并不完全准确,但是对于非编码人员,请暂时忘记专家的知识! 编码软糖需要3个常规步骤。 1.初始化它,2.添加属性,3.然后将它添加到某些东西中。 而已! 例如1.启动黄豆。 2.定义大小,颜色和点。 3.然后将其添加到果冻罐中。 您的第一堂课完了! 真的,那是它的主要要旨。 当您想到编码为软心豆豆时容易吗? 当然,制作1或2个软心豆糖会制作非常非常简单的程序。 但这是一个开始。 这是一些创建按钮的真实代码: UIButton * btn = [[UIButton alloc] init]; btn.frame = CGRectMake(0,0,100,100); [btn setTitle:@“我是一个软心豆粒糖” forState:UIControlStateNormal]; btn.titleLabel.font = [UIFont fontWithName:@“ SFUIText-Regular” size:15]; [jar […]