Tag: Objective C

快速面试问题–克里希纳

快速面试问题 1) Swift和Objective C之间的差异 Swift是用于iOS,macOS,watchOS和tvOS应用程序开发的新编程语言。 尽管如此,从您在C和Objective-C方面的开发经验中,Swift的许多部分都会为您所熟悉。 Swift提供了自己的所有基本C和Objective-C类型的版本,包括Int表示整数,Doubleand Float表示浮点值,Bool表示布尔值和String表示文本数据。 Swift还提供了三种主要集合类型(数组,集合和字典)的强大版本。 1. Swift引入了在Objective-C中找不到的高级类型,例如元组(值的分组)。您可以使用元组从一个函数返回多个值作为单个复合值。 2. Swift还引入了可选类型,用于处理缺少值的情况。 可选参数说“有一个值,它等于x ”或“根本没有值”。 它们适用于任何类型,而不仅仅是类。 使用可选选项类似于在Objective-C中对指针使用nil 3. Swift是一种类型安全的语言,如果代码的一部分需要一个String,则类型安全可防止您错误地将其传递给Int。同样,类型安全可防止您将可选的String意外地传递给期望的代码一个非可选的字符串。 类型安全性可帮助您在开发过程中尽早发现并修复错误。 4. Swift更易于阅读:不再需要用分号来结束行或括号,Swift中的方法和函数调用在括号内使用行业标准的逗号分隔参数列表。Swift代码更类似于自然英语 5. Swift易于维护: Swift将Objective-C标头(.h)和实现文件(.m)合并为一个代码文件(.swift)。 6. Swift更安全: 7. Swift与内存管理统一:在目标C中,开发人员有责任通过使用低级API(如Core图形)来管理内存处理。 与Swift中一样,即使在底层API中也无需考虑内存管理。 8. Swift需要更少的代码 9. Swift更快 10.Swift Playgrounds鼓励交互式编码: Playgrounds使程序员能够测试新的算法或图形例程,例如5至20行代码,而不必创建整个iPhone应用程序。 2) 类型安全和类型推断: Swift是一种类型安全的语言。 类型安全的语言鼓励您清楚代码可以使用的值的类型。 如果代码的一部分需要一个字符串,则不能错误地将其传递给Int,它会在编译代码时执行类型检查并将所有不匹配的类型标记为错误。 如果您没有指定所需的值类型,则Swift会使用类型推断来得出适当的类型。 当声明具有初始值的常量或变量时,类型推断特别有用。 3) 什么是类型别名 类型别名为现有类型定义备用名称。 您可以使用typealias关键字定义类型别名。 4) 什么是元组: 元组将多个值分组为一个复合值。 元组中的值可以是任何类型,而不必彼此相同。 元组作为函数的返回值特别有用。 尝试检索网页的函数可能会返回(Int,String)元组类型,以描述页面检索的成功或失败。 通过返回具有两个不同值(每个类型均不同)的元组,该函数提供的结果要比仅返回单个类型的单个值要有用得多。 […]

Swift 4和@objc警告

最近,我参与了一个迁移到Swift 4的项目,该项目在其代码库中混合了Swift 3和Objective-C。 因此,在接受来自Xcode 9的邀请以将项目转换/迁移到Swift 4之后,我遇到的第一件事是一个可怕的警告,说: 不建议在Swift 4模式下使用Swift 3 @objc推断。 请解决已弃用的@objc推断警告,启用“使用已弃用的Swift 3 @objc推断”日志记录来测试代码,然后通过将“ VarageSale”的“ Swift 3 @objc推断”构建设置更改为“默认”来禁用推断。目标。 @objc推论? WTF! 好的,这就是我所拥有的,正如您所知,Swift生成的代码仅对其他Swift代码可见/可用。 就像《猿人星球》电影中“猿不杀死猿”的扭曲版本一样。 因此,如果您有一个Swift类,要在Objective-C中使用哪些成员(函数,协议,变量),则需要通过使这些成员具有@objc属性来显式指示这些成员。 这是棘手的部分,在Swift 3中,编译器非常纵情,为某些类成员添加了@objc ,即使您可能不需要它。 但是在Swift 4中,在此问题上限制更大或更宽泛,因此我得到了警告(也可能是您)。 解决方案 1-使用@objc 就像我提到的,您可以使用@objc属性标记函数或属性, @objc会将标记的成员公开给Objective-C。 2-使用@ objcMembers 现在,如果要将所有类成员公开给Objective-C,则可以使用@objcMembers标记该类。 但是使用@objcMembers时要明智,因为由于需要在Swift和Objective-C之间映射的额外代码,它会使二进制文件更大。 参考文献 迁移到Swift 4 @objc推断 限制@objc推断

在xcode中查找非本地化的字符串

我不会在本文中解释如何在iOS中进行本地化。 深入了解基础知识,我们可以通过两种方式对字符串进行本地化。 在代码中,使用NSLocalizedString(“someStringToLocalize”, tableName: nil, bundle: Bundle.main, value: “”, comment: “”) 。 使用情节提要本地化。 通常在代码中添加NSLocalizedString(:方法,然后忘记将其添加到Localizable.strings文件中。此外,我们可能会对情节提要文件进行本地化,并稍后在UI中添加一个新标签,而您会忘记添加本地化的情节提要字符串文件。 为了跟踪这些愚蠢的错误,xcode 7及更高版本提供了一个选项。 在方案编辑器中,查看“选项”选项卡。 在以下屏幕截图中,我启用了“显示非本地化的字符串”。 显示非本地化字符串复选框需要选中,我们可以根据需要选择应用程序语言。 然后编译并运行该应用程序。 我添加了一个字符串作为标签的文本(CalculatorDisplay是一个UILabel): CalculatorDisplay.text = NSLocalizedString(“某些本地化字符串”,注释:“”) 另外,在“Some localized string”文件中未添加字符串“Some localized string” 。 在这种情况下,它将在调试器中引发错误。 情节提要中可本地化的字符串: 对于未在.strings(YOUR_LANGUAGE)文件中添加的情节.strings(YOUR_LANGUAGE)的可本地化字符串,调试器将引发以下错误: 让我们检查第一个错误: 复制GsZ-Y5–7R1 在错误中提到并在整个项目中进行搜索。 它似乎是UIButton的对象ID,可本地化的文本是UIButtons标题。 单击搜索结果,它可能会在情节提要中突出显示该对象。 情节提要字符串文件通常如下所示: 哪里, GsZ-Y5–7R1 是UIButton的对象ID。 现在复制GsZ-Y5–7R1.normalTitle 并将其添加到字符串文件。 “ GsZ-Y5-7R1。 normalTitle” = “Localized title for button”; 做完!!!!! 结论: 本文未介绍如何本地化字符串文件和本地化情节提要文件。 […]

将C ++库与Swift集成-如何构建

在“ Objective-C和Swift —友好相处”一文中,我谈到了如何使用Objective-C在Speculid中将C ++库与Swift集成在一起。 今天,我将讨论在XCode项目中使用C ++库的挑战。 Speculid是一个完全开源的应用程序,主要在Swift中使用最新版本的Xcode(10.1)构建(我将主要而不是仅解释其中的原因)。 借助Speculid,您可以拍摄一张图形并将其构建为完整的应用程序图标或图像集。 因此,这意味着将所有必需的依赖项打包在.App包中。 最初,我考虑将Inkscape和ImageMagick包含在安装中。 但是, Inkscape具有其他依赖项(例如XQuartz)这一事实意味着这太麻烦了。 因此,开罗和librsvg成为显而易见的选择。 将Cairo和librsvg与Swift集成 Speculid的第一个版本需要安装两个软件包:Inkscape和ImageMagick。 每个应用程序将以某种组合方式用于读取,操作和导出SVG,PNG,JPEG或PDF文件。 结果, 需要这些软件包使用户体验笨拙且困难。 但是,由于它们是完整的应用程序,包括这两个程序包也将很麻烦。 这就是为什么我着眼于集成C ++库的原因-特别是其中的两个: Cairo 和 libRSVG 。 Cairo和librsvg由多个软件包使用,是图形和SVG操作软件开发的领先库,尤其是在开源和Linux社区中。 因此,在Speculid v2.0中,我将这些库集成并打包为读取PNG和SVG以及导出PDF和PNG文件的主要方法 。 最重要的是,可以使用以下命令通过HomeBrew在Mac上安装这两个库: brew install cairo librsvg 现在,我们需要确保复制和链接文件。 正确链接和复制C ++库 为了使用C ++库, 我们可以将每段C ++代码作为它们各自的库编译在Speculid中,也可以集成已编译的库。 最初,似乎编译代码是最干净,最有效的方法,除了每个库都有很多要求以及用于编译每个库的特殊标志的事实。 因此,我决定采取另一种方法,并自己使用编译的库。 使用HomeBrew安装库之后,将Cairo和librsvg的目录复制到您的项目文件夹中。 HomeBrew将其应用程序和库存储在: /usr/local/Cellar 因此,例如, 开罗将位于: /usr/local/Cellar/cairo 将其复制到您的项目后,文件需要处于构建阶段的三个位置: 与库链接-所有.dylib文件都需要列出 复制文件-所有.dylib文件都需要复制到Frameworks文件夹 标头 -所有.h文件都需要在Project下列出 之后,您应该会很好。 […]

iOS生物识别本地身份验证

+ Shubaham Jain 实施TouchID身份验证 TouchID / FaceID是基于称为本地身份验证的框架的功能,该功能提供了用于从具有指定安全策略的用户请求身份验证的功能。 在应用程序中使用时,本地身份验证可以处理TouchID / FaceID的所有内容。 它将通过自定义消息提示您进行身份验证,该消息将告诉用户我们为什么需要身份验证,因此用户可以将手指放在主页按钮上。 本地认证框架 LocalAuthentication框架用于在iOS移动应用程序中实现TouchID或FaceID身份验证。touchId身份验证的使用基于本地身份验证框架。 为了实现touchId功能,我们首先在项目中添加了LocalAuthentication框架。 在项目导航中 ->选择目标->进入构建阶段->单击链接二进制文件与库->添加框架 在项目目标中添加LocalAuthentication Framework 现在我们可以编写代码了。 在AppDelegate类中,导入LocalAuthentication.framework 使用以下语句 @import LocalAuthentication; 下一步是要求框架通过评估策略功能可以将touchID应用于特定设备,它将接受两个参数,一个是我们要评估的策略名称,第二个是错误代码。 在App中实现TouchID时,请确定以下几种情况: Case 1 : Device is enabled with Biometric Sensor or not. Case 2 : At Least one Fingerprint is enrolled in device or not to check Biometric sensor availability. LAPolicy有两种类型, […]

条件(if,if..else,if..else_if…else,切换情况)

顾名思义,条件用于在执行程序或代码之前验证特定事物。 当您检查条件时,可能存在对或错的可能性。 IF条件:如果条件为true,请执行任务,否则为空。 假设我们想要一种具有一个字符串类型参数的方法。 如果传入的参数值为Sunday,则此方法将打印Holiday(假日),否则不打印任何内容。 程序: -(void)CheckForHoliday:(NSString *)strDayName { 如果([strDayName isEqualToString:@“周日”]){ NSLog(@“假日”); } } 否则:如果条件为真,执行任务,否则执行其他操作。 假设我们想要一种具有一个字符串类型参数的方法。 如果参数中的值是Sunday,则此方法将打印Holiday(假日),否则打印Not Holiday(假日)。 程序: -(void)CheckForHoliday:(NSString *)strDayName { 如果([strDayName isEqualToString:@“周日”]){ NSLog(@“假日”); } } 其他 { NSLog(@“不是假期”); } IF ELSE_IF ELSE:检查多个条件。 意味着如果第一个条件为true则执行任务,否则,请检查第二个条件为true,然后执行第二个任务,否则执行其他操作。 您可以检查许多条件,意味着您可以编写许多else_if条件。 假设我们想要一种具有一个字符串类型参数的方法。 如果输入的值是周日,则此方法将打印“全天假期”,如果输入的值是周六,则将打印“半天假期”,否则打印“非假期”。 程序: -(void)CheckForHoliday:(NSString *)strDayName { 如果([strDayName isEqualToString:@“周日”]){ NSLog(@“全天假期”); } 否则,如果([strDayName isEqualToString:@“ Saturday”]){ NSLog(@“半天假期”); } 其他 { NSLog(@“不是假期”); } […]

iOS面试问题第2部分:ObjectiveC🖥

在前面的第1部分“差异化”中,我们讨论了许多术语,这些术语用于更好地说明情况。 在这一部分中,我们将重点介绍一些特定的Objective-C和iOS应用开发概念。 @synchronized指令是在Objective-C代码中动态创建互斥锁的便捷方法。 @synchronized指令执行任何其他互斥锁将执行的操作- 防止不同的线程同时获取同一锁。 官方Apple文件 选择器是用于选择要为对象执行的方法的名称,或者是唯一的标识符,用于在编译源代码时替换该名称。 选择器本身不会执行任何操作。 它仅标识一种方法。 使选择器方法名称不同于纯字符串的唯一事情是编译器确保选择器是唯一的 详细信息:Apple Doc 捆绑软件是用于在Mac OS X上打包软件的结构。应用程序,框架和插件是所有不同种类的捆绑软件。 如果您愿意,捆绑软件可能包含可执行代码,资源,头文件和其他内容(包括其他捆绑软件)。 捆绑软件以具有定义结构的目录树的形式实现。 应用程序,框架和插件在树的结构上各有不同。 但是,对于Finder,捆绑包看起来像单个文件。 主捆绑包只是正在运行的应用程序的捆绑包。 因此,例如,Apple邮件程序的主要捆绑包是/Applications/Mail.app。 苹果开发者文档:NSBundle和mainBundle “ id”是Objective-C中对象标识符的数据类型 ,它可以用于任何类型的对象,无论其本机或原始类型是什么类。 “ id”是所有对象的最终超类型。 详细实施。 借助UIApplicationMain函数将控件移交给UIKit框架。 它创建或启动了我们应用程序的几个核心对象。 它从可用的Storyboard加载UI 。 它允许自定义代码(AppDelegate)进行一些初始设置 。 它还通过将应用程序运行循环设置为运动来启动应用程序 。 我们需要为UIAplicationMain函数提供Storyboard文件和自定义初始化代码。 它是iOS应用程序的心脏,使系统与应用程序的其他对象之间的交互变得容易。 使用NSUserDefaults类,可以保存与应用程序或用户数据有关的设置和属性 。 例如,您可以保存用户设置的配置文件图像或应用程序的默认配色方案。 对象将保存在iOS的“默认系统”中 。 iOS默认系统在您应用中的所有代码中都可用,并且保存到默认系统的所有数据将在应用程序会话中保留。 这意味着,即使用户关闭了您的应用程序或重新启动了手机,下一次打开该应用程序时,保存的数据仍然可用! 使用NSUserDefaults,可以保存以下类类型的对象: NSData,NSString,NSNumber,NSDate,NSArray,NSDictionary 如果要存储任何其他类型的对象,例如UIImage,则通常需要将其归档或包装在NSData,NSNumber或NSString的实例中。 苹果开发人员文档 根据更新的 Apple文档 ,大小为4KB。 对于常规的远程通知,最大大小为4KB(4096字节) 对于互联网协议语音(VoIP)通知,最大大小为5KB(5120字节)。 注意:如果您使用旧版APNs二进制接口发送通知而不是HTTP […]

iOS中静态库的自定义Xcode模板

在深入了解如何使用默认模板之前,让我们介绍一下TemplateInfo.plist文件中的一些重要属性。 种类:一种字符串类型,用于标识模板类型,例如,您将Xcode.Xcode3.ProjectTemplateUnitKind用于项目模板,并将Xcode.IDEFoundation.TextSubstitutionFileTemplateKind文件模板使用。 标识符:模板的唯一标识符。 以后将用于唯一地标识模板或从祖先模板继承属性。 混凝土:布尔型。 为项目选择模板时,Xcode必须设置为YES才能显示模板。 如果丢失或设置为NO,Xcode会将模板视为其他模板可以继承的抽象基础模板。 祖先:一种数组类型,用于保存标识符上的集合,用于从其他模板继承。 复制默认静态模板 以下路径是默认模板的存储位置: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates。 如果您的Xcode应用程序名称不是Xcode,则别忘了用路径中的适当名称替换Xcode.app。 从上面的路径导航到Project Templates / iOS / Framework&Library并将Cocoa Touch Static Library.xctemplate文件夹的内容复制到您的StaticFramework.xctemplate文件夹。 现在您可能想知道其中一些文件的含义,让我们看一下。 ___PACKAGENAMEASIDENTIFIER___: Objc和Swift文件是基于所选语言创建项目时获得的默认文件。 对于Swift静态库,您需要获得___ PACKAGENAMEASIDENTIFIER ___。swift 对于Objc,您将获得.h和.m文件。 宏用作文件名,因此在创建项目时将其替换。 有关使用哪个宏的更多信息,请访问此处。 TemplateIcon.png:这些是可选的png文件,用于为您的自定义模板增添趣味,使其更易于识别。 设置标识符 如前所述,重要的是模板的标识符必须唯一。 Apple提供的默认模板使用com.apple.dt.unit前缀,因此它们提供的每个模板都有它。 对于我们的自定义模板,我们必须提供自己的标识符前缀。 我决定去com.personalLibrary.dt.unit,但可以随意使用自己的。 设置swiftlint 将以下字典作为数组项粘贴到TemplateInfo.plist的Targets数组中第一项下的BuildPhases中,以设置swiftlint。 Class ShellScript 名称 运行SwiftLint ShellPath / bin / sh ShellScript $(git rev-parse –show-toplevel)/ Tools / SwiftLint / […]

我的开放源代码项目的Xcode项目结构

最近,我决定将一些自定义的iOS控件开源。 因此,我启动了Xcode,选择“ Create a new Xcode project ”,然后陷入困境……我应该选择哪个项目模板? 我必须将自定义控件设置为Cocoa Touch Framework,但与此同时,我还需要一个示例应用程序进行测试,以及在发布到Github之后展示我的自定义控件。 显然,我们可以使用CocoaPods命令: pod lib create生成具有适当结构的Xcode项目,并立即开始进行处理。 但是,我希望对项目结构具有更大的灵活性和更多的控制权,因此我决定手动设置自己的项目。 经过一番研究和反复试验,我得出了一个适合任何开源项目的项目结构。 因此,我想与任何有兴趣的人分享这一点,希望这可以为计划开始其第一个开源项目的其他开发人员提供一个良好的起点。 😃 让我们开始创建所需的Xcode项目。 第一个项目将是包含所有开源项目源代码的项目。 确保选择“ Cocoa Touch Framework ”作为所需项目模板。 出于演示目的,让我们将项目命名为“ MyOpenSource ”。 为开源项目源代码完成项目创建后,您将需要为示例应用程序创建另一个项目。 这次选择“ 单一视图应用程序 ”作为项目模板,并将其命名为“ MyOpenSourceExample ” 现在,您应该能够看到已经创建了两个Xcode项目。 双击MyOpenSourceExample.xcodeproj以启动示例项目,然后将MyOpenSource.xcodeproj从finder中拖到示例项目中,如下面的屏幕快照所示。 Xcode将提示您将示例项目保存在新的工作区中。 什么是工作区? 根据Apple文档: 工作区是将项目和其他文档分组的Xcode文档,因此您可以一起使用它们。 点击“ 保存 ”继续。 将工作区命名为MyOpenSourceExample并将其保存在根文件夹中。 现在,您可以关闭示例项目并启动刚刚保存的工作区。 注意,Xcode现在在项目导航器中同时显示MyOpenSource和MyOpenSourceExample 。 为了使MyOpenSourceExample能够访问MyOpenSource的代码,您必须将MyOpenSource框架链接到示例项目。 在项目导航器中选择MyOpenSourceExample ,然后打开“ Build Phases ”选项卡。 展开“ […]

Xcode项目中的多目标用法

有多种方法可以向用户展示应用程序的特殊功能。 向用户展示特殊功能的一种方式是拥有应用的多个版本(如Lite和Pro)。 在这种情况下,Xcode中的目标扮演主要角色。 实现此要求的另一个不好的方法是每个应用程序都有不同的项目。 但是,对一个项目有多个目标可能会生成多个版本的应用程序。 目标是通过在Xcode中运行“ build”创建的最终产品。 它可能是一个应用程序,一个框架,一个静态库或一个单元测试包。 无论是什么,它通常对应于“已建产品”文件夹中的单个项目。 在Xcode中,“文件”->“新建”->“项目”->“单视图应用程序”将在下图中填写必填字段后创建一个简单项目。 现在,您的项目导航器如下所示。 您可以在Storyboard和AppDelegate / ViewController中进行任何基本的UI和代码更改。 在此“ SimpleApp”中,有一个UIImageView作为ViewController的视图的背景图像,还有一个UILabel,其中包含用于区分应用程序目标的文本,如下所示。 现在,单击ProjectName(SimpleApp),您可以看到“目标”部分。 右键单击要在其中添加特殊功能的目标。 点击“复制”。 您将看到以下警报。 只需单击“仅重复”。 它将复制所选目标。 注意: 存在此对话框的原因是为您提供一种使用两个不同目标在单个项目中创建应用程序的iPhone和iPad版本的简便方法。 如果这是您要执行的操作,则可以选择“复制并转换到iPad”。 但是,在走这条路之前,您应该考虑使应用通用,而不是使应用的iPhone和iPad版本分开。 只需点击“返回”键,通过选择新的目标进行重命名即可进一步使用。 重命名两个目标后,“目标”部分将如下所示。 要解决的另一个命名问题是目标的方案。 方案定义了当您按下“ Build”,“ Test”,“ Profile”等时会发生什么。通常,每个目标都有至少一个方案。 我们必须通过单击上方菜单中的“管理方案”来重命名方案。 我们只需按如下所示的“ Return”键即可重命名方案。 重命名过程后,单击“关闭”。 在以上所有过程中,Xcode将生成一个新的plist文件并将其添加到您的项目导航器中。 这些plist文件名与目标服务器的名称不一致。 因此,我们必须使用相同的“返回”键方法来重命名它们。 重命名后,我们必须在Xcode Project设置中设置正确的plist文件。 还要根据需要更改包的显示名称。 现在,您可以使用多个目标了。 在单个代码库上运行时,我们需要某种编程方式来确定当前正在运行的产品(目标),以便您可以适当地做出这样的决定。这是Preprocessor Macro发挥作用的地方。 每个目标的Plist都有一些预处理器宏来标识您的工作环境。 我们必须设置一个自定义宏才能在这种情况下使用。 要添加自定义宏,请单击ProjectName(SimpleApp)->要添加宏的特定目标->构建设置。 然后按单词“ Macro”过滤。 然后,您将找到“预处理器宏”部分。 您会在这里看到Debug版本已经有了一个名为DEBUG = 1的宏。 […]