在UIWebView中调用alert()会弹出一个对话框,其中您的URL(主机名)作为Dialog标题,这很烦人。 这里讨论的方法很少(hacks)(http://stackoverflow.com/questions/10681381/change-javascript-alert-dialog-title-in-ios),但它们并不十分优雅。 随着JavaScriptCore的引入,我们可以通过JSContext用本地函数很好地替换警报函数。 类ViewController:UIWebViewDelegate { 让webview:UIWebView! let alertFunction:@convention(block)字符串->无效= {(消息)// //#1 UIAlertView(标题:“本机警报”,消息:消息,委托:nil,cancelButtonTitle:“确定”).show() } func viewDidLoad(){ webview.delegate =自我 } func webViewDidFinishLoad(webView:UIWebView){//#2 if(webview.loading){return} //#3 让context = webview.valueForKeyPath(“ documentView.webView.mainFrame.javaScriptContext”)为! JSContext context.exceptionHandler = {上下文,异常 打印(“ JS错误:\(例外)” } context.setObject(unsafeBitCast(alertFunction,AnyObject.self),forKeyedSubscript:“ alert”) //测试 context.evaluateScript(“ alert(’Test Message’);”) } } alertFunction是我们的本机弹出功能。 在此示例中,我使用了不赞成使用的UIAlertView来简化演示。 您应该使用UIAlertController或自定义弹出窗口。 每次加载页面时,我们都需要执行此操作,因此代码进入UIWebViewDelegate函数webViewDidFinishLoad中。 由于webview可能多次调用webViewDidFinishLoad(ajax调用等),因此我们确保在webview.loading为true之后,代码仅执行一次。
我们有两个问题要考虑是否使用static 类型属性 。 将此值与类型本身相关联是否有意义? 此属性是否包含提供上下文的信息,而无需实例化实例? 如果此值独立于类型,则可以考虑使用static类型属性。 例子 在2D地图上,我们使用Point(x, y)表示位置 结构点{ 令x:整数 令y:整数 } 地图上的原点不会将此值与地图类型本身相关联。 它永远不会根据实例而改变。 由于它永远不会改变,因此我们可以将其声明为static 类型属性 。 如果我们希望原点始终为(0, 0) ,则可以使用let 。 结构图{ 静态让原点= Point(x:0,y:0) } print(Map.origin)// Point(x:0,y:0) 否则,如果我们希望原点是可变属性,则可以使用var。 结构图{ 静态var原点= Point(x:0,y:0) } Map.origin = Point(x:1,y:1) print(Map.origin)// Point(x:1,y:1) 我们可以启动Map实例,但是新实例不能使用static属性 。 另一个失败的例子 失败的原因是,即使通过计算属性,编译器也不允许创建的新实例使用static来源。 为了解决这个问题,我们可以添加static使x处于相同的作用域。 使用静态类型属性的另一种方法。 实际情况是,如果您将类型声明为静态,则它将成为引用类型。 结论 那么什么时候我们要使用static 类型属性呢? 我建议如果要声明全局属性,请使用静态类型属性。 它更有意义,并且更安全地跟踪价值。
整个故事始于例行的团队会议。 讨论了有关使用Gartner的工具包进行应用程序适应性和价值审查。 填写另一个excel表格的热情不高。 有人提到使用App来做会更好玩。 如果可以在一个周末买一瓶酒,那么会发生一些笑话,然后我们继续前进。 接受挑战 我认为,如果我能够做到这一点,那将对我的同事建筑师产生启发。 这是周末和编码之夜@Zmags的故事。 免责声明-Gartner拥有此评估工具包的所有版权,因此,我认为我不能分享它。 出于同样的原因,我无法共享项目的全部源代码。 我没有律师钱。 产品 与其说是在图表上可视化结果,不如说是根据一组具有评级的智能标准评估应用程序列表。 因此,有一个应用程序列表,一个调查表,一个介于1到5之间的评分,一些智能算法以及一个图表。 而已! 警告-示波器蠕变! 然后,我开始思考此应用程序是否可能是SaaS产品。 可能是公司在这里维护其应用程序的适用性吗? Gartner可以提供此服务吗? 而且比起我我对功能的了解还不够。 添加了身份验证,Web界面,导入/导出和API,付款。 什么可以赋予它更多的附加值? 让我们有一个类似timemachine的历史。 哦,让我们添加身份验证和注册,以便该应用程序可以作为SaaS出售。 让我们进行全面的应用程序组合管理扩展等。 停! 这是一个有趣的周末项目! 说到时间表 我有一个周末,外加一个编码聚会@Zmags +通勤时间。 周末我总共花了6个小时( 两个小孩子Not不错 )+聚会时6个小时+火车上1个小时。 大约是 13个小时的纯粹编码乐趣。 这项研究 因此,我不得不找出如何制作应用程序。 在这里,您可以查看电报样式的过程和结果: Google – Github – Cocoapods – Google – Stackoverflow – Google – Github – Stackoverflow,Cocoapods – Google […]
? O聚光灯索引乌拉姆菲拉芒塔许可塞贾姆criados项目buscáveiscom oconteúdo或存在于umaaplicação。 Estes itenssãobuscáveisatravésdo Spotlight。 操作系统criados aparecem quando uma das palavras chaves,que podem ser definidas pelo desenvolvedor,ébuscada no Spotlight。 Alémdisso,符合条件的构成作品。 最适合做的是Spotlightéselecionado,自动复制和质量控制。 AppDelegate可能具有相同的许可权,可以从项目中获得任何好处,包括合作伙伴,项目合作伙伴和合作伙伴。 范例 基调 没有聚焦的图像。 Comovocêpode观测器,a公共汽车“ spotlight”,podemos可识别的主题发言,最重要的发言在seutítulo进行。 在主题演讲中有重要意义的内容,请参见《龙卷风》。 WhatsApp的 应用程序在聚光灯下进行交互,显示应用程序的运行情况。 在WhatsApp上进行合格的对话,这是WhatsApp的主题,没有任何特别之处。 Assim como nomes de contatos e grupos。 Nas会为聚光灯下的观察物成像。 重要的物品清单,包括自动完成的布局图和布局图。 通过示例: Mais para frente没有教程,请参见属性集。 在agora上,具有重要意义的要素。 O标题,文本标识,空间标识,内容标识,内容描述,音频标识和缩略图标识。 Alémdisso existem覆盖了a deprotos que podem ser definidos,alémde atributos […]
这是不可避免的-您可以设计一个出色的UI,然后在模拟器或设备上运行它。 您点击一个文本字段,键盘从底部向上猛扑,您看不到正在输入的任何内容。 那里有处理这种情况的框架,还有一种使“自己滚动”的技术-这里还有另外一种收集方法。 扩展名 扩展是扩展类,结构,枚举和协议的好方法,无论您是否有权访问源代码。 这对于隔离协议实现的功能块(例如UITableViewDelegate,CLLocationDelegate)视图控制器实现非常有用。 我亲自采用了这种做法,作为保持源代码干净和可读的一种方法。 扩展在无法访问原始代码的情况下甚至更好。 例如,假设您希望添加wizbang功能,以在每次要使用此新的有尖齿的功能时都无需子类化,强制转换就可以转换代码中的任何String 。 扩展使此操作变得非常简单 入门 通常,如果我将扩展用于UITableDelegate之类的东西,则只需将扩展名添加到与UIViewController相同的源文件中。 当扩展更笼统并且将适用于所有UIViewControllers时,我将扩展代码添加到单独的文件中。 除了将texfield委托输出连接到视图控制器外,我们还需要在视图控制器类中添加两个方法。 这些方法使视图控制器可以根据视图控制器的生命周期为键盘事件注册和注销。 只需两行代码!
在上一篇文章中,我们描述了一种称为基于属性的测试的测试方法。 我们不用编写示例来测试我们的代码,而是编写输出必须具有的属性。 我们可以继续编写约束该输出的属性,直到我们对我们的软件需要做什么进行准确的说明。 Swift中基于属性的测试—简介 这是Swift进行的基于属性的测试(PBT)系列的第一部分。 在这第一篇文章中,我们将… medium.com 尽管无需任何库就可以执行这种类型的测试,但是有些工具可以帮助我们简化这些任务。 在Swift中,我们可以使用SwiftCheck (一种秉承Haskell的QuickCheck精神的开源库)。 在您的项目中包括SwiftCheck就像使用CocoaPods一样容易。 只需添加pod ‘SwiftCheck’, ‘~> ‘ ,将替换为该库的最新版本。 安装好吊舱,就可以开始了! 使用SwiftCheck编写基于属性的测试 在上一篇文章中,我们使用了String串联示例。 我们可以使用SwiftCheck重写三个基于属性的测试: 让我们分解一下这些测试的结构: 我们必须通过扩展XCTestCase并添加带有test前缀的方法来创建常规的单元test 。 在每个单元测试中,我们创建一个带有String的property ,该property描述我们要测试的内容。 使用运算符<- ,我们调用forAll ,它收到一个闭包。 此闭包接受许多参数,这些参数的类型实现Arbitrary协议。 现在不用担心,该库为我们扩展了基本的Swift类型。 这个闭包的参数将是用于基于属性的测试的随机字符串(在上randomString()文章中,我们是使用randomString()创建的)。 在闭包的主体中,我们执行要测试的方法或函数。 最后,我们不需要编写断言,而是返回Testable表达式。 在我们的例子中,我们从正在执行的比较中返回一个Bool 。 运行这些测试将多次执行我们的闭包。 默认情况下,每个属性都会运行100次,尽管可以增加或减少此数目。 如您所见,使用SwiftCheck编写基于属性的测试非常容易。 在这些系列的最后一篇文章中,我们将展示如何约束这些测试的输入(有时我们可能会对输入类型的某些子集感兴趣)以及如何为我们的自定义类型提供输入。
Firebase云消息传递(FCM) Cloud Messaging是Firebase的免费酷功能之一。 将推送通知从服务器发送到FCM很容易,它可以处理iOS,Android和Web的其余部分。 我将在本文中跳过设置。 您可以按照精心编写的设置指南,将Firebase添加到您的项目中。 您可以通过Firebase控制台或应用服务器连接到Firebase Cloud Messaging。 Firebase控制台非常简单,但这是手动工作。 我将在这篇文章中介绍应用服务器。 通过FCM发送通知的方式有三种 。 您可以将通知发送到一个设备或设备组或主题 。 我想向特定用户的所有设备发送通知,并且我不想存储令牌。 在这里,我将跳过仅将通知发送到一种设备的方式。 设备组也用于将一个用户的所有设备分组。 这样,您可以将通知发送到一个用户的所有设备。 因此,它们两个都需要存储令牌。 如果您需要将每个用户的消息发送到多个设备,Firebase建议使用设备组。 但是正如我所说,我不想存储令牌。 因此,我将只关注本文中的主题。 如果您更喜欢存储令牌并进行处理,则可以使用其他两种方式。 什么是主题 ? 主题基于发布/订阅模型。 每个设备可以订阅不同的主题。 服务器向主题发送请求。 FCM处理休息,所有订阅的设备都收到通知。 这样简单而强大的方法。 但是,作为每项服务,它都有优点和缺点。 主题未针对快速交付进行优化。 因此,发送通知和接收通知之间可能会有延迟。 主题针对吞吐量进行了优化。 现实生活场景 我们有一个微服务,当它接收到事件时会创建推送有效载荷。 我们可爱的推送程序不了解客户端设备,也没有任何存储空间。 当基础系统上发生新事件时,它将得到通知。 然后,它将通知发送到移动平台。 我们的推送程序将HTPP请求发送到FCM。 您可以在此处了解有关FCM的服务器实现的更多信息。 我们的基本请求结构如下: https://fcm.googleapis.com/fcm/send 内容类型:application / json 授权:key = SERVER_API_KEY { “ condition”:“主题中的“ condition1”和主题中的“ condition2””, […]
重用UIKit元素,集中观察者,简化设计。 您在上图中看到了什么? 一个有趣的建筑 设计 。 您还能观察到什么? 三次重复 模式 。 尽管重复模式在体系结构中是神圣的,但在其他地方却不那么受重视。 我们所有人都在开发具有某种形式的应用程序,通常用于捕获个人详细信息(例如注册)。 您必须向上移动活动文本字段,因为它原本在键盘后面。 为此,您必须观察键盘的UIKeyboardDidShow和UIKeyboardWillHide通知,以便您可以在键盘向上时对文本字段位置应用垂直偏移,而在关闭键盘时可以移除该偏移。 典型形式如下所示(从下面的代码片段创建)。 如果您从事的大型项目具有几种这样的形式,则可能发现自己不得不在需要该功能的每个ViewController中重复执行键盘通知观察代码。 但是,对于这样的表单,我们可以使用tableview而不是直接使用滚动视图,然后使用自定义的公共Tableview进行观察。 这是一个例子。 监听键盘显示更改的自定义表格视图 在这里,我们传入了将要坐在键盘上的视图(必须是weak property以避免保留周期)。 然后,我们创建一个协议,使用此自定义Tableview的所有类都必须遵守该协议。 接下来,在我们的注册视图控制器中,我们将使用自定义表KBTableView ,即KBTableView来监听键盘显示更改,而不是使用普通的表视图,并实现两种协议方法。 使用键盘侦听器TableView的ViewController 这就对了。 如果我们还有另一个带有窗体的viewcontroller,则它也只订阅KeyboardDisplayChangeProtocol协议,而不必观察键盘显示的变化。 如果您希望在此处查看我们的CustomCell : 如果您觉得这篇文章有用,请随时喜欢它,也欢迎您关注我们的出版物以跟踪后续文章。 谢谢!
扩展名有照片,共享,自定义键盘等几种类型。扩展名是iOS 8中引入的功能,非常受欢迎。 我们将专注于其中之一。 今天的扩展也称为小部件,并描述简单的实现。 让我们解释一下关于小部件的细节。 首先,今天和其他扩展都是简单的“子”应用,它们正在扩展“父”应用,因此不能单独分发。 今天的扩展程序可以为用户提供快速信息,如日程安排,天气,阅读最多的新闻。 他们必须具有更新的内容,具有低内存使用率的简单UI,因为用户通常可以具有多个扩展名,已打开并且系统将立即终止使用过多内存的扩展名。 互动是有限的。 没有键盘访问权限。 理论足够,让我们开始执行。 打开Xcode,然后在“文件”菜单中选择“新建”>“项目…”(将其作为编程语言)。 创建项目后,打开“文件”菜单,然后选择“新建”>“目标”,然后在“ Aplication Extension”部分中选择“ Today Extension”。 在出现有关为扩展创建新方案的警报后,只需单击“激活”。 Xcode将为您创建一个新的.storyboard文件(默认情况下为MainInterface.storyboard),UIViewController类(默认情况下为TodayViewController)和另一个Info.plist文件。 在Info.plist文件中,我们可以在Bundle显示名称键下更改扩展名,并设置更长,更具描述性的名称。 扩展仅是StoryBoard和UIViewController,它具有所有可用的方法(viewDidLoad(),viewDidAppear()…)。 要设置高度值,我们可以使用preferredContentSize来设置所需的高度。 宽度的最大值将是屏幕的宽度。 将self.extensionContext?.widgetLargestAvailableDisplayMode = .expanded添加到viewDidLoad()以在扩展视图上添加“更多/更少”按钮。 我们必须实现widgetActiveDisplayModeDidChange(_ activeDisplayMode:NCWidgetDisplayMode,withMaximumSize maxSize:CGSize)协议方法,该方法将在按下“更多/更少”按钮时被调用,扩展大小可以根据该方法中的状态进行设置。 widgetActiveDisplayModeDidChange(_ activeDisplayMode:NCWidgetDisplayMode,withMaximumSize maxSize:CGSize)是NCWidgetProviding协议的一部分,稍后我们将提及(func widgetMarginInsets(forProposedMarginInsets defaultMarginInsets:UIEdgeInsets)-> UIEdgeInsets在iOS 10中已弃用)。 在继续之前,请打开MainInterface.storyboard。 将另一个UILabel和UIImageView添加到控制器,并将它们连接到TodayViewController类。 将高度和宽度的固定约束添加到UIImage,并使用垂直约束添加居中,并在标题UILabel和字幕UILabel中添加底部,顶部,前导,尾随。 之后,我们可以在类的扩展中添加简单的数据获取方法。 将用于从响应中获取URL的响应数据和UIImage数据。 设置图片网址以获取json数据。 创建用于解析和存储响应数据的结构。 添加用于用新数据更新UI的简单方法。 将在viewDidLoad()和widgetPerformUpdate(completionHandler:(@escaping(NCUpdateResult)-> Void))中设置fetchData()。 当扩展名不在屏幕上时,它用于更新视图,更新取决于将在完成处理程序中返回的常量(NCUpdateResult.newData,NCUpdateResult.noData,NCUpdateResult.failed)。 为了隐藏空内容并在收到内容时取消隐藏,我们还可以使用setHasContent(_标志:Bool,forWidgetWithBundleIdentifier bundleID:String),在其中传递确定内容状态的布尔值。 现在我们可以运行该应用程序,并且应该看到类似于此视图的简单视图。 开启网址 如今,扩展程序(窗口小部件)是轻量级的,可以显示基本信息,并且如果用户希望进行更多交互,则将其转移至应用程序是一种好习惯。 对于这种传输,我们通常使用UIApplication.sharedApplication()。openURL(url),但由于扩展名不是应用程序,因此没有可用的UIApplication对象。 代替的是扩展上下文执行相同的操作extensionContext?.openURL(url,completionHandler:((Bool)-> Void)?) […]
这是我第一次以代码风格接触社区,与此同时,我感到有些紧张和兴奋。 我知道我的代码不是完美的,但我也知道为了增长,无论如何,有时您有时需要处于不舒服的情况下。 而且,老实说,只要存在iOS / Swift,我也不知道要进入哪里,我觉得自己的方向是正确的。 当我发现自己从事iOS项目时,有时会遇到从服务器获取一些数据的情况,只有立即获得这些数据后,我才需要点击另一个端点来获取其他东西。 因此,这意味着我必须调用异步函数并在其完成闭包内部,然后才必须嵌套另一个异步调用,是的,我知道那里不存在某些东西。 在我之前的工作中,我曾经作为Node.JS后端开发人员工作,所以我知道嵌套异步调用是一种不好的做法,即使JavaScript世界上的人也将其称为回调地狱。 而且有一个很棒的库叫做async,可以使用它来防止Node.JS / JavaScript中的这种不良做法(当然,这不是唯一的选择,它们有Promise,Generators等)。 但是我不在JavaScript世界中,而是在令人惊叹的iOS世界中! 因此,我几乎没有考虑过如何在Swift中处理这种情况,我发现有一些很棒的框架(如RxSwift或FutureKit)可以帮助我解决问题,但是感觉它们对于我的简单问题来说太高级了。 这就是为什么我创建此博客文章,试图为我的简单问题提供简单的解决方案。 而且我不得不说我的解决方案有偏见,并且与异步是如此相同,只要我的问题得以解决,就可以了吗? 我当时处在不断将我的解决方案复制到其他项目的情况,这就是为什么我决定将其作为图书馆(如Github)提供。 这就是我最终创建这个名为Ax的库的初衷,其最初目的是使我的解决方案可用于其他项目,但我怀疑我不是唯一可以解决Swift中嵌套异步调用问题的人。 如果您对Ax库中的协作感兴趣,请随时与我联系,我计划实现更多功能。 因此,我想谈一谈我如何在Github中创建/上载我的库并使它在cocoapods中可用的过程,但这可能是另一篇文章,如果您有兴趣,请告诉我,我想分享一下。 感谢您的阅读。