关于iOS开发:如何关闭ios模拟器

抉择文件菜单->抉择敞开窗口或者按住[Command + W ]。它就会敞开在顶层的模拟器。

January 31, 2022 · 1 min · jiezi

关于iOS开发:iOS-新版本证书申请及打包流程2021版

iOS 打包流程配置证书App证书申请地址 旧版本的 App 创立和证书配置流程能够参考 iOS证书(.p12)和形容文件(.mobileprovision)申请 如果你的 Xcode 版本大于11须要留神在证书申请时抉择 Apple Distribution 和 Apple Development 这两种证书类型,不然可能会因为 Xcode 构建模式不一样导致各种问题 Xcode11 曾经简化了证书申请流程,所有的证书申请都能够在 Xcode 内实现,根本步骤如下 在 Xcode 内登录开发者账号在账户的右下角找到 Manage Certificates,点击左下角向下箭头抉择你想要配置的证书。开发证书抉择 Apple Development,生产抉择 Apple Distribution, Xcode 会主动同步证书到 App 治理后台上,而后你只须要登录 https://developer.apple.com/a... 来依据不同的证书创立形容文件即可回到我的项目中找到 TARGETS -> Build Settings -> Signing -> Code Signing Identity -> 配置相干证书接着配置前面的 Development Team、Provisioning Profile 字段打包时须要更新 Build 版本号。目前我采纳的规定是日期字符串格局,每次上传到 Apple Connect 时须要先更改这个字段

December 2, 2021 · 1 min · jiezi

关于iOS开发:KVO原理分析

介绍KVO全称KeyValueObserving,是苹果提供的一套事件告诉机制。容许对象监听另一个对象特定属性的扭转,并在扭转时接管到事件。因为KVO的实现机制,所以对属性才会产生作用,个别继承自NSObject的对象都默认反对KVO。 KVO和NSNotificationCenter都是iOS中观察者模式的一种实现。区别在于,绝对于被观察者和观察者之间的关系,KVO是一对一的,而不一对多的。KVO对被监听对象无侵入性,不须要手动批改其外部代码即可实现监听。 KVO能够监听单个属性的变动,也能够监听汇合对象的变动。通过KVC的mutableArrayValueForKey:等办法取得代理对象,当代理对象的外部对象产生扭转时,会回调KVO监听的办法。汇合对象蕴含NSArray和NSSet。 应用应用KVO分为三个步骤 通过addObserver:forKeyPath:options:context:办法注册观察者,观察者能够接管keyPath属性的变动事件回调。在观察者中实现observeValueForKeyPath:ofObject:change:context:办法,当keyPath属性产生扭转后,KVO会回调这个办法来告诉观察者。当观察者不须要监听时,能够调用removeObserver:forKeyPath:办法将KVO移除。须要留神的是,调用removeObserver须要在观察者隐没之前,否则会导致Crash。注册在注册观察者时,能够传入options参数,参数是一个枚举类型。如果传入NSKeyValueObservingOptionNew和NSKeyValueObservingOptionOld示意接管新值和旧值,默认为只接管新值。如果想在注册观察者后,立刻接管一次回调,则能够退出NSKeyValueObservingOptionInitial枚举。 还能够通过办法context传入任意类型的对象,在接管音讯回调的代码中能够接管到这个对象,是KVO中的一种传值形式。 在调用addObserver办法后,KVO并不会对观察者进行强援用。所以须要留神观察者的生命周期,否则会导致观察者被开释带来的Crash。 监听观察者须要实现observeValueForKeyPath:ofObject:change:context:办法,当KVO事件到来时会调用这个办法,如果没有实现会导致Crash。change字典中寄存KVO属性相干的值,依据options时传入的枚举来返回。枚举会对应相应key来从字典中取出值,例如有NSKeyValueChangeOldKey字段,存储扭转之前的旧值。 change中还有NSKeyValueChangeKindKey字段,和NSKeyValueChangeOldKey是平级的关系,来提供本次更改的信息,对应NSKeyValueChange枚举类型的value。例如被察看属性产生扭转时,字段为NSKeyValueChangeSetting。 如果被察看对象是汇合对象,在NSKeyValueChangeKindKey字段中会蕴含NSKeyValueChangeInsertion、NSKeyValueChangeRemoval、NSKeyValueChangeReplacement的信息,示意汇合对象的操作形式。 其余触发办法调用KVO属性对象时,不仅能够通过点语法和set语法进行调用,KVO兼容很多种调用形式。 // 间接调用set办法,或者通过属性的点语法间接调用[account setName:@"Savings"];// 应用KVC的setValue:forKey:办法[account setValue:@"Savings" forKey:@"name"];// 应用KVC的setValue:forKeyPath:办法[document setValue:@"Savings" forKeyPath:@"account.name"];// 通过mutableArrayValueForKey:办法获取到代理对象,并应用代理对象进行操作Transaction *newTransaction = <#Create a new transaction for the account#>;NSMutableArray *transactions = [account mutableArrayValueForKey:@"transactions"];[transactions addObject:newTransaction];理论利用KVO次要用来做键值察看操作,想要一个值产生扭转后告诉另一个对象,则用KVO实现最为适合。斯坦福大学的iOS教程中有一个很经典的案例,通过KVO在Model和Controller之间进行通信。 触发被动触发KVO在属性产生扭转时的调用是主动的,如果想要手动管制这个调用机会,或想本人实现KVO属性的调用,则能够通过KVO提供的办法进行调用。 - (void)setBalance:(double)theBalance { if (theBalance != _balance) { [self willChangeValueForKey:@"balance"]; _balance = theBalance; [self didChangeValueForKey:@"balance"]; }}能够看到调用KVO次要依附两个办法,在属性产生扭转之前调用willChangeValueForKey:办法,在产生扭转之后调用didChangeValueForKey:办法。然而,如果不调用willChangeValueForKey,间接调用didChangeValueForKey是不失效的,二者有先后顺序并且须要成对呈现。 禁用KVO如果想禁止某个属性的KVO,例如要害信息不想被三方SDK通过KVO的形式获取,能够通过automaticallyNotifiesObserversForKey办法返回NO来禁止其余中央对这个属性进行KVO。办法返回YES则示意能够调用,如果返回NO则示意不能够调用。此办法是一个类办法,能够在办法外部判断keyPath,来抉择这个属性是否容许被KVO。 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey { BOOL automatic = NO; if ([theKey isEqualToString:@"balance"]) { automatic = NO; } else { automatic = [super automaticallyNotifiesObserversForKey:theKey]; } return automatic;}KVC触发KVC对KVO有非凡兼容,当通过KVC调用非属性的实例变量时,KVC外部也会触发KVO的回调,并通过NSKeyValueDidChange和NSKeyValueWillChange向上回调。 ...

November 20, 2021 · 5 min · jiezi

关于iOS开发:iOS开发通过第三方分析工具对dSYM文件进行分析

前言在iOS开发过程的时候,在遇到报错的时候抛出的报错异样,须要疾速定位到具体报错地位,有时候通过惯例的代码排查办法能够解决,然而有些时候通过惯例的形式不能很好的定位到报错地位,尤其是遇到一些隐性的报错信息,不能疾速的定位到报错起因信息,这样就要借助第三方的错误信息剖析来解决了。 那么本文就来分享一下在iOS开发过程中借助第三方工具来剖析解决报错异样的解决办法,本文案例应用的友盟U-APM来做应用案例。通过在我的项目中集成友盟剖析工具,应用友盟U-APM来剖析报错异样信息,就能在友盟给出的错误信息中,很不便的找出客户端异样的信息,比方很多像数组越界却只给出了 * -[__NSArrayM objectAtIndex:]: index 50 beyond bounds [0 .. 39]' 这类错误信息,这种很难定位具体报错地位的信息,如下图所示: 遇到这种问题的话,如果通过 objectAtIndex 去检索谬误的中央,那将会是一个微小的工作量,那么怎么办能力加重工作量呢,那就是上面要介绍的状况了。 一、dSYM 文件Xcode编译我的项目后,咱们会看到一个同名的 dSYM 文件,dSYM 是保留 16 进制函数地址映射信息的直达文件,咱们调试的 symbols 都会蕴含在这个文件中,并且每次编译我的项目的时候都会生成一个新的 dSYM 文件,位于 /Users/<电脑用户名>/Library/Developer/Xcode/Archives 目录下,对于每一个公布版本咱们都很有必要保留对应的 Archives 文件 。 二、dSYM 文件的作用当咱们应用程序release 模式打包或上线后,不会像在Xcode中那样直观的看到用解体的谬误,这个时候就须要剖析 crash report 文件了,iOS 设施中会有日志文件保留咱们每个利用出错的函数内存地址,通过 Xcode 的 Organizer 能够将 iOS 设施中的 DeviceLog 导出成 crash 文件,这样就能够通过出错的函数地址去查问 dSYM 文件中程序对应的函数名和文件名。然而前提是咱们须要有软件版本对应的 dSYM 文件,这也是为什么很有必要保留每个公布版本的 Archives 文件了。 三、如何把文件一一对应每一个 xxx.app 和 xxx.app.dSYM 文件都有对应的 UUID,crash文件也有本人的UUID,只有这三个文件的UUID统一,咱们就能够通过它们解析出正确的谬误函数信息了。 1.查看 xxx.app 文件的 UUID,terminal 中输出命令 :dwarfdump --uuid xxx.app/xxx (xxx是你的项目名称) ...

November 19, 2021 · 1 min · jiezi

关于iOS开发:设计一套完整的日志系统

需要日志对于线上排查问题是十分重要的,很多问题其实是很偶现的,同样的零碎版本,同样的设施,可能就是用户的复现,而开发通过雷同的操作和设施就是不复现。然而这个问题也不能始终不解决,所以能够通过日志的形式排查问题。可能是后盾导致的问题,也可能是客户端逻辑问题,在关键点记录日志能够疾速定位问题。 假如咱们的用户量是一百万日活,其中有1%的用户应用呈现问题,即便这个问题并不是解体,就是业务上或播放呈现问题。那这部分用户就是一万的用户,一万的用户数量是很宏大的。而且大多数用户在遇到问题后,并不会被动去分割客服,而是转到其余平台上。 尽管咱们当初有Kibana网络监控,然而只能排查网络申请是否有问题,用户是否在某个工夫申请了服务器,服务器下发的数据是否正确,然而如果定位业务逻辑的问题,还是要客户端记录日志。 现状咱们我的项目中之前有日志零碎,然而从业务和技术的角度来说,存在两个问题。现有的日志零碎从业务层角度,须要用户手动导出并发给客服,对用户有不必要的打搅。而且大多数用户并不会许可客服的申请,不会导出日志给客服。从技术的角度,现有的日志零碎代码很乱,而且性能很差,导致线上不敢继续记录日志,会导致播放器卡顿。 而且现有的日志零碎仅限于debug环境开启被动记录,线上是不开启的,线上出问题后须要用户手动关上,并且记录时长只有三分钟。正是因为当初存在的诸多问题,所以大家对日志的应用并不是很踊跃,线上排查问题就比拟艰难。 方案设计思路正是针对当初存在的问题,我筹备做一套新的日志零碎,来代替现有的日志零碎。新的日志零碎定位很简略,就是纯正的记录业务日志。Crash、埋点这些,咱们都不记录在外面,这些能够当做当前的扩大。日志零碎就记录三种日志,业务日志、网络日志、播放器日志。 日志收集咱们采纳的被动回捞策略,在日志平台上填写用户的uid,通过uid对指定设施下发回捞指令,回捞指令通过长连贯的形式下发。客户端收到回捞指令后,依据筛选条件对日志进行筛选,随后以天为单位写入到不同的文件中,压缩后上传到后端。 在日志平台能够依据指定的条件进行搜寻,并下载文件查看日志。为了便于开发者查看日志,从数据库取出的日志都会写成.txt模式,并上传此文件。 API设计对于调用的API设计,应该足够简略,业务层应用时就像调用NSLog一样。所以对于API的设计方案,我采纳的是宏定义的形式,调用办法和NSLog一样,调用很简略。 #if DEBUG#define SVLogDebug(frmt, ...) [[SVLogManager sharedInstance] mobileLogContent:(frmt), ##__VA_ARGS__]#else#define SVLogDebug(frmt, ...) NSLog(frmt, ...)#endif日志总共分为三种类型,业务日志、播放器日志、网络日志,对于三种日志别离对应着不同的宏定义。不同的宏定义,写入数据库的类型也不一样,能够用户日志筛选。 业务日志:SVLogDebug。播放器日志:SVLogDebugPlayer。网络日子:SVLogDebugQUIC。淘汰策略不光是要往数据库里写,还须要思考淘汰策略。淘汰策略须要均衡记录的日志数量,以及时效性的问题,日志数量尽量够排查问题,并且还不会占用过多的磁盘空间。所以,在日志上传之后会将已上传日志删除掉,除此之外日志淘汰策略有以下两种。 日志最多只保留三天,三天以前的日志都会被删掉。在利用启动后进行查看,并后盾线程执行这个过程。日志减少一个最大阈值,超过阈值的日志局部,以工夫为序,从前往后删除。咱们定义的阈值大小为200MB,个别不会超过这个大小。记录根底信息在排查问题时一些要害信息也很重要,例如用户过后的网络环境,以及一些配置项,这些因素对代码的执行都会有一些影响。对于这个问题,咱们也会记录一些用户的配置信息及网络环境,不便排查问题,但不会波及用户经纬度等隐衷信息。 数据库旧计划之前的日志计划是通过DDLog实现的,这种计划有很重大的性能问题。其写入日志的形式,是通过NSData来实现的,在沙盒创立一个txt文件,通过一个句柄来向本地写文件,每次写完之后把句柄seek到文件开端,下次间接在文件开端持续写入日志。日志是以NSData的形式进行解决的,相当于始终在频繁的进行本地文件写入操作,还要在内存中维持一个或者多个句柄对象。 这种形式还有个问题在于,因为是间接进行二进制写入,在本地存储的是txt文件。这种形式是没有方法做筛选之类的操作的,扩展性很差,所以新的日志计划咱们打算采纳数据库来实现。 计划抉择我比照了一下iOS平台支流的数据库,发现WCDB是综合性能最好的,某些方面比FMDB都要好,而且因为是C++实现的代码,所以从代码执行的层面来讲,也不会有OC的音讯发送和转发的额定耗费。 依据WCDB官网的统计数据,WCDB和FMDB进行比照,FMDB是对SQLite进行简略封装的框架,和间接用SQLite差异不是很大。而WCDB则在sqlcipher的根底上进行的深度优化,综合性能比FMDB要高,以下是性能比照,数据来自WCDB官网文档。 单次读操作WCDB要比FMDB慢5%左右,在for循环内始终读。 单次写操作WCDB要比FMDB快28%,一个for循环始终写。 批量写操作比拟显著,WCDB要比FMDB快180%,一个批量工作写入一批数据。 从数据能够看出,WCDB在写操作这块性能要比FMDB要快很多,而本地日志最频繁的就是写操作,所以这正好合乎咱们的需要,所以抉择WCDB作为新的数据库计划是最合适的。而且我的项目中曝光模块曾经用过WCDB,证实这个计划是可行并且性能很好的。 表设计咱们数据库的表设计很简略,就上面四个字段,不同类型的日志用type做辨别。如果想减少新的日志类型,也能够在我的项目中扩大。因为应用的是数据库,所以扩展性很好。 index:主键,用来做索引。content:日志内容,记录日志内容。createTime:创立工夫,日志入库的工夫。type:日志类型,用来辨别三种类型。数据库优化咱们是视频类利用,会波及播放、下载、上传等次要性能,这些性能都会大量记录日志,来不便排查线上问题。所以,防止数据库太大就成了我在设计日志零碎时,比拟看重的一点。 依据日志规模,我对播放、下载、上传三个模块进行了大量测试,播放一天两夜、下载40集电视剧、上传多个高清视频,累计记录的日志数量大略五万多条。我发现数据库文件夹曾经到200MB+的大小,这个大小曾经是比拟大的,所以须要对数据库进行优化。 我察看了一下数据库文件夹,有三个文件,db、shm、wal,次要是数据库的日志文件太大,db文件反而并不大。所以须要调用sqlite3_wal_checkpoint将wal内容写入到数据库中,这样能够缩小wal和shm文件的大小。但WCDB并没有提供间接checkpoint的办法,所以通过调研发现,执行database的敞开操作时,能够触发checkpoint。 我在应用程序退出时,监听了terminal告诉,并且把解决理论尽量靠后。这样能够保障日志不被脱漏,而且还能够在程序退出时敞开数据库。通过验证,优化后的数据库磁盘占用很小。143,987条数据库,数据库文件大小为34.8MB,压缩后的日志大小为1.4MB,解压后的日志大小为13.6MB。 wal模式这里顺带讲一下wal模式,以不便对数据库有更深刻的理解。SQLite在3.7版本退出了wal模式,但默认是不开启的,iOS版的WCDB将wal模式主动开启,并且做了一些优化。 wal文件负责优化多线程下的并发操作,如果没有wal文件,在传统的delete模式下,数据库的读写操作是互斥的,为了避免写到一半的数据被读到,会等到写操作执行实现后,再执行读操作。而wal文件就是为了解决并发读写的状况,shm文件是对wal文件进行索引的。 SQLite比拟罕用的delete和wal两种模式,这两种模式各有劣势。delete是间接读写db-page,读写操作的都是同一份文件,所以读写是互斥的,不反对并发操作。而wal是append新的db-page,这样写入速度比拟快,而且能够反对并发操作,在写入的同时不读取正在操作的db-page即可。 因为delete模式操作的db-page是离散的,所以在执行批量写操作时,delete模式的性能会差很多,这也就是为什么WCDB的批量写入性能比拟好的起因。而wal模式读操作会读取db和wal两个文件,这样会肯定水平影响读数据的性能,所以wal的查问性能绝对delete模式要差。 应用wal模式须要管制wal文件的db-page数量,如果page数量太大,会导致文件大小不受管制。wal文件并不是始终减少的,依据SQLite的设计,通过checkpoint操作能够将wal文件合并到db文件中。但同步的时机会导致查问操作被阻塞,所以不能频繁执行checkpoint。在WCDB中设置了一个1000的阈值,当page达到1000后才会执行一次checkpoint。 这个1000是微信团队的一个经验值,太大会影响读写性能,而且占用过多的磁盘空间。太小会频繁执行checkpoint,导致读写碰壁。 # define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){#ifdef SQLITE_OMIT_WAL UNUSED_PARAMETER(db); UNUSED_PARAMETER(nFrame);#else#ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;#endif if( nFrame>0 ){ sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame)); }else{ sqlite3_wal_hook(db, 0, 0); }#endif return SQLITE_OK;}也能够设置日志文件的大小限度,默认是-1,也就是没限度,journalSizeLimit的意思是,超出的局部会被覆写。尽量不要批改这个文件,可能会导致wal文件损坏。 ...

November 9, 2021 · 1 min · jiezi

关于iOS开发:iOS开发常见问题汇总

iOS开发常见问题模拟器零碎软键盘不弹出快捷键:command + k,菜单栏上找到I/O->keyboard->toggle software keyboard

September 17, 2021 · 1 min · jiezi

关于iOS开发:iOS-MVC架构设计模式和MVVM

本文转载自:星星月亮0MVC(Model-View-Controller)iOS应用程序都遵循MVC架构,iOS13推出的SwiftUI除外,SwiftUI的设计遵循的MVVM.MVC是构建iOS App的规范模式,是苹果举荐的一个用来组织代码的权威范式,市面上大部分App都是这样构建的Model(模型):数据(业务)模型,负责解决和存取数据model里可能基本不是oc对象,可能是网络api. 数据库跟新了,模型得告诉控制器View(视图):界面,负责显示数据和与用户交互Controller(控制器):业务逻辑,相当于一个解决核心,负责管理Model和View, Model和View都是控制器里的对象,次要负责将数据模型展现在视图上,同时也负责界面交互的解决。Model和View是不相通的,所有的事件,都只能通过控制器替换控制器的工作就是展现模型,对模型了如执掌。控制器为视图翻译和格式化它们须要的模型数据管制UI如何显示就是它天天干的事件 作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这是一个我的iOS交换群: 711315161,不论你是小白还是大牛欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长!控制器要和模型或是视图沟通是很容易的,因为控制器自身就持有模型和视图,模型和视图对象就是在控制器中创立的,所有控制器很容易就能够获取模型和视图对象的属性和办法 视图要和控制器沟通能够通过button增加点击(target-action)事件,delegate, datasource delegate 模型要和控制器沟通要通过kvo和告诉(Notification) 会弄很多个MVC,层层蕴含,互相帮助iOS里有API,容许一个控制器把其余的MVC当作本人的视图,如下图. 像下图,这样可不行,会把本人都看晕,所以打一个红圈圈,淘汰掉 MVVM(Model-View-ViewModel) MVC尽管是storyboard我的项目中iOS app的规范模式,然而它也有一个别称叫Massive View Controller(重量级控制器),也就是当业务逻辑比较复杂的时候ViewController打代码会很多。为了给控制器瘦身,就引入ViewModel层用来解决网络申请,数据转换等业务逻辑(这些在MVC里也是由控制器来做)。而控制器更多的是负责和界面展现,用户交互相干的性能。并且把controller和view合并成View.这样就由MVC衍生出MVVM架构。 Model:数据View: 视图展现(UIView + UIViewController)ViewModel: 连贯View和Model swiftUI(MVVM)iOS13推出的SwiftUI苹果的规范架构就是MVVM。不须要咱们像在用storyboard的时候一样,原本苹果MVC是苹果的规范模式,咱们硬是要拆一个MVVM进去

July 21, 2021 · 1 min · jiezi

关于iOS开发:iOS-KVO详解

一、概述KVO<NSKeyValueObserving>,是一个非正式协定,提供了一个路径,使对象(观察者)可能察看其余对象(被观察者)的属性,当被观察者的属性发生变化时,观察者就会被告知该变动。指定一个被察看对象(例如 A 类),当对象某个属性(例如 A 中的字符串 name)产生更改时,对象会取得告诉,并作出相应解决;【且不须要给被察看的对象增加任何额定代码,就能应用 KVO 机制】 二、应用办法零碎框架曾经反对KVO,所以程序员在应用的时候非常简单。 1、增加观察者: - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;2、实现察看响应办法: - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary*)change context:(nullable void *)context;3、移除观察者: - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;假如一个场景,股票的价格显示在以后屏幕上,当股票价格更改的时候,实时显示更新其价格。 1.定义Model, @interface StockData : NSObject { NSString * stockName; Nsstring * price; } @end @implementation StockData @end#import "KVOViewController.h" @interface KVOViewController (){ StockData *stockForKVO; UILabel *myLabel;}@end @implementation KVOViewController - (void)viewDidLoad { [super viewDidLoad]; //2.定义此model为Controller的属性,实例化它,监听它的属性,并显示在以后的View里边 stockForKVO = [[StockData alloc] init]; [stockForKVO setValue:@"searph" forKey:@"stockName"]; [stockForKVO setValue:@"10.1" forKey:@"price"]; [stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL]; myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )]; myLabel.backgroundColor = [UIColor redColor]; myLabel.text = [stockForKVO valueForKey:@"price"]; [self.view addSubview:myLabel]; UIButton * b = [UIButton buttonWithType:UIButtonTypeCustom]; b.frame = CGRectMake(10, 100, 100, 30); [b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside]; [b setTitle:@"测试" forState:(UIControlStateNormal)]; [self.view addSubview:b];// self.view.backgroundColor = [UIColor greenColor]; }-(void) buttonAction{ [stockForKVO setValue:@"20.0" forKey:@"price"];} -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if([keyPath isEqualToString:@"price"]) { myLabel.text = [stockForKVO valueForKey:@"price"]; }}- (void)dealloc{ [stockForKVO removeObserver:self forKeyPath:@"price"];} @end/** options参数阐明: NSKeyValueObservingOptionNew 拿到新值 NSKeyValueObservingOptionOld 拿到旧值 NSKeyValueObservingOptionInitial 注册就会发一下告诉,扭转后还会发 NSKeyValueObservingOptionPrior 扭转之前发一次,扭转后发一次 */ ...

July 20, 2021 · 1 min · jiezi

关于iOS开发:苹果关闭-iOS-1442-系统验证通道

本文转载自IT之家 IT之家 5 月 4 日音讯 在 4 月下旬公布 iOS 14.5 正式版后,苹果公司明天进行了对 iOS 14.4.2 的验证。这意味着更新到 iOS 14.5 的用户无奈再降级到 iOS 14.4.2 版本。 iOS 14.5 带来了大量更新内容,包含佩戴口罩时通过 Apple Watch 解锁 iPhone 的选项,新增对 AirTag 的反对,并且 App 跟踪透明度可让用户管制哪些 App 可在其余公司的 App 和网站中跟踪其流动。 苹果通常会在推送正式版更新之后的几周内进行对旧版 iOS 的验证。对于一些更新至最新 iOS 零碎的用户,当其遇到重大 Bug 时,降级的形式有时会非常无效。这也是苹果在敞开旧版 iOS 系统验证通道之前会期待一段时间的起因。 IT之家理解到,iOS 14.4.2 则提供了重要的安全更新,苹果此前倡议所有用户装置。

July 20, 2021 · 1 min · jiezi

关于iOS开发:2021最新iOS面试题总结一

看完这些,大厂不是梦!!!明天刚刚开始面试,接下来这几天把遇到的面试题总结如下:1.内存治理在理论开发中的利用(必考,曾经被问两次了)答:1.UITableView的数据条数太多时会耗费内存,能够给UITableViewCell、UICollectionViewCell、UITableViewHeaderFooterView设置正确的复用ID,充沛复用。 2.有透明度的View(alpha值在0到1之间),opaque的值应该设置为YES,能够优化渲染零碎、进步性能。(当alpha值为0或1时,opaque的值对性能没有影响) 3.防止过于宏大的XIB/StoryBord文件,当加载XIB文件的时候,所有的内容都会被加到内存里,如果有一个不会立即用到的View,就是在节约内存资源。 4.不要让主线程承当过多的工作,否则会阻塞主线程,使app失去反馈。 5.加载本地图片时,应该保障UIImageView的大小和图片的大小雷同,因为缩放图片是很耗费资源的,特地是在UIImageView嵌套在UIScrollView中的状况下。如果是从网络加载的图片,能够等图片加载实现当前,开启一个子线程缩放图片,而后再放到UIImageView中。 6.在适合的场景下抉择适合的数据类型,对于数组:应用索引查问很快,应用值查问很慢,插入删除很慢,对于字典:用键来查找很快,对于汇合:用值来查找很快,插入删除很快。 7.网络下载文件时压缩(目前AFNetworking曾经默认压缩) 8.当UIScrollView嵌套大量UIView时会耗费内存,能够模拟UITableView的重用形式解决,当网络申请的时候能够应用提早加载来显示申请谬误的页面,因为网络申请谬误的页面不会马上用到,如果每次都先加载进去会耗费内存。 9.不大可能扭转但常常应用的货色能够应用缓存,比方cell的行高能够缓存起来,这样reloaddata的时候效率会很高。还有一些网络数据,不须要每次都申请的,应该缓存起来,能够写入数据库,也能够写入plist文件。 10.在appDelegate和UIViewController中都有解决内存正告的办法,注册并承受内存正告的告诉,一旦收到告诉就移除缓存,开释不须要的内存空间。 11.一些对象的初始化很慢,比方NSDateFormatter和NSCalendar,但你又必须要应用它,这时能够重用它们,有两种形式,第一种是增加属性到你的类,第二种是创立动态变量(相似于单例) 12.服务器端和客户端应用雷同的数据结构,防止重复解决数据,UIWebView中尽可能少的应用框架,用原声js最好,因为UIView的加载比较慢。 13.在循环创立变量解决数据的时候,应用主动开释池能够及时的开释内存。 14.加载本地图片的时候,如果只应用一次应用imageWithContentOfFile办法,因为imageNamed办法会缓存图片,耗费内存。 总结:面试时我只答了内存治理的法令和MRC、ARC、主动开释池的区别,并没有说出内存治理在理论开发中是怎么使用的,齐全没有答到点子上。 2.多线程的理论利用场景,回到主线程的办法 (必考,曾经被问两次)在理论开发中可能会有一些耗时的操作,这时能够开拓一个子线程把耗时的操作放到子线程中,当耗时操作执行结束当前再回到主线程刷新UI。必须要在主线程刷新UI,因为多线程是不平安的,如果在子线程中刷新UI可能会导致未知谬误。 回到主线程的办法是performSelectorOnMainTread 延时执行的代码:performSelector:onThread:withObject:waitUntillDone: 应用GCD回到主线程的办法:dispatch_get_main_queue() 应用GCD开启线程:dispatch_async([sŋk] ) 二者的区别:dispatch_async()不受运行循环模式的影响 总结:我只答复出了多线程的概念、长处,而面试官次要想听的关键词是:耗时、开启子线程、回到主线程刷新UI,所答非所问,而且回到主线程的办法名字我也没记住。这段话很重要,简直所有的iOS技术面试都会问到,肯定要熟记于心。 3.对于GCD的了解答:GCD中有两个外围概念,队列和工作。队列寄存工作,工作的取出遵循FIFO准则。队列其实就是线程池,在OC中以dispatch_queue_t示意,队列分串行队列和并发队列。工作其实就是线程执行的代码,在OC中以Block示意。在队列中执行工作有两种形式:同步执行和异步执行。 串行队列:工作一个一个执行。 并发队列:同一时间有多个工作被执行。 区别:会不会有工作放在别的线程(因为并发队列是取出一个工作放到别的线程,再取出一个工作放到另一个线程,因为动作很快,能够忽略不计,所以看起来所有工作都是一起执行的) 同步执行:不会开启新的线程,工作按程序执行。 异步执行:会开启新的线程,工作能够并发执行。 区别:会不会开启新的线程。 组合: 同步串行队列:one by one异步串行队列:one by one (因为前一个工作不执行结束,队列不会调度)同步并行队列:one by one (因为同步执行不会开启新的线程)异步并发队列:能够实现工作的并发,常常用到 主队列:主队列是串行队列,只有一个线程,那就是主线程,增加到主队列中的工作会在主线执行。通过dispatch_get_main_queue获取主队列。 全局队列:全局队列是并发队列。能够通过dispatch_get_global_queue获取不同级别的全局队列。 同步主队列:死锁卡住不执行。主队列异步:one by one (因为没有开启新线程) 总结:我只答复出了延时操作应用gcd,应用加载动画时用到了dispatch_after办法,都太外表了,面试官想要听的是更深层次的了解,于是问了我对于工作和队列,我没有想到这方面,当前提到gcd首先要想到的就是工作和队列,因为工作和队列是gcd的外围概念。 4.TCP、HTTP、WebSokect的区别答:IP协定(网络层协定)TCP:传输控制协议,次要解决数据如何在网络中传输,面向连贯,牢靠。(传输层协定)UDP:用户数据报协定,面向数据报,不牢靠。HTTP:次要解决如何包装数据。(应用层协定)Socket:是对TCP/IP协定的封装,Socket自身并不是协定,而是一个调用接口(API),通过Socket,咱们能力应用TCP/IP协定。(传输层协定) HTTP连贯:短连贯,客户端向服务器发送一次申请,服务器端响应连贯后会立刻端掉。Socket连贯:长连贯,实践上客户端和服务器端一旦建设连贯将不会被动端掉。 建设Socket连贯至多须要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。套接字之间的连贯过程分为三个步骤:服务器监听,客户端申请,连贯确认。 WebSocket是双向通信协定,模仿Socket协定,能够双向发送或承受信息。HTTP是单向的。Socket是传输管制层协定,WebSocket是应用层协定。 总结:我本人简历上写的货色我还不了解,很难堪,即便说不出来深层次的货色也应该把他们的次要区别说进去。还有网络七层模型肯定要记住,几年前的面试官就问过我我就没记住。 从底层到顶层别离是物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。 5.iOS应用程序的生命周期,最次要的是什么application:willFinishLaunchingWithOptions: 程序启动application:didFinishLaunchingWithOptions: 入口,只执行一次,启动实现筹备开始运行applicationWillResignActive: 切换到非活动状态,如按下home键、切换程序applicationDidBecomeActive: 切换到激活状态applicationDidEnterBackground: 应用程序进入后盾applicationWillEnterForeground: 应用程序将要被激活applicationWillTerminate: 应用程序将要退出 App的启动过程:关上程序——执行main函数——UIAPPlicationMain函数——初始化UIAPPlicationMain函数(设置代理,开启runloop)——监听系统事件,告诉AppDelegate——程序完结 总结:面试官问的是应用程序的生命周期,而我答的是Viewcontroller的生命周期,面试官次要想听到的关键词应该是:main函数、UIApplicationMain、AppDelegate、runloop、监听 另外总结一下对于runloop的知识点: runloop:运行循环,在程序运行过程中循环做一些事runloop的作用:放弃程序继续运行、解决App中的各种事件、进步资源利用率runloop在理论我的项目中的利用:控制线程的生命周期、解决NSTimer在滑动时进行工作的问题、监控利用的卡顿、性能优化 6.iOS的外围动画 (必考,曾经被问两次)答:动画有两种根本类型:隐式动画(始终存在,须要手动敞开)和显式动画(不存在,须要手动创立)UIView的动画: UIViewAnimationOptionCurveEaseInOut //工夫曲线函数,由慢到快 ...

July 17, 2021 · 1 min · jiezi

关于iOS开发:2021年整理的iOS高频面试题及答案总会有你需要的

各位最近应该忙于跳槽与面试吧,毕竟金三银四,珍惜好机会,预祝大家面试顺利通过,迎接大厂offer。有须要材料能够私聊我理解 从输出url到页面展现到底产生了什么1、输出地址2、浏览器查找域名的 IP 地址3、浏览器向 web 服务器发送一个 HTTP 申请4、服务器的永恒重定向响应5、浏览器跟踪重定向地址6、服务器解决申请7、服务器返回一个 HTTP 响应8、浏览器显示 HTML9、浏览器发送申请获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)iOS高频(根底+底层)面试题你在开发过程中罕用到哪些定时器,定时器工夫会有误差吗,如果有,为什么会有误差? iOS中常NSTimer、CADisplayLink、GCD定时器,其中NSTimer、CADisplayLink基于NSRunLoop实现,故存在误差,GCD定时器只依赖零碎内核,绝对一前两者是比拟准时的。 误差起因是:与NSRunLoop机制无关, 因为RunLoop每跑完一次圈再去查看以后累计工夫是否曾经达到定时设置的间隔时间,如果未达到,RunLoop将进入下一轮工作,待工作完结之后再去查看以后累计工夫,而此时的累计工夫可能曾经超过了定时器的间隔时间,故会存在误差。 block是类吗,有哪些类型?block也算是个类,因为它有isa指针,block.isa的类型包含 _NSConcreteGlobalBlock 跟全局变量一样,设置在程序的数据区域(.data)中_NSConcreteStackBlock栈上(后面讲的都是栈上的 block)_NSConcreteMallocBlock 堆上这个isa能够按位运算block的分类,__block的作用,block循环援用产生的起因及解决办法blcok分为全局blcok,堆block,栈block。在 MRC下:只有没有拜访内部变量,就是全局block。拜访了内部变量,就是栈block。显示地调用[block copy]就是堆block。在 ARC下:只有没有拜访内部变量,就是全局block。如果拜访了内部变量,那么在拜访内部变量之前存储在栈区,拜访内部变量之后存储在堆区。__block的作用:将内部变量的传递模式由值传递变为指针传递,从而能够获取并且批改内部变量的值。同样,内部变量的批改,也会影响block函数的输入。block循环援用问题:当一个类的对象持有block,block外面又援用了这个对象,那么就是一个循环援用的关系。能够用strong-weak-dance的办法解除循环援用。 浅复制和深复制的区别?答案:浅层复制:只复制指向对象的指针,而不复制援用对象自身。深层复制:复制援用对象自身。意思就是说我有个A对象,复制一份后失去A_copy对象后,对于浅复制来说,A和A_copy指向的是同一个内存资源,复制的只不过是是一个指针,对象自身资源还是只有一份,那如果咱们对A_copy执行了批改操作,那么发现A援用的对象同样被批改,这其实违反了咱们复制拷贝的一个思维。深复制就好了解了,内存中存在了两份独立对象自身。用网上一哥们艰深的话将就是:浅复制好比你和你的影子,你完蛋,你的影子也完蛋深复制好比你和你的克隆人,你完蛋,你的克隆人还活着。 有想要支付收费材料的能够进裙或者加好友支付,这里有一个iOS交换圈:710 558 675 能够来理解,分享BAT,阿里面试题、面试教训,探讨技术,裙里材料间接下载就行, 大家一起交流学习!类别的作用?继承和类别在实现中有何区别?答案:category 能够在不获悉,不扭转原来代码的状况下往里面增加新的办法,只能增加,不能删除批改。并且如果类别和原来类中的办法产生名称抵触,则类别将笼罩原来的办法,因为类别具备更高的优先级。类别次要有3个作用: (1)将类的实现扩散到多个不同文件或多个不同框架中。(2)创立对公有办法的前向援用。(3)向对象增加非正式协定。继承能够减少,批改或者删除办法,并且能够减少属性。oc中的协定和java中的接口概念有何不同?答案:OC中的代理有2层含意,官网定义为 formal和informal protocol。前者和Java接口一样。informal protocol中的办法属于设计模式思考领域,不是必须实现的,然而如果有实现,就会扭转类的属性。其实对于正式协定,类别和非正式协定我很早前学习的时候大抵看过,也写在了学习教程里“非正式协定概念其实就是类别的另一种表达方式“这里有一些你可能心愿实现的办法,你能够应用他们更好的实现工作”。这个意思是,这些是可选的。比方我门要一个更好的办法,咱们就会申明一个这样的类别去实现。而后你在前期能够间接应用这些更好的办法。这么看,总感觉类别这玩意儿有点像协定的可选协定。"当初来看,其实protocal曾经开始对两者都对立和标准起来操作,因为材料中说“非正式协定应用interface润饰“,当初咱们看到协定中两个修饰词:“必须实现(@requied)”和“可选实现(@optional)”。 oc中可批改和不能够批改类型。答案:可批改不可批改的汇合类。这个我集体简略了解就是可动静增加批改和不可动静增加批改一样。比方NSArray和NSMutableArray。前者在初始化后的内存控件就是固定不可变的,后者能够增加等,能够动静申请新的内存空间。 对于多态性答案:多态,子类指针能够赋值给父类。这个题目其实能够出到所有面向对象语言中,因而对于多态,继承和封装根本最好都有个自我意识的了解,也并非肯定要把书上材料上写的能背进去。最重要的是转化成自我了解。 告诉和协定的不同之处?答案:协定有管制链(has-a)的关系,告诉没有。首先我一开始也不太明确,什么叫管制链(专业术语了~)。然而简略剖析下告诉和代理的行为模式,咱们大抵能够有本人的了解简略来说,告诉的话,它能够一对多,一条音讯能够发送给多个音讯接受者。代理按咱们的了解,到不是间接说不能一对多,比方咱们晓得的明星经济代理人,很多时候一个经济人负责好几个明星的事务。只是对于不同明星间,代理的事物对象都是不一样的,一一对应,不可能说今天要解决A明星要一个发布会,代理人收回解决发布会的音讯后,别称B的发布会了。然而告诉就不一样,他只关怀发出通知,而不关怀多少接管到感兴趣要解决。因而管制链(has-a从英语单词大抵能够看出,繁多领有和可管制的对应关系。 线程和过程的区别?1 一个应用程序对应一个过程,一个过程帮忙程序占据一块存储空间 2 要想在过程中执行工作,就必须开启线程,一条线程就代表一个工作 3 一个过程中容许开启多条线程,也就是同时执行多个工作 Objective-C如何对内存治理的,说说你的认识和解决办法?1 每个对象都有一个援用计数器,每个新对象的计数器是1,当对象的计数器减为0时,就会被销毁 2通过retain能够让对象的计数器+1、release能够让对象的计数器-1 3 还能够通过autorelease pool治理内存 如果用ARC,编译器会主动生成治理内存的代码 堆和栈的区别?1 堆空间的内存是动态分配的,个别寄存对象,并且须要手动开释内存 2 栈空间的内存由零碎主动调配,个别寄存局部变量等,不须要手动治理内存 为什么很多内置的类,如TableView的delegate的属性是assign不是retain? 1 tableView的代理个别都是它所属的控制器,控制器会对它外部的view做一次retain操作2 假如tableView也对代理(控制器)做一次retain操作,那么就呈现循环retain问题定义属性时,什么状况应用copy、assign、retain? 1 copy:NSString、Block等类型2 assign:根本数据类型3> retain:OC对象类型 App冷启动优化?App冷启动优化计划博客十分之多,概括总结大抵如下: pre-main优化:缩小动静动态库,合并动静库,移除废除第三方库及所依赖的零碎库,二进制重排(抖音优化计划) runtime对类的注册,类对象的初始化,load办法加载阶段:精简类,合并分类,移除废除分类等等 main函数之后,推延对三方库注册及延时调用耗时操作函数。能够通过Instruments–>Time Profiler: 性能剖析,定位耗时函数 ...

July 16, 2021 · 1 min · jiezi

关于iOS开发:iOS面试题基础

分类、扩大、代理、告诉、KVC、KVO、属性关键字 一、分类(Category) *1、分类的作用? 申明公有办法,合成体积大的类文件 *2、分类的特点? 能够为零碎类增加分类。在运行时期间,将 Category 中的实例办法列表、协定列表、属性列表增加到主类中后(所有Category中的办法在办法列表中的地位是在主类的同名办法之前的),而后会递归调用所有类的 load 办法,这一切都是在main函数之前执行的。 *3、分类能够增加哪些内容? 实例办法,类办法,属性(增加getter和setter办法,并没有实例变量,增加实例变量须要用关联对象) *4、如果工程里有两个分类A和B,两个分类中有一个同名的办法,哪个办法最终失效? 取决于分类的编译程序,最初编译的那个分类的同名办法最终失效,而之前的都会被笼罩掉(这里并不是真正的笼罩,因为其余办法依然存在,只是拜访不到,因为在动静增加类的办法的时候是倒序遍历办法列表的,而最初编译的分类的办法会放在办法列表后面,拜访的时候就会先被拜访到,同理如果申明了一个和原类办法同名的办法,也会笼罩掉原类的办法)。 5、如果申明了两个同名的分类会怎么? 会报错,所以第三方的分类,个别都带有命名前缀 6、分类能增加成员变量吗? 不能。只能通过关联对象(objc_setAssociatedObject)来模仿实现成员变量,但其实质是关联内容,所有对象的关联内容都放在同一个全局容器哈希表中:AssociationsHashMap,由AssociationsManager对立治理。 二、扩大(Extension) 1、扩大的作用? 申明公有属性,申明公有成员变量 2、扩大的特点? 编译时决定,只能以申明的模式存在,少数状况下放在在宿主类的.m中,不能为零碎类增加扩大 三、代理(Delegate) 代理是一种设计模式,委托方申明协定,定义须要实现的接口,代理方依照协定实现办法 个别用weak来防止循环援用 四、告诉(NSNotification) 应用观察者模式用于实现跨层传递信息的机制。传递形式是一对多。 五、KVO(key-value-observing) KVO是观察者的另一实现 应用了isa混写(isa-swizzling)来实现KVO 应用setter办法扭转值KVO会失效,应用KVC扭转值KVO也会失效,因为KVC会调用setter办法 - (void)setValue:(id)value { [self willChangeValueForKey:@"key"]; [super setValue:value]; [self didChangeValueForKey:@"key"];}间接赋值成员变量不会触发KVO,因为不会调用setter办法,须要加上willChangeValueForKey和didChangeValueForKey 六、KVC(key-value-coding) KVC能够通过key间接拜访对象的属性,或者给对象的属性赋值,这样能够在运行时动静的拜访或批改对象的属性 当调用setValue:属性值 forKey:@”name“的代码时,,底层的执行机制如下: 1、程序优先调用set<Key>:属性值办法,代码通过setter办法实现设置。留神,这里的<key>是指成员变量名,首字母大小写要合乎KVC的命名规定,下同 2、如果没有找到setName:办法,KVC机制会查看+ (BOOL)accessInstanceVariablesDirectly办法有没有返回YES,默认该办法会返回YES,如果你重写了该办法让其返回NO的话,那么在这一步KVC会执行setValue:forUndefinedKey:办法,不过个别开发者不会这么做。所以KVC机制会搜寻该类外面有没有名为<key>的成员变量,无论该变量是在类接口处定义,还是在类实现处定义,也无论用了什么样的拜访修饰符,只在存在以<key>命名的变量,KVC都能够对该成员变量赋值。 3、如果该类即没有set<key>:办法,也没有_<key>成员变量,KVC机制会搜寻_is<Key>的成员变量。 4、和下面一样,如果该类即没有set<Key>:办法,也没有_<key>和_is<Key>成员变量,KVC机制再会持续搜寻<key>和is<Key>的成员变量。再给它们赋值。 5、如果下面列出的办法或者成员变量都不存在,零碎将会执行该对象的setValue:forUndefinedKey:办法,默认是抛出异样。 如果想禁用KVC,重写+ (BOOL)accessInstanceVariablesDirectly办法让其返回NO即可,这样的话如果KVC没有找到set<Key>:属性名时,会间接用setValue:forUndefinedKey:办法。 当调用valueForKey:@”name“的代码时,KVC对key的搜寻形式不同于setValue:属性值 forKey:@”name“,其搜寻形式如下: 1、首先按get<Key>,<key>,is<Key>的程序办法查找getter办法,找到的话会间接调用。如果是BOOL或者Int等值类型, 会将其包装成一个NSNumber对象 2、如果下面的getter没有找到,KVC则会查找countOf<Key>,objectIn<Key>AtIndex或<Key>AtIndexes格局的办法。如果countOf<Key>办法和另外两个办法中的一个被找到,那么就会返回一个能够响应NSArray所有办法的代理汇合(它是NSKeyValueArray,是NSArray的子类),调用这个代理汇合的办法,或者说给这个代理汇合发送属于NSArray的办法,就会以countOf<Key>,objectIn<Key>AtIndex或<Key>AtIndexes这几个办法组合的模式调用。还有一个可选的get<Key>:range:办法。所以你想从新定义KVC的一些性能,你能够增加这些办法,须要留神的是你的办法名要合乎KVC的规范命名办法,包含办法签名。 3、如果下面的办法没有找到,那么会同时查找countOf<Key>,enumeratorOf<Key>,memberOf<Key>格局的办法。如果这三个办法都找到,那么就返回一个能够响应NSSet所的办法的代理汇合,和下面一样,给这个代理汇合发NSSet的音讯,就会以countOf<Key>,enumeratorOf<Key>,memberOf<Key>组合的模式调用。 4、如果还没有找到,再查看类办法+ (BOOL)accessInstanceVariablesDirectly,如果返回YES(默认行为),那么和先前的设值一样,会按_<key>,_is<Key>,<key>,is<Key>的顺序搜索成员变量名,这里不举荐这么做,因为这样间接拜访实例变量毁坏了封装性,使代码更软弱。如果重写了类办法+ (BOOL)accessInstanceVariablesDirectly返回NO的话,那么会间接调用valueForUndefinedKey:办法,默认是抛出异样 七、属性关键字 1、读写权限:readonly,readwrite(默认) 2、原子性:(atomic),nonatimic。atomic读写平安,但效率低,不是相对的平安,比方操作数组,减少或移除,这种状况能够应用互斥锁来保障线程平安 3、援用计数 retain/strong assign润饰根本数据类型 ...

July 3, 2021 · 1 min · jiezi

关于iOS开发:iOS-14-自定义画中画-AVPictureInPictureController隐藏系统快进快退按钮

仿悬浮提词器,实现以下性能: 增加任意 UIView 到画中画窗口;按需暗藏零碎的快进快退按钮、播放按钮、进度条;动静批改画中画窗口的形态,横向、竖向 or 方形;旋转窗口;基于常驻线程的线程保活措施,让你的画中画永不停歇;拍摄视频画中画的 timer 也不会进行;审核被拒的胜利应答措施。演示:

June 21, 2021 · 1 min · jiezi

关于iOS开发:IOS-自定义View绘制UIImage出现锯齿如何解决

我须要制作一个疾速更新 UIImage 的性能,一开始应用 UIImageView 来显示图片,所以须要频繁的调用 UIImageView.image = newImage 办法来更新图片。代码看起来像这样。 func onSomethingChanged() { myUIImageView.image = newImage}这样更新图片十分的卡顿,操作和画面响应有肯定的滞后,体验不好,因而思考本人做一个 UIView 来绘制图片,看看是否能够解决。 于是本人自定义了一个 View,继承 UIView 来做,在 draw(rect:) 办法外面做文章。 首先当然是简略粗犷间接 UIImage.draw(in: bounds) 先看看成果。 var image: UIImage? { didSet { setNeedsDisplay() }} override func draw(_ rect: CGRect) { guard let ctx = UIGraphicsGetCurrentContext() else { return } ctx.addRect(bounds) ctx.setFillColor(UIColor.black.cgColor) ctx.fillPath() if var im = image { im.draw(in: bounds) }}很好,更新速度很快,是现实的成果,不过目前画面是拉伸的,同时还有锯齿。 下图中右边是现实的显示成果,左边则是理论的显示成果,能够看到显著的锯齿。 通过我一番搜寻尝试了以下配置,均无任何帮忙: ctx.setShouldAntialias(true)ctx.setAllowsAntialiasing(true)ctx.interpolationQuality = .highlayer.allowsEdgeAntialiasing = truelayer.minificationFilter = .trilinear我回忆起之前用 CGImageContext 缩放图片的时候也没有这个问题啊,难道是因为 UIView 自带的这个 CGContext 无奈很好的缩放图片? ...

March 31, 2021 · 2 min · jiezi

关于iOS开发:粉丝福利-免费-get-支付宝同款扫码组件

简介:源自支付宝的扫码组件,全网收费接入About Scan随着支付宝的线下场景不断扩大,收钱码、口碑、共享单车、充电宝、停车缴费等产品让咱们的生存越来越便当。 二维码因为成本低、兼容性好成为了线上线上最次要的连贯工具,也因而面临更多新的挑战。 因为二维码是一种点阵式信息编码方式,任何视觉上的缺损、蜿蜒以及光线作用都会极大的影响辨认成功率,如果辨认艰难也就意味着用户可能抉择放弃,影响领取体验也影响用户心智。 源自支付宝的扫码组件,全网收费凋谢!欢送下载接入~ 下载地址关注「mPaaS」CSDN 账号即可收费下载 https://download.csdn.net/download/m0\_47737908/15684443 插件介绍本插件是支付宝 mPaaS 的扫码组件,让您的 app 能够领有像支付宝一样的扫码体验,辨认速度、识别率远超开源扫码。扫码组件完全免费提供应用,接入时须要您在阿里云上进行注册开明并将 mPaaS 扫码增加到您的工程即可。 接入过程中,您遇到任何问题,都能够在钉钉上搜寻「32843812」进群进行解答。 欢送大家应用不同带有扫码性能的 App,对以下三种二位码进行扫码辨认,体验 mPaaS 扫码弱小的辨认能力和辨认速度 弱光二维码 反光二维码 含糊二维码 插件应用筹备1.购买插件,抉择该插件绑定的我的项目。 2.在 HBuilderX 里找到我的项目,在 manifest 的 app 原生插件配置中勾选模块,如须要填写参数则参考本文增加。 3.依据本文的提供的文档开发代码,在代码中援用插件,调用插件性能。 4.打包自定义基座,抉择插件,失去自定义基座,而后运行时抉择自定义基座,进行 log 输入测试。 5.开发结束后正式云打包 付费原生插件目前不反对离线打包。 Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline\_package/android iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline\_package/ios 注意事项:应用 HBuilderX2.7.14 以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提醒包名绑定不统一时,须要在HBuilderX我的项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件从新抉择 插件应用流程1. 开明阿里云 mPaaS登陆阿里云账号拜访mPaaS 产品页,点击「立刻开明」,即可开沟通 mPaaS 产品。 2. 创立 mPaaS 利用开明后您须要创立一个 mPaaS 利用 3. 配置 Config 并下载3.1 Android3.1.1 填写配置信息,并上传签名 APK。点击 代码治理 > 代码配置 > Android,输出 Package Name(利用包名)(此处以 com.mpaas.demo 为例),上传编译并增加签名后的 APK 安装包。对于疾速生成签名后的 APK 相干信息,请参见 生成控制台用签名 APK。 ...

March 24, 2021 · 1 min · jiezi

关于iOS开发:IOS录音录音权限

在IOS上录音,须要先取得权限,不然录音只能返回空数据。 取得权限有两步: 1.Info设置在Xcode->Info->Custom iOS target properties里,增加Privacy-Microphone Usage Description设置,并填写一段形容。 2.代码中动静申请//recordPermission获取以后的权限状况//requestRecordPermission 申请权限-(void)checkRecordPermission{ AVAudioSession* session = [AVAudioSession sharedInstance]; AVAudioSessionRecordPermission recordPermission = [session recordPermission]; if( recordPermission == AVAudioSessionRecordPermissionUndetermined ) { NSLog(@"record permission:%d", recordPermission ); if( [session respondsToSelector:@selector( requestRecordPermission:)]) { [session requestRecordPermission:^(BOOL granted) { if( granted ) { NSLog(@"get record permission"); } else{ NSLog(@"not permit record"); } }]; } } else{ if( recordPermission == AVAudioSessionRecordPermissionGranted ) { NSLog(@"already get record permission"); } else{ NSLog(@"already denied record permission ,please set in settings"); } }}

February 15, 2021 · 1 min · jiezi

关于iOS开发:iOS开发-TableView

TableView 是iOS app 中最罕用的控件,许多代码间接或者间接的关联到table view工作中,包含提供数据、更新tableView、管制tableView行为等等。上面会提供放弃tableView代码整洁和构造清晰的办法。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! UITableViewController vs. UIViewController TableViewController的个性 table view controllers能够读取table view的数据、设置tabvleView的编辑模式、反馈键盘告诉等等。同时Table view controller可能通过应用UIRefreshControl来反对“下拉刷新”。 Child View Controllers tableViewController也能够作为child view controller增加到其余的viewController中,而后tableViewController会持续治理tableView,而parentViewController能治理其余咱们关怀的货色。 -(void)addDetailTableView{ DetailViewController *detail = [DetailViewController new]; [detail setup]; detail.delegate = self; [self addChildViewController:detail]; [detail setupView]; [self.view addSubview:detail.view]; [detail didMoveToParentViewController:self]; } 如果在应用以上代码时,须要建设child View controller 和 parent view controller之间的分割。比方,如果用户抉择了一个tableView里的cell,parentViewController须要晓得这件事以便可能响应点击工夫。所以最好的办法是table view controller定义一个协定,同时parent view controller实现这个协定。 @protocol DetailViewControllerDelegate-(void)didSelectCell; @end @interface ParentViewController () <DetailViewControllerDelegate> @end @implementation ParentViewController //.... ...

August 22, 2020 · 2 min · jiezi

关于iOS开发:iOS开发-简化view-controller

导语view controller通常是一个我的项目中最宏大的文件,因为它外面常常蕴含了不属于它的代码,同时这也使它成为代码中最难以重用的局部。所以为view controller瘦身,让其中的代码复用性更强,把相干代码放到正确的中央显得尤其重要。iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 将Data Source和其余协定拆散为view controller瘦身最无效的办法就是把UITableViewDataSource中的代码移动到相干的类中,具体的办法能够参阅《iOS利用开发 扼要TableView》中的相干实现。 而更进一步,不只是TableView,这个办法能够扩大到其余的协定上,比方UICollectionViewDataSource。如果在开发中抉择应用UICollectionView代替UITableView时,这个办法能够让你简直不必批改viewController中的任何货色,甚至能够让Data Source同时反对两个协定,给予了极大的便利性。 将弱业务逻辑移到Model中注:markdown对代码块的语法是开始和完结行都要增加:```,其中 ` 为windows键盘左上角 首先是代码,以下的代码是帮忙用户查找优先事项的列表: -(void)loadPriorities {     NSDate *now = [NSDate date];     NSString *formatString = @"startDate <= %@ AND endDate >= %@";     NSPredicate *predicate = [NSPredicate predicateWithFormat:formatString, now, now];     NSSet *priorities = [self.user.priorities filteredSetUsingPredicate:predicate];     self.priorities = [priorities allObjects]; } 然而,如果把这些代码移动到User类中会让它变得更加清晰,这时ViewController.m中会是: -(void)loadPriorities {     self.priorities = [self.user currentPriorities]; } 而User + Extensions.m中则是: -(NSArray *)currentPriorities {     NSDate *now = [NSDate date];     NSString *formatString = @"startDate <= %@ AND endDate >= %@";     NSPredicate *predicate = [NSPredicate predicateWithFormat:formatString, now, now];     return [[self.priorities filteredSetUsingPredicate:predicate] allObjects]; } 将这些代码移动的根本原因是因为ViewController.m是大部分业务逻辑的载体,自身代码的复杂度曾经很高,所以这类跟业务关联不大的代码比方日期转换、图像裁剪、设定过滤器等的操作能够拆散到各自的类中实现,一方面为viewController减负,另一方面也能增进代码的复用。 对于这个题目的翻译我斟酌了比拟久的工夫,因为在原文中是“Move Domain Logic into the Model”,意为“把畛域逻辑移到Model中”。对于“畛域逻辑”一词我进行过讲究,大抵意思为“稳固的、不会扭转的逻辑关系”,同时在原文中也是应用了NSPredicate作为例子援用,而我认为其例子中的代码也是与业务相干的,只不过关联性不大,而且不会轻易改变,所以应用了“弱业务逻辑”一词代替了“畛域逻辑”一词。把数据处理的逻辑移到服务层一些代码可能没方法很无效的挪动到model中,然而这些代码却和model中的代码有清晰的关联,对于这种问题,能够应用Store。比方在上面的代码中,viewController须要实现从一个文件中获取一些数据,并对其进行操作: -(void)readArchive  {     NSBundle *bundle = [NSBundle bundleForClass:[self class]];     NSURL *archiveURL = [bundle URLForResource:@"photodata" withExtension:@"bin"];     NSDate *data = [NSData dataWithContentsOfURL:archiveURL options:0 error:NULL];     NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];     _users = [unarchiver decodeObjectOfClass:[NSArray class] forKey:@"users"];     _photos = [unarchiver decodeObjectOfClass:[NSArray class] forKey:@"photos"];     [unarchiver finishDecoding]; } 事实上,view controller不须要分明怎么实现这些货色,而应该将这些解决交给一个store object来实现。 通过对代码进行拆散,可能增进代码复用、对代码进行单元测试、放弃view controller整洁等。同时可能让view controller更多关注于业务自身的内容,把数据的读取 、缓存、新建等操作交给服务层来解决。 把网络服务的逻辑移到Model层这与下面提到的十分相似:不要把网络服务的逻辑放到view controller中,而应该把它们寄存到不同的类中。 对于view controller,应该只是应用一个completion block来调用这些办法,而把网络申请、错误处理、缓存解决交给这些类来实现 ...

August 21, 2020 · 1 min · jiezi

关于iOS开发:iOS内存管理浅析

Objective-C内存治理的对象iOS开发中,内存中的对象次要有两类,一类是值类型,比方int、float、struct等根本数据类型,另一类是援用类型,也就是继承自 NSObject类的所有的OC对象。前一种值类型不须要咱们治理,后一种援用类型是须要咱们治理内存的,一旦治理不好,就会产生十分蹩脚的结果。 为什么值类型不须要治理,而援用类型须要治理呢?那是因为他们分配内存形式不一样。 值类型会被放入栈中,他们顺次严密排列,在内存中占有一块间断的内存空间,遵循先进后出的准则。援用类型会被放到堆中,当给对象分配内存空间时,会随机的从内存当中开拓空间,对象与对象之间可能会留有不确定大小的空白空间,因而会产生很多内存碎片,须要咱们治理。 栈内存与堆内存从性能上比拟,栈内存要优于堆内存,这是因为栈遵循先进后出的准则,因而当数据量过大时,存入栈会显著的升高性能。因而,咱们会把大量的数据存入堆中,而后栈中寄存堆的地址,当须要调用数据时,就能够疾速的通过栈内的地址找到堆中的数据。 值类型和援用类型之间是能够互相转化的,把值类型转化为援用类型的过程叫做装箱,比方把int包装为NSNumber,这个过程会减少程序的运行时 间,升高性能。而把援用类型转为值类型的过程叫做拆箱,比方把NSNumer转为float,在拆箱的过程中,咱们肯定要留神数据原有的类型,如果类型错 误,可能导致拆箱失败,因而会存在安全性的问题。手动的拆箱和装箱,都会减少程序的运行工夫,升高代码可读性,影响性能。 在IOS开发过程中,栈内存中的值类型零碎会主动治理,堆内存中的援用类型是须要咱们治理的。每个OC对象外部都专门有四个字节来存储援用计数器, 它是一个整数,示意对象被援用的次数,通过它能够判断对象是否被回收,如果援用计数为0,对象回收,不为0不回收。当对象执行alloc、new或者 retain时,援用计数加1,release时,援用计数减1。

August 17, 2020 · 1 min · jiezi

详解-WWDC-20-SwiftUI-的重大改变及核心优势

导读6月23日凌晨 1 点,苹果 WWDC20 开发者大会在线上以主题演讲的形式,在 Apple Park 进行直播。 23-26日,苹果公开了 100 多个面向开发者的视频,内容涵盖Swift / SwiftUI 、App Clips、Widgets、Privacy & Security 等等方面。 对于开发者和程序员来说,咱们有哪些新发现和新思考? 淘系技术客户端团队,将给大家带来一系列对于新零碎背地的启发,欢送交换探讨。 本篇内容来自于阿里巴巴淘系技术部,淘宝客户端iOS架构组,高级开发工程师倾寒。 前言SwiftUI 是苹果公司于 2019 年推出的 Apple Platform 的新一代申明式布局引擎,笔者于去年第一工夫降级 Beta 尝鲜全家庭,并在短时间内迅速落地了基于 SwiftUI 的外部 APP, 也分享了几篇对于 SwiftUI 的文章, 但 SwiftUI 1.0 根本没有任何公司敢用在正式上线的主 APP 上,API 在 Beta 版本之间各种废除,UI 款式常常不兼容,大列表性能差,彼时都标识着 SwiftUI 还称为一个 Toy Framewrok. 随着 WWDC 20 相干新个性和介绍视频的释出,都明确的宣告着 SwiftUI 元年曾经到了,SwiftUI 曾经成长为新时代的布局引擎。 以下从几个方面分享对于 SwiftUI 的重大扭转及外围劣势。 PS: 须要读者对 Swift 及 SwiftUI 1.0 有肯定相熟。 ...

July 15, 2020 · 4 min · jiezi