iOS 开发

iOS 常用 XCode, Swift3, UITableView, cocatouch, 一起创建 iPhone, iPad 和 Macbook应用

本地化macOS应用程序。

https://appfillip.com/important-tips-for-app-store-localization-help-to-increase-app-ranking-globally/ 世界上有太多语言(超过6500种)。 但是,地球上的大多数人口(约60–70%)仅使用其中的50–60。 对我们有利,我们不需要将我们的应用程序转换为所有6500! 实际上,并非每个应用程序都需要本地化,它取决于客户群(大多数用户使用哪种语言)以及该应用程序的受欢迎程度。 此外,如果他们在理解内容时遇到困难,可以将本地化视为可以鼓励用户使用该应用程序的功能。 我一直在寻找一个有助于发展的项目,却发现了一个名为IINA的项目。 伊娜 IINA是适用于macOS的现代视频播放器。 它具有本机播放器(快速时间)不具备的许多功能,例如制作播放列表,添加字幕,缩略图预览等。 同时,它具有漂亮的用户界面,与“快速时间”非常相似。 IINA仍在发展中。 我打开了一个问题页面,找到了一些尚待解决的错误,然后发现要求对多种语言进行本地化。 我在应用程序本地化方面没有任何经验,因此认为这是学习如何进行的好机会。 在不同的网站上有很多关于如何本地化iOS / macOS应用程序的教程。 他们非常简单,并通过分步说明详细解释了所有内容。 本质上,本地化是通过将强类型文本( UILabel , UIView等中的所有文本)移动到单独的文件中来完成的。 所有本地化的字符串都存储在扩展名为.string文件中。 内容很简单,由键值对组成。 在我刚开始的时候,INIA已经针对多种语言进行了本地化(对于某些语言仍然不完全适用)。 但是,如果您正在处理的项目没有任何本地化,则可以从添加一种新语言开始:在项目导航器的“信息”选项卡中有一个“本地化”部分。 只需单击+按钮即可添加新语言。 如果要将本地化添加到新项目中,我建议使用本教程。 由于已经为该项目设置了本地化,所以我决定检查俄罗斯和乌克兰的本地化。 要使用特定的本地化环境运行应用程序(更改应用程序语言),您需要在xCode中编辑方案,或者更改系统语言(老实说是个坏主意)。 导航到“产品”->“方案”->“编辑方案”,或单击活动方案(位于旁边的左上角 按住alt键的同时点击“ stop按钮)。 在这里,您可以选择一种语言,该语言将是使用xCode运行该应用程序时的默认语言。 因此,我以两种语言运行了IINA,发现它并没有完全本地化为乌克兰语。 我首先过滤所有文件以仅获取用于乌克兰语本地化的.string文件(例如uk.lproj / PrefGeneralViewController.strings或iina / uk.lproj / PrefCodecViewController.strings)。 这些文件与Localize.string文件不同,因为它们没有键的明确名称,而是包含UI元素的ObjectID (例如“ hWC-KJ-FuC.title”)。 因此,在Localize.string文件中添加缺少的翻译很容易。 为其他文件添加翻译要困难一些,因为几次我遇到缺少的ObjectID ,这意味着具有这些ID的对象将无法翻译。 为了修复它,我为相同的ViewController打开了本地化文件,并从那里复制了缺少的ObjectID 。 现在,我唯一需要做的就是翻译它们。 完成这些操作后,我再次运行该应用程序,并注意到整个菜单选项卡仍未翻译。 那是因为我只向缺少的.string文件添加了缺少的翻译。 很明显,该菜单选项卡的翻译文件不存在。 要为该视图添加本地化文件,我为PrefUtilsViewController打开了一个xib文件,并在“检查器”菜单中选中了缺少语言的复选框。 […]

iOS-在Swift中进行重构:标识符!

更新(2018年12月): 向Mark Moeykens大喊大叫,他制作了一段受本文启发的视频:https://www.youtube.com/watch?v=6Om91KRQCiM&feature=youtu.be。 他在自己的YouTube频道上有一些有关iOS开发的精彩内容,如果你们喜欢这个,那么您绝对应该检查一下该频道。 在制作iOS应用程序时,我们需要一些标识符,例如可重用的UITableViewCells或UICollectionViewCells ,segues, UIStoryboards , UIViewControllers等。我们如何管理所有这些在源代码中只是字符串的标识符? 作为一个初学者(一年前),我的方法是简单地跟踪UI组件并将标识符复制并粘贴到我需要的位置。 但是,我很快意识到,随着应用程序的扩展,这种方法会使我的生活变得更加艰难,而且我还有更多的选择, UIViewControllers , UIStoryboards等。如果您在团队中工作,那么我强烈建议重构标识符! 1. UITableViewCells和UICollectionViewCells标识符: 本部分介绍了可重用的单元格,该单元格需要一个标识符来重用并将其注册到相应的容器视图,即UITableView或UICollectionView 。 当您创建一个新的自定义类时(我以UICollectionViewCell为例,它应该对UITableViewCell应用相同的方式),它看起来像这样: 现在,我们更新自定义单元格类以包含静态常量。 该名称具有名称标识符并存储我们的标识符,在本例中为MyCell 。 该行看起来像这样…… static let identifier = “MyCell” 。 但是,如果它与类名相同,那么我认为我们可以做得更好。 我们可以使用描述性的String初始值设定项来获取类的名称…… static let identifier = String(describing: MyCell.self) 。 如果我们使每个自定义单元格的标识符与类名相同,那么我们可以通过扩展UICollectionViewCell和UITableViewCell类来进一步泛化它! 我知道命名单元标识符与类名称相同可能会有例外。 这是我针对该异常的解决方案,而不是使标识符成为static var而不是使其成为static var class var ,这为我们提供了在自定义单元格类中覆盖identifier变量并分配自定义String的优势。 这增加了一个额外的步骤,但是我们仍然享受自动完成的好处。 更新后的代码如下所示: 此方法使源代码中没有字符串,可以帮助开发人员利用自动完成功能,并且易于维护和更新。 下一步:Segue标识符。 2. Segue标识符 这种类型的标识符非常凌乱,并且随着项目的扩大而变得非常混乱。 将标识符从相同的UIViewController重复到不同的UIViewControllers是非常容易的,尤其是当您在更大的团队中工作时。 此外,四处查看您的源代码并检查我们是否已经使用了标识符很不方便。 […]

不起眼的TableView

我最近一直在考虑表视图。 表视图和集合视图已成为为许多类型的应用程序(尤其是内容驱动的应用程序)构建UI的默认方法。 但是,随着我们的表格视图变得越来越复杂,很难测试它们是否显示了正确的内容。 我认为创建可测试表的许多困难源于一种模式,在这种模式下,我们具有描述应用程序域的模型对象,然后尝试将其显示在表中。 尽管这些模型完美地描述了应用程序域的特定问题,但它们可能无法完全描述我们要在特定表单元格中显示的内容。 让我们看一个例子,然后看看如何改进。 我将使用表视图,因为它稍微简单一些,但是您也可以将这些技术应用于集合视图。 您的应用程序中可能有一些模型对象,它们描述了您的应用程序所关注的领域。 例如,如果您制作一个社交应用程序,则可能具有User , Friend和Message对象。 您可能是通过从api获得的Json表示形式创建对象来获得这些对象的,并在整个应用程序中使用它们来对应用程序的域进行建模。 在我们的示例中,我们可以想象一个音乐流应用程序,其中有一个特定艺术家的屏幕,其中显示了可以为该艺术家播放的所有曲目。 我们可能已经有一个域对象Track ,因此我们可以获取艺术家的所有Track ,并在表中显示它们: struct Track { let id:字符串 让标题:字符串 持续时间:双倍 让streamURL:URL } TrackCell类:UITableViewCell { func configure(track:Track){ //用轨道配置单元格 } } 好吧,还不错! 当用户打开艺术家页面时,我们将从MusicAPI获取Track ,并将其显示在表格中。 然后,该单元格可以显示曲目标题和持续时间,并且当用户按下播放时,我们可以开始流式传输。 通过此设置,我们直接从域模型( Track )转到UITableViewCell 。 但是,当我们必须在单元格中显示Track对象未描述的信息时,该策略就会Track 。 假设我们有一个新的要求–我们的应用程序现在可以下载轨道,并且需要在列表中显示每个轨道的下载状态。 我们的用户界面将如下所示。 在此示例中,已下载了第三首曲目,而其他未下载。 不幸的是,我们的Track模型现在无法完全描述TrackTableViewCell需要了解的所有内容。 我们是从MusicAPI获取Track的,但是我们需要参考DownloadsManager来确定是否在本地下载了轨道。 也许我们可以在创建单元格并将其分别传递给下载状态时调出给DownloadsManager ,甚至可以从单元格内部调用它,如下所示: TrackCell类:UITableViewCell { func configure(track:Track){ //用轨道配置单元格 downloadIcon.showDownloaded […]

类型安全的用户默认值

以前,我们只是通过使用字符串键将数据存储在UserDefaults中。 每当我们需要照顾数据类型时 。 setBool(_:forKey:_)和co是解决方案。 可是等等?! 如果您需要获取给定密钥的值怎么办? 您需要遍历代码库并检查在那里存储了什么类型:它是Int吗? 或数组。 这是浪费时间,甚至如此危险:您可以在此处存储Bool,其他人可以存储任何其他类型。 但是您可以确定这是一个布尔型,并且解开nil可选项可能会导致崩溃。 我为什么过去说话? 因为自Swift 3推出以来,一个不错的解决方案就可以实现。 setValue(_:for key:_)方法现在接受Any值,不再接受AnyObject :这使事情变得更加容易。 让我们看看如何: 使用泛型,我们可以定义一个简单的DefaultKey结构,该结构包含要存储的类型和键名信息。 这样,您可以轻松地在常量文件中定义DefaultKey集 完成此操作后,您可以轻松地为UserDefaults构建通用扩展,如下所示 这个小界面可让您获取或设置存储的值,而无需关心值的类型 如果您尝试为LaunchesKey存储字符串会怎样? 实际上,此界面会自动提醒您应为定义的键存储什么类型。 检查我的Github存储库上的完整代码:https://github.com/dalu93/Defaults 更新:使用Swift 4现在可以实现通用下标。 有关更多信息,请查看GitHub上的develop分支。

升级项目以支持Xcode 10和Swift 4.2

将项目升级到Xcode 10.1和Swift 4.2可能会导致错误和警告,因为Swift 4.2已重命名了常量,函数和类型。 当您在Xcode 10.1中打开Xcode 9项目时,您会在Xcode 10中看到一条警告消息,要求进行Swift转换。 除了使用Swift转换器,我们还可以手动进行转换: 首先,您需要在项目目标的“ 构建”设置中更改Swift语言版本。 默认情况下,Xcode 10支持Swift 4.2版本。 Xcode 10支持以下Swift版本:v3,v4,v4.2 我们可以看到一条警告消息来更新项目设置,单击“ 执行更改” 升级到Swift 4.2: 框架更新 套料 1.类型 2.常数 3.功能 嵌套类型: UIApplicationState: UIApplicationState转换为嵌套类型,如下所示—状态嵌套在UIApplication中。 UITabBarItemPositioning: ItemPositioning嵌套在UITabBar中。 嵌套常量: 通知:通知名称嵌套在UIApplicaiton中。 UIFloatingRange: UIFloatRangeZero和UIFloatRangeInfinite嵌套在UIFloatRange中。 嵌套函数: 插图和图像: UIEdgeInsetsInsetRect和UIImagePNGRepresentation嵌套在实例方法内部。 字符串转换: CGPoint,CGSize,CGRect等使用JSONEncoder进行编码,并且可以使用JSONDecoder进行解码。 注意:—引用自WWDC 2018 会议202 。 以下是其他错误: “ UIApplicationLaunchOptionsKey”已重命名为“ UIApplication.LaunchOptionsKey” “ UIApplicationOpenURLOptionsKey”已重命名为“ UIApplication.OpenURLOptionsKey” UIViewController的实例方法addChildViewController()已重命名为addChild() UIViewController的实例方法didMove(toParentViewController:)已重命名为didMove(toParent:) “ UIControlState”已重命名为“ UIControl.State” […]

自动关闭,作为参数的关闭,尾随关闭和Swift开罗

您可能要略过,这只是一个介绍。 我一直在与一个我要在开罗建立的新社区进行在线课程:Cairo-Swift,并且我们一直在进行在线活动,以阅读一个开源项目并了解其来龙去脉,所以每个人可以从该项目及其构建过程中学到一些东西。 该建议是由我们的一位成员提出的,因为她受到这次演讲的启发:https://www.youtube.com/watch?v = mW_xKGUKLpk 我自己没想到它会这么有用,我真的很感谢迄今为止的进展以及我们每周要经过的信息和搜索量,而这个博客确实是其中的一项特权! 我自己选择了要进行的第一个项目,因为我们是聚会,所以我选择了trySwift的聚会应用,这是一个很好的灵感,也许我们迟早可以为我们的社区构建类似的东西! 通过代码,我们发现了重复的代码,我建议我们可以通过使用泛型来将其修改为更好的版本,我最近一直在与他们一起玩,并且有点像锤子一样使用它,所以让我们看看它在哪里走! 基本代码是: func showAbout(){让aboutViewController = AboutTableViewController()performSegue(withIdentifier:moreDetailSegue,发件人:aboutViewController)} webViewController = WebDisplayViewController()webViewController.url = URL(字符串:conference.codeOfConductURL)! webViewController.displayTitle =“行为准则”。localized()performSegue(withIdentifier:moreDetailSegue,发送者:webViewController)} func showOrganizers(){让organizerViewController = OrganizersTableViewController()performSegue(withIdentifier:moreDetailSegue,发送者:organizerViewController)} func showLibraries() {let path = Bundle.main.path(forResource:“ Pods-trySwift-acknowledgements”,ofType:“ plist”)let ConfirmationesViewController = AcknowListViewController(acknowledgementsPlistPath:path)ConfirmationesViewController.edgesForExtendedLayout = [] confirmmentesViewController.headerText =“我们❤️打开源代码软件”。localized()performSegue(withIdentifier:moreDetailSegue,发送者:confirmationesViewController)} 你能发现吗? 这是使用特定控制器和String ID执行segue的重复代码,因此让我们将其转换为通用函数吗? func navigationTo (_ withType:T.Type,id:String =“ moreDetailSegue”){ performSegue(withIdentifier:id,发件人:T()) } //称呼它 navigationTo(UIViewController.self) 最初,我尝试使用T.initialize()碰壁,这是通过Xcode自动完成来完成的,而.init()甚至simple()根本不显示,花了大约15分钟的时间来尝试找出问题所在用我的代码,我去看了关于该功能的苹果文档,但我完全不了解。 只是一个奇怪的函数,不会像我想的那样初始化! 上面的函数将摆脱上面的几个函数,并保留最后两个,那么我们如何改进呢? […]

后台音频播放器同步控制中心

在本教程中,您将创建一个能够在后台模式下播放音频并与Control Center中的音乐控件同步的播放器。 特征: 播放声音文件。 使声音在后台模式下继续播放。 从控制中心控制音频。 处理完成。 处理中断。 处理路线更改。 如果您遇到任何问题,可以在这里下载完整的源代码项目,然后再使用每个功能。 1.播放声音文件 要播放声音文件,您需要初始化播放器。 阅读以下文章以了解有关AVAudioPlayer的信息: AVAudioPlayer 音频播放器,可播放文件或内存中的音频数据。 将以下块代码添加到视图控制器中以初始化播放器: 您还需要准备一个mp3文件进行测试。 要播放mp3文件,请按如下所示调用play()方法: player.play() 现在,您可以从导入的文件中听到声音。 但是,当您按“主页”按钮将应用程序移至背景模式时,声音已被静音。 因此,我们需要让它在下一指南中继续在后台模式下播放。 2.使声音在后台模式下继续播放 要使声音在后台模式下继续播放,您需要阅读以下文章: AVAudioSession 与系统通信的中介对象,您打算如何在应用程序中使用音频。 启用背景音频 配置您的应用,使其在进入后台时继续播放音频。 如下替换AppDelegate.swift文件的application(_:didFinishLaunchingWithOptions:)方法以配置音频会话: 现在运行该应用程序,播放声音,然后按“主页”按钮将应用程序移至背景模式,并检查声音是否仍继续播放。 3.从控制中心控制音频 阅读以下文章,了解如何从“控制中心”和“ iOS锁定”屏幕控制背景音频: 控制背景音频 支持从控制中心和iOS锁定屏幕控制背景音频。 将以下方法添加到视图控制器中,并从viewDidLoad()方法调用setupRemoteTransportControls() , setupNowPlaying() viewDidLoad()方法: 现在运行该应用程序,打开“控制中心”并进行检查。 4.处理完比赛 音频播放器播放完毕后,您需要更新nowPlayingInfo和UI。 要接收此事件,您需要实现AVAudioPlayerDelegate协议的audioPlayerDidFinishPlaying(_:successfully :)方法,并如下更新setUpPlayer()方法: 运行该应用程序并进行检查。 5.处理中断 在后台模式下播放时,如果打来电话,则声音会静音,但在挂断电话时,声音不会自动继续播放。 因此,我们需要阅读以下文章来处理这些中断事件: 响应音频会话中断 直接观察音频会话通知,以确保您的应用响应中断。 在中断结束时添加以下代码片段以自动播放: 现在运行该应用程序并进行测试。 6.处理路线变更 现在,当您将耳机插入手机时,声音将在耳机上发出。 但是当您拔下耳机插头时,声音会自动继续在内置扬声器上播放。 […]

为什么要投资Ios应用开发以增强业务?

为什么要投资Ios应用开发以增强业务? 随着世界变得无处不在,企业正在利用移动技术将其业务提升到一个新的水平。 鉴于Ios市场的普及和发展,iPhone和其他Apple设备对应用程序开发的需求急剧上升。 作为一个有远见的企业家,您肯定想利用Ios应用程序开发服务的优势,以便在这个竞争激烈的时代中生存和维持下去。 随着iOS的新版本和高级版本的发布,企业一直在寻找新的机会来为自己创造利基。 实际上,新的API,增强的UI和框架已成为iOS开发人员中的热门话题,他们希望为用户提供更好的解决方案。 随着每一个新版本的框架和应用程序的发布,iOS开发人员和企业都得到了应有的认可。 让我们快速看一下其中的一些模式: ‘Swift’-开发人员首选的编程语言: 目前,iOS应用程序开发市场受到一种新的编程语言(即“ swift”)的统治。 除了iPhone和iPad,该技术还与Apple Watch和Apple TV兼容。 它是一种多范例的编译语言,也与Linux兼容。 此外,新版本的swift即swift 2已被设计为更具兼容性和用户友好性,从而使开发人员能够更加专注于应用程序开发而不是技术。 2.免费版和付费版应用程序:当前的应用程序开发生态系统发现iOS更加关注付费版应用程序,而Android则专注于免费版应用程序。 现在,随着趋势的逆转,免费iOS应用程序的需求和下载量肯定会增长25%。 3,基于云的应用程序 众所周知,为基于云的应用程序铺平道路的云技术为开发人员以及最终用户都带来了无数的好处。 实际上,由于这些应用具有多小工具同步功能,因此它们肯定会在市场上保持主导地位。 换句话说,随着对手持设备的依赖性不断提高,移动商务市场正在稳步增长。 因此,作为佛罗里达州的企业家,如果您希望利用应用程序开发的好处,那么现在是时候去雇用拥有信誉的,可靠的公司的服务,该公司在Fl提供Ios应用程序开发 。 这样做可以使您在竞争者中遥遥领先,同时可以成倍地提升和提高业务利润。

对值类型使用领域

在本文中,我想探讨如何使用基于struct的模型和类型安全的查询在Realm之上构建数据持久层 。 如果您在过去的两年中一直被碳酸盐岩所冻结,那么Realm是一种从头开始为移动设备构建的数据库技术,它实际上是Apple世界中Core Data的替代品。 与Core Data一样,Realm需要子类化来定义模型对象,并且仅允许在创建它们的线程上使用它们。 这些要求和其他要求通常会增加复杂性,并且通常会在应用程序中的任何地方增加与Realm的耦合。 这就是为什么将这些框架视为实现细节并将它们抽象到持久层下通常是一个好主意的原因。 楷模 例如,让我们创建一个持久层,以将漫画书中的超级英雄角色与其发布者一起存储。 我们可以使用几个结构来定义我们的模型: 公共结构发布者{ 公共租用标识符:Int 公开名称:String } 公共结构字符{ 公共租用标识符:Int 公开名称:String public let realName:字符串 公开让发布者:发布者? } 尽管我们仅将它们仅用作传输机制并将它们对应用程序的其余部分隐藏,但我们仍然需要创建相应的RealmSwift.Object子类。 最后一个类 PublisherObject:对象{ 动态var标识符= 0 动态var名称=“” 覆盖静态函数 primaryKey()->字符串? { 返回 “标识符” } } 最终课程 CharacterObject:对象{ 动态var标识符= 0 动态var名称=“” 动态var realName =“” 动态var发布者:PublisherObject? 覆盖静态函数 primaryKey()->字符串? { 返回 “标识符” } } 制图 我们需要一种机制来将基于struct的模型转换为其相应的Realm对象。 让我们为此定义一个协议: […]