关于ios:UIButton-状态新解

本文作者:谭歆0x0 控件状态作为 iOS 开发者,一提到控件,就不得不提到 UIButton,它做为 iOS 零碎最罕用的响应用户点击操作的控件,为咱们提供了相当丰盛的性能以及可定制性。而咱们的日常工作的 80% ~ 90% 做是在与 UI 打交道,解决控件在用户的不同操作下的不同状态,最简略的,比方用户没有登录时,按钮置灰不可点击,用户点击时呈现一个反色成果反馈到用户等等。对罕用状态的定义,零碎在很早的时候就给出了: typedef NS_OPTIONS(NSUInteger, UIControlState) { UIControlStateNormal = 0, UIControlStateHighlighted = 1 << 0, // used when UIControl isHighlighted is set UIControlStateDisabled = 1 << 1, UIControlStateSelected = 1 << 2, // flag usable by app (see below) UIControlStateFocused API_AVAILABLE(ios(9.0)) = 1 << 3, // Applicable only when the screen supports focus UIControlStateApplication = 0x00FF0000, // additional flags available for application use UIControlStateReserved = 0xFF000000 // flags reserved for internal framework use};咱们个别事后设置好 UIButton 在不同状态下的款式,而后间接改对应状态的 bool 值即可,应用上比拟不便。 ...

October 14, 2020 · 3 min · jiezi

关于ios:swift53-UIScrollView-动态计算-contentSize

UIScrollView 的非凡之处就在于当它遇到了AutoLayout之后其contentSize 的计算规定有些非凡。contentSize是依据子视图的leading/trailing/top/bottom进行确定的 所以防止咱们手动去设置 contentSize,咱们必须投合它的规定去设置 间接上代码 let scrollView = UIScrollView() scrollView.backgroundColor = .gray view.addSubview(scrollView) scrollView.snp.makeConstraints { (make) in make.edges.equalToSuperview() } let containerView = UIView() containerView.backgroundColor = .blue scrollView.addSubview(containerView) containerView.snp.makeConstraints { (make) in make.edges.equalToSuperview() make.width.equalToSuperview() } let view1 = UIView() view1.backgroundColor = .orange let view2 = UIView() view2.backgroundColor = .blue containerView.addSubview(view1) containerView.addSubview(view2) view1.snp.makeConstraints { (make) in make.top.equalToSuperview() make.width.equalToSuperview() make.height.equalTo(500) } view2.snp.makeConstraints { (make) in make.top.equalTo(view1.snp.bottom) make.bottom.equalTo(containerView.snp.bottom) make.leading.trailing.equalTo(containerView) make.width.equalToSuperview() make.height.equalTo(500) }大略就是这意思,咱们通过一个填满的 containerView 去设置子视图,同时咱们最初一个 subview 的 bottom 肯定要与 containerView 对齐即可 ...

October 13, 2020 · 1 min · jiezi

关于ios:仿扫描全能王的选择区域功能拍照旋转

拍照,用零碎的,简略 本文次要是讲,抉择区域的旋转 照片的旋转,用仿射变换抉择区域的旋转,就是旋转坐标系中的点,有一个坐标变换手机 UIKit 框架下, view 的坐标系原点,是 view 的左上角 旋转坐标系中的点,个别坐标系用核心,不便 拍照,略。开始旋转抉择区域1, 摆放好 下面有两个视图,放照片的 UIImageView, 和照片上拖拽视图 sketch 布局没有采纳,束缚 因为旋转的时候,他们的 frame 变来变去, 间接手动计算 frame, 更加的直观 if let img = image{ let s = img.size.size(in: measure.s) imgView.frame.size = s imgView.center = measure.center sketch.frame = imgView.frame // 照片 view.addSubview(imgView) // 照片上的,拖拽区域 view.addSubview(sketch) // ... }零碎拍照,默认分辨率, 4 : 3 为了简化计算,这里 imageView 的高/宽 = 其 image 的高/宽 拍照的图片,很大,适合的放在指定的小区域中 extension CGSize{ func size(in std: CGSize) -> CGSize{ let hRatio = height / std.height let wRatio = width / std.width let reSolution = height / width let s: CGSize if hRatio > wRatio{ // 图片更窄 s = CGSize(width: std.height / reSolution, height: std.height) } else{ // 图片更宽 s = CGSize(width: std.width, height: std.width * reSolution) } return s }}2, 旋转从图 a 到图 b , 是一个右旋 ...

October 13, 2020 · 3 min · jiezi

关于ios:iOS-14Widget开发

Widget 相似一个迷你版的 App,能够快速访问 App 提供的信息—比方天气、事件、笔记等。Widget 还能够充当“快捷方式”,点击它会立刻跳转到 App 的指定地位。 介绍WidgetKit 通过在 iOS 主屏幕或 macOS 告诉核心搁置小部件,让用户能够随时拜访 App 中的内容。Widget 能够放弃更新,从而让用户取得最新信息。当须要查看 App 的更多细节时,Widget 会间接跳转到 App 中的适当地位。Widget 有三种不同的尺寸(小号、中号和大号),能够对 Widget 进行个性化定制。要实现一个 Widget,须要给利用增加一个 Widget 扩大并只能应用 SwiftUI 来实现 Widget 的内容。App实现Widget 寄宿于 App,所以首先必须将 App 性能实现。 增加Widget点击我的项目,抉择File > New > Target。从Application Extension中,抉择Widget Extension,而后点击Next。输出扩展名的名称。单击Finish。此时会生成一个新文件夹,蕴含以下内容 扩展名.swift扩展名.intentdefinitionAssets.xcassetsInfo.plist数据共享App 与 Widget 能够通过网络数据和本地数据两种形式进行数据的共享。 网络数据可通过 URLSession 实现数据的申请与解析。本地数据共享能够通过 App Groups,它是 iOS 8 之后推出的在 App 之间共享数据的形式,只须要简略的配置就能够实现数据的共享。(本文以此为例)配置App 在Signing&Capabilities中关上App Groups,内容个别为group.Bundle Identifier。Widget 必须在Signing&Capabilities中关上App Groups,内容与 App 保持一致。 如果文件须要共享,能够选中 App 中须要共享给 Widget 的文件,而后勾选 Widget 的 Target。实现配置实现当前,能够通过UserDefaults或FileManager来实现 App 与 Widget 的数据共享,这里以UserDefaults为例,因为 SwiftUI 提供了@AppStorage来简化操作。 ...

October 12, 2020 · 2 min · jiezi

关于ios:iOS-Universal-link-入门指南

1.1 Universal link 是什么Universal Link是苹果在WWDC上提出的iOS9的新个性之一。此个性相似于深层链接,并可能不便地通过关上一个Https链接来间接启动您的客户端利用(手机有装置App)。对比起以往所应用的URL Scheme,这种新个性在实现web-app的无缝链接时可能提供极佳的用户体验。 当你的利用反对Universal Link(通用链接),当用户点击一个链接是能够跳转到你的网站并取得无缝重定向到对应的APP,且不须要通过Safari浏览器。如果你的利用不反对的话,则会在Safari中关上该链接。在苹果开发者中能够看到对它的介绍是: Seamlessly link to content inside your app, or on your website in iOS 9 or later. With universal links, you can always give users the most integrated mobile experience, even when your app isn’t installed on their device.1.2 Universal link 的利用场景应用Universal Link(通用链接)能够让用户在Safari浏览器或者其余APP的webview中拉起相应的APP,也能够在APP中应用相应的性能,从而来把用户引流到APP中。 这具体是一种怎么的情景呢?举个例子,你的用户safari外面浏览一个你们公司的网页,而此时用户手机也同时装置有你们公司的App;而Universal Link可能使得用户在关上某个详情页时间接关上你的app并达到app中相应的内容页面,从而施行用户想要的操作(例如查看某条新闻,查看某个商品的明细等等)。比方在Safari浏览器中进入淘宝网页点击关上APP则会应用Universal Link(通用链接)来拉起淘宝APP。 1.3 Universal link 跳转的益处唯一性: 不像自定义的URL Scheme,因为它应用规范的HTTPS协定链接到你的web站点,所以个别不会被其它的APP所申明。另外,URL scheme因为是自定义的协定,所以在没有装置 app 的状况下是无奈间接关上的(在Safari中还会呈现一个不可关上的弹窗),而Universal Link(通用链接)自身是一个HTTPS链接,所以有更好的兼容性;平安: 当用户的手机上安装了你的APP,那么零碎会去你配置的网站下来下载你上传上去的阐明文件(这个阐明文件申明了以后该HTTPS链接能够关上那些APP)。因为只有你本人能力上传文件到你网站的根目录,所以你的网站和你的APP之间的关联是平安的;可变: 当用户手机上没有装置你的APP的时候,Universal Link(通用链接)也可能工作。如果你违心,在没有装置你的app的时候,用户点击链接,会在safari中展现你网站的内容;简略: 一个HTTPS的链接,能够同时作用于网站和APP;公有: 其它APP能够在不须要晓得你的APP是否装置了的状况下和你的APP互相通信。Universal link配置和运行2.1 配置App ID反对Associated Domains登录https://developer.apple.com/ 苹果开发者核心,找到对应的App ID,在Application Services列表里有Associated Domains一条,把它变为Enabled就能够了。 ...

October 10, 2020 · 3 min · jiezi

关于ios:关于input在iOS下会变成圆角的解决

-webkit-appearance:none;border-radius:0; /*革除ios默认圆角*/这两个css写到input下面霎时input就复原了失常

October 10, 2020 · 1 min · jiezi

关于ios:苹果手机-input框兼容性input-在iPhone-上-上边框有阴影

一、款式复现h5挪动端开发,发现在苹果手机上input显示有问题。input的border曾经初始化设置为none了,依据需要进行了border款式的重置。但在苹果手机上渲染有问题。如下图所示: 二、解决方案: input{ outline: none; -webkit-appearance: none; /*去除零碎默认的款式*/ -webkit-tap-highlight-color: rgba(0, 0, 0, 0); /* 点击高亮的色彩*/}三 ios 对click有兼容性 设置款式 cursor:pointer;四、挪动端input框 在手机页面中无奈输出文字的问题-moz-user-select: none;-webkit-user-select: none;

October 10, 2020 · 1 min · jiezi

关于ios:iOS开发你面试能用到的iOS面试题二

题目起源自这里,笔者对常识类问题和教训类问题做了解答,答案有脱漏的中央心愿大家能补充,这是你能用到的面试题(一) 为大家总结一份残缺的2020年《大厂最新常问iOS面试题+答案》,面试题合集答案、复习资料,均有残缺PDF版,须要的小伙伴加iOS技术分享群:761407670,群文件间接获取!Push Notification 是如何工作的?推送告诉分为两种,一个是本地推送,一个是近程推送 本地推送:不须要联网也能够推送,是开发人员在APP内设定特定的工夫来揭示用户干什么近程推送:须要联网,用户的设施会于苹果APNS服务器造成一个长连贯,用户设施会发送uuid和Bundle idenidentifier给苹果服务器,苹果服务器会加密生成一个deviceToken给用户设施,而后设施会将deviceToken发送给APP的服务器,服务器会将deviceToken存进他们的数据库,这时候如果有人发送音讯给我,服务器端就会去查问我的deviceToken,而后将deviceToken和要发送的信息发送给苹果服务器,苹果服务器通过deviceToken找到我的设施并将音讯推送到我的设施上,这里还有个状况是如果APP在线,那么APP服务器会于APP产生一个长连贯,这时候APPF服务器会间接通过deviceToken将音讯推送到设施上什么是 Runloop?是一个与线程相干的机制,能够了解为一个循环,在这个循环外面期待事件而后处理事件.而这个循环是基于线程的,在Cocoa中每个线程都有它的runroop,通过他这样的机制,线程能够在没有事件要解决的时候劳动,有事件运行,加重CPU压力,这题能够衍生出为什么在滑动时会导致定时器失败,在上面有解答 Toll-Free Bridging 是什么?什么状况下会应用?Toll-Free Bridging用于在Foundation对象与Core Foundation对象之间替换数据,俗称桥接 在ARC环境下,Foundation对象转成 Core Foundation对象 应用__bridge桥接当前ARC会主动2个对象应用__bridge_retained桥接须要手动开释Core Foundation对象在ARC环境下, Core Foundation对象转成 Foundation对象 应用__bridge桥接,如果Core Foundation对象被开释,Foundation对象也同时不能应用了,须要手动治理Core Foundation对象应用__bridge_transfer桥接,零碎会主动治理2个对象当零碎呈现内存正告时会产生什么?会将不在以后窗口上的view临时移除如果放任内存正告,最终会导致软件强制被零碎敞开什么是 Protocol,Delegate 个别是怎么用的?协定是一个办法签名的列表,在其中能够定义若干个办法,恪守该协定的类能够实现协定里的办法,在协定中应用@property只会生成setter和getter办法的申明delegate用法:成为一个类的代理,能够去实现协定里的办法autorelease 对象在什么状况下会被开释?分两种状况:手动干涉开释和零碎主动开释 手动干涉开释就是指定autoreleasepool,以后作用域大括号完结就立刻开释零碎主动去开释:不手动指定autoreleasepool,Autorelease对象会在以后的 runloop 迭代完结时开释 kCFRunLoopEntry(1):第一次进入会主动创立一个autoreleasekCFRunLoopBeforeWaiting(32):进入休眠状态前会主动销毁一个autorelease,而后从新创立一个新的autoreleasekCFRunLoopExit(128):退出runloop时会主动销毁最初一个创立的autorelease为什么 NotificationCenter 要 removeObserver? 如何实现主动 remove?如果不移除的话,万一注册告诉的类被销毁当前又发了告诉,程序会解体.因为向野指针发送了音讯实现主动remove:通过自释放机制,通过动静属性将remove转移给第三者,解除耦合,达到主动实现remove当 TableView 的 Cell 扭转时,如何让这些扭转以动画的模式出现?这里举个例子,点击cell当前以动画模式扭转cell高度 @interface ViewController ()@property (nonatomic, strong) NSIndexPath *index;@end@implementation ViewControllerstatic NSString *ID = @"cell";- (void)viewDidLoad { [super viewDidLoad];}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; cell.textLabel.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row]; return cell;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 20;}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ if(self.index == indexPath){ return 120; } return 60;}- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ self.index = indexPath; [tableView deselectRowAtIndexPath:indexPath animated:TRUE]; // 重点是这2句代码实现的性能 [tableView beginUpdates]; [tableView endUpdates];} 为什么 UIScrollView 的滚动会导致 NSTimer 生效?定时器外面有个runoop mode,个别定时器是运行在defaultmode上然而如果滑动了这个页面,主线程runloop会转到UITrackingRunLoopMode中,这时候就不能解决定时器了,造成定时器生效,起因就是runroop mode选错了,解决办法有2个,一个是更改mode为NSRunLoopCommonModes(无论runloop运行在哪个mode,都能运行),还有种方法是切换到主线程来更新UI界面的刷新 ...

October 9, 2020 · 2 min · jiezi

关于ios:iOS-14下面图片无法加载包括weexYYAnimateViewSDAnimatedImageView

降级xcode12后,编译运行App发现大片大片的图片加载不进去,包含weex的图片和YYAnimateView的图片都有问题。 通过一番钻研之后,发现是iOS 14下UIKit对 displayLayer:的解决机制有所变动。displayLayer:是CALayerDelegate的代理办法。在iOS 14之前,UIKit在调用这个办法之前就会去渲染UIImageView.image。而在iOS 14,UIKit则是先去调用代理办法,如果你实现了displayLayer:这个办法,那么UIKit就不会再去渲染了。 如果改成上面这样就能够失常加载了: - (void)displayLayer:(CALayer *)layer { UIImage *currentFrame = _curFrame; if (currentFrame) { layer.contentsScale = currentFrame.scale; layer.contents = (__bridge id)currentFrame.CGImage; } else { // If we have no animation frames, call super implementation. iOS 14+ UIImageView use this delegate method for rendering. if ([UIImageView instancesRespondToSelector:@selector(displayLayer:)]) { [super displayLayer:layer]; } }// if (_curFrame) {// layer.contents = (__bridge id)_curFrame.CGImage;// }}参考: https://github.com/apache/inc...https://github.com/ibireme/YY...https://github.com/SDWebImage...原地址:https://y500.me/2020/09/29/im...

September 29, 2020 · 1 min · jiezi

关于ios:iOS动态View的探索

大家始终都在寻求可能动静更新业务的办法,对于这方面的框架也是层出不穷。自从 Facebook 推出 React Native 当前,便以其良好的兼容性和性能劣势占据了这方面的领先地位,携程也在此基础上开源了CRN 框架。 如果是新业务,用CRN 开发是十分适合的,开发效率高,双平台兼容性好。但如果要把已有的Native 页面转CRN,简单的外围页面老本会有点高。在不减少人手的状况下,要想同时进行业务的迭代和CRN 的转换,会有点力不从心。 如果硬转,周期会很长。以携程酒店主流程页面之一的订单详情页为例,在没有额定减少人手的状况下,前后花了几个月工夫,才陆陆续续实现了90% 的性能转CRN,过程尤为艰苦。订单详情页是主流程页面中绝对简略的,如果要转酒店详情页,光是几百行的ViewModel 就曾经让人望而生畏了。563513413,不论你是大牛还是小白都欢送入驻 对此,咱们思考能不能采纳一种让Native 和CRN 共存的形式,这样既能够保留Native 的业务逻辑,又能够在UI 层面做到灵活应变。最要害的是,能够分模块的开发,而不必像转CRN 那样必须整个页面一起上。 当然,Native 和CRN 混合的解决方案早就有了,然而当CRN 作为一个子View 呈现在Native 页面里的时候,因为CRN 的框架比拟重量级,在性能上并不是特地现实,而且和Native 的交互也不是特地不便,所以咱们开始思考有没有更为轻便的解决方案。 在比拟了多种跨平台计划之后,首先排除了相似Lua 这种须要依赖第三方库,且语法非主流的计划,最终决定采纳原生零碎就自带反对的,且语法有着宽泛大众根底的JavaScript。 在iOS7 之前,要在Native 环境中和JavaScript 交互是非常简单且性能无限的,基本上只有依附Webview 的EvaluateJavaScript 来注入执行一段JS 脚本。从iOS7 开始,苹果引入了JavaScriptCore 这个库,登时给iOS 的开发带来了天翻地覆的变动。 为什么会这么说呢,首先来看一下JavaScriptCore 中所蕴含的两个要害类,JSContext 和JSValue: JSContext JSContext 提供了一个在 APP 中执行 JavaScript 代码的环境,使得咱们能够间接在 Objective-C 或 Swift 代码中间接调用 JavaScript 代码,并失去返回后果,反过来也能够裸露办法和类供 JavaScript 调用。 JSValue JSValue 则是一个 JavaScript 数据类型在 Objective-C 或 Swift 中的包装对象,借助于这个对象咱们能够在 Native 代码和 JavaScript 代码之间相互传值,这两者之间的对应关系如下图所示: ...

September 29, 2020 · 3 min · jiezi

关于ios:iOS14剪切板探究淘宝实现方法分析

随着iOS 14的公布,剪切板的滥用也被大家所通晓。只有是APP读取剪切板内容,零碎都会在顶部弹出揭示,而且这个揭示不可能敞开。这样,大家在应用APP的过程中就可能看到哪些APP应用了剪切板。 正好咱们本人的利用也应用了剪切板,降级了iOS 14之后弹的着实让人心烦。就想着怎么解决一下,翻了一下UIPasteboard的文档,发现相干的内容并不多。读取UIPasteboard的string、strings、URL、URLs、image、images、color、colors的时候会触发零碎提醒。应用hasStrings、hasURLs、hasImages、hasColors等办法的时候不会触发零碎提醒。那么思路就是尽可能少的去调用会触发零碎提醒的办法,依据其余办法去判断的确须要读取的时候再去调用那些办法。依据咱们本人的状况,只有判断hasStrings为YES就去读取,又不能清剪切板,其实还是有点不尽人意,而后又看到这个属性: @property(readonly, nonatomic) NSInteger changeCount;The number of times the pasteboard’s contents have changed.Whenever the contents of a pasteboard changes—specifically, when pasteboard items are added, modified, or removed—UIPasteboard increments the value of this property. After it increments the change count, UIPasteboard posts the notifications named UIPasteboardChangedNotification (for additions and modifications) and UIPasteboardRemovedNotification (for removals). These notifications include (in the userInfo dictionary) the types of the pasteboard items added or removed. Because UIPasteboard waits until the end of the current event loop before incrementing the change count, notifications can be batched. The class also updates the change count when an app reactivates and another app has changed the pasteboard contents. When users restart a device, the change count is reset to zero.而后就又加了一个条件,记录一下真正读取剪切板时的changeCount,如果下次读取的时候没有发生变化则不读取。这样一来成果就好多了,利用运行生命周期内,基本上只会弹出一次提醒。 ...

September 28, 2020 · 2 min · jiezi

关于ios:Xcode-升级到120模拟器无法启动问题

降级到Xcode12.1之后,可能会存在如下问题,有趣味的同学能够尝试一下! 点击查看原文地址 1: objc_msgsend too many arguments to function call expected 0 have 3解决办法: Project -> Clear Builder Folder而后 设置 Enable Strict Checking of objc_msgSend Calls为NO敞开XCode 从新关上2: missing one or more architectures required by this target: arm64Xcode12 build error. The linked framework 'Pods_projectA.framework'is missing one or more architectures required by this target: arm64解决办法: Project -> Build Settings -> Excluded Architecture -> Debug -> Any iOS Simulator SDK 增加arm64 ...

September 27, 2020 · 1 min · jiezi

关于ios:Swift-类构造器的使用

程序员连本人写的源代码都不想读, 怎么可能看他人写的源代码! 每半年取得的常识相当于之前取得的全副常识的总和.集体感觉这句话还是蛮有情理的. 反正对于我来说, 每过一段的工夫回过头来看本人写的代码都感觉有很大的重构空间, 很多中央写的不够 PERFECT, 尽管我不是一个处女座, 然而对于代码的强壮和整洁还是很留神的. 接下来, 我来扯一扯谈一谈最近写 Swift 遇到的那些坑问题吧. [](https://draveness.me/swift-zh...首先说下 Swift 给我带来的感触吧, Swift 的刚开始应用的时候感觉还是太特么难用了能够的. 不过 Xcode 在 Swift 上的补全极其慢, 因为 Swift 所有的属性办法都是默认公开的, 所以可能是因为每次都要搜寻全局的符号导致主动补全十分迟缓, 重大影响了工作效率, 有同样的问题的请戳这里. 当然也不排除我电脑配置的影响, 不过重写的过程还是蛮顺利的, 没有遇到太多的问题, 而且应用了很多 Swift 的高级个性来缩减原来简短的 ObjC 代码. [](https://draveness.me/swift-zh... init好了而后, 谈一下我在这两天中写 Swift 时遇到的最大问题 —- 结构器 init 的应用. 注: 咱们在这篇博客中提到的结构器都为类结构器, 在这里不提及值结构器的应用,详见文档. 刚刚应用这个结构器的时候我感觉到很困惑啊, 不就是个 init, 你给我搞这么多事件干什么? 我只想安安静静地初始化 [](https://draveness.me/swift-zh... init当我听从以前写 ObjC 的习惯, 在 Swift 中键入 init 之后, 编译器揭示我: 复制代码 ...

September 27, 2020 · 4 min · jiezi

关于ios:iOS底层系列关联对象

前言之前咱们聊过了,在Category中申明一个属性,能够本人手动实现set和get办法,然而因为没有成员变量,所以说并不能储值。 咱们能够通过runtime的api实现让成员变量能够储值,其实实质也并不是贮存,而是通过关联对象实现了这种看似是能够储值的成果。 咱们能够用上面的办法来设置关联对象。 objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key);明天咱们就来探索一下这种关联对象的实现逻辑。 实现咱们在runtime源码中搜寻objc_setAssociatedObject,最终能够定位到上面这个办法。 _object_set_associative_reference通过简略的剖析源码,咱们能够看出关联对象的实现,大抵是由上面四个类联合实现的。 AssociationsManagerAssociationsHashMapObjectAssociationMapObjcAssociation简略的抽取和简化一下源码,根本能够得出这四个类的关系。 class AssociationsManager { static AssociationsHashMap * _map}typedef DenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap> AssociationsHashMap;typedef DenseMap<const void *, ObjcAssociation> ObjectAssociationMap;class ObjcAssociation { uintptr_t _policy; id _value;};大家也能够看一下上面这幅图。 这里很清晰的表明了这几个类的关系,AssociationsManager有一个AssociationsHashMap类型的属性_map,_map的key是DisguisedPtr<objc_object>类型,value是ObjectAssociationMap类型,而这个ObjectAssociationMap类型中的key是一个指针(void*),value是ObjcAssociation类型。这个ObjcAssociation中有两个重要的是就是属性,_policy和_value。 关联对象的设置就是通过这几个类来实现的,下面咱们也剖析完了这几个类的互相关系,那这些类和咱们在调用objc_setAssociatedObject时传入的参数关系是怎么样的呢?咱们持续剖析源码。 咱们在看一遍上面这办法。 objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)在调用的时候咱们传入了四个参数,第一个就是咱们的被关联对象,第二个是咱们设置的关联对象的key, 第三个就是咱们要存的值,第四个就是关联的策略(相似retain,copy等) 这里先间接说后果吧,其实能够了解为AssociationsManager的属性_map中,以参数object为key,value是一个ObjectAssociationMap类型的map。ObjectAssociationMap中,则是以参数中的key为key,value是一个ObjcAssociation类型的对象,最初咱们参数中的value和policy就贮存在这个ObjectAssociation变量中。 ...

September 26, 2020 · 1 min · jiezi

关于ios:百度App组件化之路

组件化是一个陈词滥调的涉及面很广的话题,即不是做好一件事而是做好一系列的事件能力达成;其中蕴含组件化框架在内的各架构层级、构建零碎、依赖管理系统、以及配套的防劣化机制与规定标准。 本文次要基于百度 App 背景、指标和组件化历程来讲述保障并行开发和组件复用的伎俩,尽量避免过多发散到构建零碎、依赖管理系统, 以及组件化框架这样的具体子方向。组件化的重要性取决于利用规模、团队规模、产品技术指标;所述内容尽管是从 iOS 平台登程,但方法论与实现门路实用于大部分平台。背景与指标百度 App(大型 App) 复杂度起源 业务规模大:百度 App 技术方向及子方向 70+,单端代码量 180w+;指标:隔离各组件间影响防止故障蔓延,并管制整体 App 的复杂度; 团队规模大:有代码权限的数百人 ;指标:保障高效并行开发; 公司外部接入业务多:30+, 非单纯根底库,与百度 App 关系简单;指标:解决接入业务与百度 App 架构及架构中各组件关系,保障疾速高效接入与根底能力复用。 迭代速度快:3 周一个版本,2 周开发 1 周测试;指标:防止高速迭代状况下组件化水平劣化。 技术状态多:H5、NA、Hybrid、Talos、Flutter 并存;指标:保障根底能力复用,构建零碎撑持。另外启动速度、体积等准入流程的束缚;以及指标的多样性也是大型 App 复杂度起源因素;由背景产生的指标是天生的技术需要,除此之外,百度 App 在不同阶段有不同的产品技术指标。 百度 App 不同阶段的不同指标单干业务三方库复用 ; 单个技术组件输入 (最早的需要,2014 年), 对单个组件输入来讲,如何防止输入时, 插入萝卜带出"泥";矩阵产品孵化(2017 年~2019);小程序开源复用(2018 年):输入组件兼容不同宿主, 放弃局部依赖组件可替代性;指标多样性要求在开发时思考到各个指标的诉求,在方案设计时尽量避免和这些指标抵触。 重要架构迭代初始态 -2013(钻木取火):这一时期,百度 App 浏览器角色较重,大家都在一个工程里开发,各业务和根底逻辑交织,没有边界,你中有我、我中有你;UI 架构比较复杂,每个 RD 都要从 App 主入口开始看懂主流程代码,小心翼翼的开发。这一时期的架构是这样:这一时期的次要问题有: 一些根底库、甚至开源三方库都会有业务侵入;没有明确分层和防批改机制,入侵老本极低;首屏各业务间没有容器隔离,牵一发而动全身,极容易相互影响;对各业务共用的服务 (近程配置、端能力) 没有服务组件化,if else/switch case 式逻辑有限蔓延逻辑、资源没有正当归属,数据没有拆分,根底组件对外输入艰难;插件接口层没有体系化建设,稳定性欠佳 (fragile);接入业务成为百度 App 里的超级模块,依赖关系难以管制。iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长!2014-2015(蒸汽机时代):尽管过后团队规模只有几十人,但曾经意识到了组件化的重要性;接入业务逐渐变多,同时也有局部技术组件对外输入的需要;这一阶段: ...

September 26, 2020 · 1 min · jiezi

关于ios:iOS-图像处理技术追踪Core-Image

Core Image 是苹果官网提供的图像处理框架,通过丰盛的 built-in(内置)或自定义 Filter(过滤器)高效解决动态图片、动静图片或视频。开发者还能够通过结构 Filter 链或自定义 Core Image Kernel 来实现更丰盛的成果。在 WWDC20 中,苹果官网针对 Core Image 技术在以下三方面做了优化:Core Image 对视频 / 动图的反对、基于 Metal 构建 Core Image (CI) Kernel 以及 Core Image 的 Debug 反对。 优化 Core Image 对视频 / 动图的反对创立 CIContext创立 CIContext 时,须要遵循一个 view 一个 context 的准则。因为视频的每一帧都会发生变化,将 CIContext 的 cacheIntermediates 属性设置为 false 能够大大减少内存耗费。 如果在应用 Core Image 时将同时使用 Metal(作为输出或输入),通过设置 MTLCommandQueue 属性创立 CIContext 将会是较好抉择。在不应用 MTLCommandQueue 的状况下,每一个 Metal 或 CoreImage 执行的工作都在不同队列中并以 wait 命令分隔开,导致工作执行效率低。通过设置 MTLCommandQueue 创立的 CIContext 和相应的 Metal 工作在同一队列中,能进步 app 的运行效率。 ...

September 25, 2020 · 3 min · jiezi

关于ios:iOS14-debug安装的带有flutter应用从桌面图标重新启动时闪退

刚刚降级遇到的问题,心愿可能帮忙到遇到雷同问题的人。 用xcode12连贯iOS设施调试装置利用拔掉数据线从桌面图标点击进入App必闪退起初发现是flutter的起因,目前有上面两种个解决方案: 应用flutter的release模式 flutter run --release应用flutter的beta版本v1.22参考文章: https://medium.com/flutter/su...https://github.com/flutter/fl...

September 25, 2020 · 1 min · jiezi

关于ios:iOS底层系列KVC

前言明天咱们简略聊一下KVC,键值编码。平时咱们给属性赋值或者取值都是应用点语法,调用属性的set或者get办法,除此之外苹果还为咱们提供另一种办法,应用key或者能够keyPath赋值或者取值。 //赋值- (void)setValue:(nullable id)value forKey:(NSString *)key;- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;- // 取值- (nullable id)valueForKey:(NSString *)key;- (nullable id)valueForKeyPath:(NSString *)keyPath;具体应用咱就不提了,说说KVC底层具体的实现逻辑吧 赋值 当咱们调用了setValue:forKey:的时候,比方咱们执行上面代码 [person1 setValue:@10 forkey:@"age"];零碎会依照setAge:,_setAge:的程序,查找person类中是否实现了这些办法(其中之一即可),如果找到了,则间接调用办法,如果这两个办法否没有找到,上面就从Person类中查找+ (BOOL)accessInstanceVariablesDirectly这个办法的返回值。 默认该办法返回的是YES,通过返回值管制是否容许间接给成员变量赋值。因为有些时候咱们只是创立了一个成员变量,向上面代码中这样,并没有set办法,所以就要看是否容许间接给成员变量设置值。 @interface Person : NSObject{ @public int _age;}@end如果不容许间接给成员变量赋值,则间接抛出NSUnknownKeyException谬误。 如果是容许给成员变量间接设置值,则会依照_age, _isAge, age, isAge顺便,顺次查找成员变量,查找到成员变量,间接赋值,如果找不到这几个成员变量,抛出NSUnknownKeyException谬误。 这就是赋值的整个流程,蛮简略的,可能就是这几个程序容易混掉。 取值取值的流程跟赋值其实是一样的,只是最开始查找的取值办法是不一样的,大家能够对照下图看一下

September 24, 2020 · 1 min · jiezi

关于ios:Charles的配置与使用

PC:MacOS手机:iPhone中文名叫青花瓷,它是一款基于HTTP协定的代理服务器,通过成为电脑或者浏览器的代理,而后截取申请和申请后果达到剖析抓包的目标。 配置手机端开启Charles,使手机与Mac处于同一Wi-Fi环境下,点击Help -> SSL Proxying -> Install Charles Root Certificate on a Mobile Device or Remote Browser 按提醒配置代理,之后装置手机端证书(safari拜访 chls.pro/ssl 默认下载)并信赖(设置 -> 通用 -> 对于 -> 证书信赖设置)。 如果你须要在不同地点办公应用charles,手机端须要增加新证书,并信赖。 Mac端装置证书并信赖(点击之后没反馈就在 keychain 外面搜寻 charles 试试) 开启SSL代理 敞开 macOS proxy,防止烦扰 至此,Charles就应该能够失常应用了。Map 性能Charles 的 map 性能可将某个申请进行重定向,用重定向的内容响应申请的内容。具体分为两种:map local(将某个网络申请重定向到本地某个文件)、map remote(将某个网络申请重定向到另一个网络申请),两者都能够将js、css、html以及api接口进行重定向,此外也能够应用通配符来进行简略的批量匹配,达到批量重定向的目标。Map local在开发过程中应用 map local 性能能够返回自定义数据来笼罩各种测试样例。步骤: 性能开启: Tools → map local -> ✔️ Enable Map Local增加要调试的申请:点击 add 按钮,或在此申请上点击右键,抉择map local。 map from(要调试的线上文件)、map to(本地文件)。 在对应目录创立文件,自定义假数据即可。 Map remote进行一个需要开发,测试环境是:dev.a.com,测试实现,前端开发者上线了,当初QA须要跟踪线上状况,如何切到线上环境?这时就用到了 map remote 。步骤与 map local 相似。 ...

September 24, 2020 · 1 min · jiezi

关于ios:我的-2020-iOS-BAT-面试心得

面试我面试了大大小小的各种公司,BAT、bigo、字节、快手、伴鱼等,因为一些起因,也拒面了一些公司,拿了几家的offer。 伴鱼伴鱼是我筹备后加入的第一轮面试,有很多本人筹备得不是很全,也没有齐全进入面试状态,面试后果不是很好,一面就挂了。 看到本文章如果你正在跳槽或者正筹备跳槽无妨动动小手,增加一下咱们的交换群563513413来获取一份具体的大厂面试材料为你的跳槽多添一份保障。 一面算法题:判断均衡二叉树(easy)代码浏览题:(问输入)TestObject *object1 = [[TestObject alloc] init]; __block TestObject *object2 = [[TestObject alloc] init]; object1.name = @"Mike"; object2.name = @"Sean"; __block int vi = 1; void (^handler)(NSString ) = ^(NSString name) { object1.name = name; object2.name = name; vi = 2; } handler(@"Lucy"); NSLog(object1.name); NSLog(object2.name); NSLog(@"%i", vi); 引申: 如果__block int vi = 1; 这句改成int vi = 1会怎么,为什么代码中的block是什么block,为什么weak的实现原理weak弱援用表是可变的么还是不可变的weak是在什么时候置nil的,如果同时有很多对象对性能影响大怎么办UIView 和 CALayer的关系和区别UIView 和 CALayer在动画上的区别frame和bounds在什么状况下是不相等的bounds x,y 肯定是0,0么,为什么bounds 改成 (50, 50, width, height)会产生什么,view自身,子View?5858我面了很屡次,一开始面的根底研发部门,起初给我转到了企业工具研发,两头工夫拖得有点长,间接拒面了。 ...

September 23, 2020 · 2 min · jiezi

关于ios:iOS开发过程中优雅的调试数据库

背景在开发的时候,数据库的操作始终是一个很辣手的问题,起初发现Android上面有一个第三方的库还挺好用的,就模拟它搞了个iOS的,能够不便的通过浏览器查看、增加、删除、批改数据库。 历史情况咱们来回忆一下调试的过程:如果在模拟器中调试: 找到模拟器利用中数据库的文件地位拷回到一个比拟不便关上的中央装置一个数据库操作软件关上数据库文件select/insert/upate/delete...拷会模拟器利用目录中运行利用,查看后果成果不现实,反复1-7步如果是手机设施,就更麻烦了。。。 解决方案要是有一个能够不必下面这些步骤、不必装置软件既能够随便操作数据库的办法,那就太好了。。。 还真有,先来看看成果: 列出数据库,显示数据库的表和选中表中的所有记录条件查问更新记录:删除记录:辅助性能:显示罕用信息和userdefault的信息,如:利用名字、版本号、build号、Document门路、Cache门路等等 集成办法:在 Podfile中增加:pod 'YYDebugDatabase' run $ pod installapplication:didFinishLaunchingWithOptions中增加一行代码:[[DebugDatabaseManager shared] startServerOnPort:9002];而后就能够在浏览器里不便的增删改查了。 纵情享受吧!能够轻易去fork和star!https://github.com/y500/YYDebugDatabase本篇文章由一文多发平台ArtiPub主动公布

September 22, 2020 · 1 min · jiezi

关于ios:ObjectC-TwoStage-Creationallocinit

在其余语种中例如JAVA,C++,Ruby等这些语言中new是很常见的,然而在object-c中,大家最常见到的和最罕用的初始化办法就是[[ClassName alloc] init]而不是[ClassName new] 去初始化对象。 先来看看他们的办法实现: + new { id newObject = (*_alloc)((Class)self, 0); Class metaClass = self->isa; if (class_getVersion(metaClass) > 1) return [newObject init]; else return newObject;} + alloc { return (*_zoneAlloc)((Class)self, 0, malloc_default_zone()); }- init { return self;}从下面的实现办法来看,其实就是把new拆分成了alloc和init,所以在Cocoa的文档中,这种创建对象的办法也被叫做 Two-Stage Creation 首先咱们看看Cocoa这么设计的初衷是什么 应用初始化办法的时候,不须要管内存调配的形式子类化一个对象时,防止须要实现太多的初始化办法简化长期实例的创立和应用怎么了解呢,举个例子:如果有这样一个对象,处于一些非凡起因,有5中分配内存的形式和10种初始化的形式,如果alloc和init在一起的,那么就须要5*10种构造方法为每一种内存调配形式下提供10中初始化形式。如果alloc和init离开的话,就只须要别离提供5种内存调配形式和10中初始化的形式就能够了。 allocNSObject这个基类提供了两种内存调配的办法:+(id)alloc 和 +(id)allocWithZone:(NSZone *)aZone,这两个办法在被继承的对象中简直从不被重写。+(id)alloc 其实也是调用了 +(id)allocWithZone:(NSZone *)aZone 传入了一个默认的zone参数(等下咱们再具体说下zone)。这两个办法会返回一个指向一个重新分配的内存块的指针并且做了上面几件事件: 把对象的retain count设为1.把对象的isa变量指向对象的class初始化所有的成员变量为默认值(0、nil,0.0 etc.)Zones这个从头说起,每一个Cocoa的利用都有大量的可寻址内存。 当设施上所有物理内存都被占用了,这时有利用还在动静的向操作系统申请内存。这个时候,操作系统就会把内存中的一些内容拷到硬盘(swapping)上从而开释出一部分内存来满足这个要求。 而后利用运行的过程中要须要用到拷到硬盘下来的那局部数据了,操作系统又会把内存中另外一块内容拷到硬盘上,而后把之前拷进来的换回来供给用应用。 因为这样的操作是比拟耗时的,所以这样操作过多时就会造成抖动(thrashing)。 如果常常一起应用的两个object存在内存中比拟“远”的块中,那么造成抖动的机会就会大大的减少。 考虑一下这种状况: 利用须要应用到的其中一个object不在内存中,这个时候就须要把硬盘中的块儿换回来。换回来之后,发现这个object要拜访的另外一个object又不在内存中。这时就须要这时就须要持续从硬盘中换回数据。最坏的状况就是,换第二局部的时候又把第一次的给换出去了。OK,那么zone就是用来保障须要一起应用的object尽量调配的相互凑近的地位,保障,要么都在内存中,要么都在硬盘中,防止下面的状况产生。 不过在OS X 10.5的Object-C 2.0之后,如果你应用了ARC,那么allocWithZone:的zone参数将被疏忽,Apple不在激励应用这个办法,这些操作将默认有Cocoa来实现。 init当内存调配实现之后,就要调用object的实例办法进行初始化了。这些初始化办法通常以init结尾,返回值为id类型。 ...

September 22, 2020 · 1 min · jiezi

关于ios:iOS-面试梳理

本次面试周期为一周,筹备工夫为一周。 本次面试共投递25家,约面11家,最初大厂只面了360、字节,理论面了9家,收到4家offer。 563513413可获取相干的面试材料阐明:16年毕业,非重点大学,非计算机专业,本科 通过这次面试,对本人的定位又有了更多的认知,因为之前工作教训的起因,音视频这块将会成为我今后的次要方向,下一次心愿能做到一个资深iOS音视频工程师,我也会把更多工夫放到这下面。 的确算法能考查一个人的聪慧水平,这段时间齐全被女票碾压,好在算法多做一些,总结法则,也能把人训练的更聪慧,像奥数一样。 倡议大家用C写算法题;平时leetcode也用C。 主观面试感触最右印象较差,面试官不nice;360最佳,很仔细,很喜爱他们的leader;其余公司均不错简直每一家都有算法题,但整体难度不大(大部分是动静布局+树的遍历)360 音视频岗位主观评估:面的是音视频中台的岗位,本认为HR会举荐业务岗,筹备不充沛 一面: 以往直播和相机的业务考查AVFoundation、GPUImage两道算法题(诘问优化)二面: AVPlayer实现原理、数据缓存OpenGL ES 解决流程硬编、软编直播整体流程滤镜实现原理而后回去让我等告诉,说一周内。 抖音 业务岗主观评估:吐槽下,猎头给我很多面试题,让我背,后果一个都没遇到; 心愿大家遇到一个好的面试官 大数相加树的遍历(递归,队列两种形式)事件响应机制(传递链、响应链、手势)算法写进去了但花了50分钟,而后一个小时就过来了,我。。。能力有余,leetcode还要持续。 天真互动主观评估:这家尽管是守业公司,有三面,算上HR是4面,最初一面我感觉面试官程度超高,应该是个大神,被虐,但还是拿到了他家的offer。 xcode 证书校验过程json转model实现动静库动态库区别用纯AVFoundation框架,向视频中退出一个水印怎么做GPUImag框架介绍网络如何优化camke用法视频从采集到显示,最终写入文件流程AVPlayer缓存技术视频如何2倍播放,2倍速导出charles原理samplebuffer与pixelbuffer区别CMTime构造这个人的问题业余水平不逊于360。 最右一面 crash解体怎么解,解体到底层代码AVplayer 遍播遍下载如何设计一个网络库二面 FBO、H264、GPUImage3、大图加载、PCM计算工夫、如何实现宰割滤镜、音视频编码美术宝主观评估:我感觉是最高效的,简洁 kvoblocknotificationrunloop二面有个算法题两次面试加一起50分钟,而后就发offer,牛。 其余公司主观评估:大小公司都会有算法,有的用牛客网,有的用leetcode,纯手撸,无提醒。 NSCache 利用场景 与NSDictionary区别git工作流常见的锁,哪个性能最差,以及起因app逆向剖析leak工具应用charles原理http与https区别组件化思路继续集成计划copy、assign区别内存对齐sel、_cmd、isaTagged pointer剪刀石头布最长不反复字符串大量的数字排序leetcode 32leetcode 1237leetcode 828leetcode 283leetcode j67leetcode 116函数调用机制音讯转发h5、js总结iOS底层: kvo、runtime、kvc、notification、runloop、关键字(copy、assign、strong)、block、GCD其实货色不多,了解底层对于记忆规定,有很大帮忙。倡议源码和《iOS和OS X多线程和内存治理》一起看,以及一些大神的文章 音视频方向: 从AVFoundation动手,而后GPUImage,在而后OpenGL ES、MetalKitffmpeg、opencvcc++rtmp、webrtc其余: 组件化设计模式与准则网络继续集成团队合作流程面试没有遇到Swift的问题,有点意外,这次面试,大概有一半应用swift,有一家纯swift开发,其余都是混编,或者有业务线是swift。 倡议大家先找到工作再辞职,除非工作太忙,没工夫。 对于Swiftswift我也筹备了,预计明年,swift相干的问题会暴发进去 泛型束缚关联类型类型擦除where应用codable 如何实现key映射AnyIteratorsequenceindexablecollectionmap、filter、reduce、sorted如何实现链式编程(snapkit)函数派发机制(class、struct、extension、protocol)kvo生效怎么办内存治理 pwt、vwt内存,对立类型的变量可选值与非选值内存有什么区别

September 21, 2020 · 1 min · jiezi

关于ios:GrowingIO-数据采集-iOS-SDK-测试实践

GrowingIO 是基于用户行为数据的增长平台,精准采集用户行为数据是公司业务的基石,只有及时、精确、牢靠的采集到数据,能力撑持下层的数据分析,用户画像,经营等业务,所以公司始终十分重视数据采集 SDK(Software Development Kit) 的质量保证工作。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 为了满足客户的各种业务与技术的需要,GrowingIO 提供了 Web、Android、 iOS、Hybrid、各种小程序(微信、支付宝、头条、QQ 等 )、微信内嵌页等多种平台,以及 React Native、Flutter 、Cordova、Weex 、API Cloud 、AppCan 泛滥开发框架的 SDK,这无疑为 SDK 的测试工作带来的微小的挑战。 本文次要介绍 GrowingIO 在 iOS SDK 测试方面的具体实际,心愿对从事 iOS 测试的同学提供一些参考。 1. 数据采集 SDK 是如何工作的?要测试一个软件或零碎首先必须要先理解其业务逻辑和技术实现,接下来咱们简略看下数据采集 SDK 是如何工作的。 GrowingIO 的数据采集 SDK 反对无埋点(全埋点)数据采集以及埋点数据采集,以满足不同的业务需要,其繁难构造如下: 在用户关上 App ,浏览不同的页面,点击不同的元素(如按钮,文本框,图片),敞开 App 时,无埋点事件采集模块会将用户的具体行为主动采集并保留到手机的本地存储(对于无埋点数据采集的具体实现,欢送关注 GrowigIO 后续的文章分享,这里不再详述)。 埋点事件采集与之相似,不同之处是埋点事件是由 App 被动调用 SDK 的埋点 API 触发事件采集,当然不同事件的具体数据格式有所不同。 接下来是数据发送模块,其次要负责将数据通过 HTTP API 上报到数据接管服务。 须要阐明的是,为了节约用户的数据流量和电量,发送程序并不是实时上报的,它会依据设施的电量、网络类型、以及数据量进行发送机会的抉择,而且发送前还会对数据进行压缩和混同以升高传输数据量并晋升数据安全性。 当然数据发送程序还会解决数据上报中的各种数据发送失败,网络异样等谬误,采取适当的重试机制。 2. 如何测试?通过以上构造剖析,能够看出数据发送模块跟外围的数据采集业务关系不大,并且很稳固,简直不会改变,因而咱们测试的重点次要是数据采集局部,尤其是无埋点数据采集。 要测试数据采集首先须要有一个蕴含各种页面和元素的 Demo App,而后切换不同的页面,操作页面上的元素或触发埋点事件,而后查看采集到的事件数据是否正确。 ...

September 19, 2020 · 3 min · jiezi

关于ios:sonariOS的实践

架构与整合(Architecture and Integration)iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 先简略介绍一下SonarQube的总览SonarQube是由四局部组成的,如下图所示:[](https://kingdomrain002.github... [ ](https://kingdomrain002.github... 1.SonarQube Server2.一个SonarQube的数据库3.服务器上安装了多个SonarQube插件,可能包含语言,SCM,集成,身份验证和治理插件4.在构建/继续集成服务器上运行一个或多个SonarScanner,以剖析我的项目 SonarQube在CI中地位以下架构显示了SonarQube如何与其余ALM工具集成以及应用SonarQube的各种组件的地位[](https://kingdomrain002.github... [ ](https://kingdomrain002.github... 阐明:开发人员提交代码到SCM(代码治理平台),CI服务器会触发主动构建,并执行运行SonarQube剖析所需的SonarScanner,并推送剖析报告到SonarQube Server,数据存储到SonarQube配置的数据库。开发人员通过SonarQube UI评审,评论他们的问题,以治理和缩小技术债权。并且经理从剖析中接管报告。 Mac环境装置SonarMac环境 12复制代码MacOS:10.15.5 java:1.8.0_111复制代码重点阐明装置不同版本的SonarQube有不同的要求。1.例如SonarQube 7.9之后数据库就不再反对MySQL了。所以依照本文装置要先看下你要装置SonarQube对应版本的要求。这个也是我一开始,装置最新版本SonarQube,数据库配置了MySQL,所以服务始终没有起来的起因。2.Sonar 7.9及更高版本须要JAVA 11。 共事和我说装置SonarQube用Docker不便一些,我为了在我本人电脑上搭建Sonar的环境,抉择了低一点的版本。 我应用的是SonarQube:7.5 和 sonar-scanner-4.3.0.2102[](https://kingdomrain002.github... [ ](https://kingdomrain002.github... 环境配置大抵分为以几个步骤1.下载SonarQube server2.下载SonarScanner3.配置环境变量4.配置数据库5.下载Swift/OC的插件6.启动SonarQube server 1.下载SonarQube server将sonarqube-enterprise-7.5.zip解压,放在/usr/local目录下,倡议重新命名删掉版本后缀。 2.下载SonarScanner将sonar-scanner-cli-4.4.0.2170-macosx.zip解压,放在/usr/local目录下,倡议重新命名删掉版本后缀。 如下图所示[](https://kingdomrain002.github... [ ](https://kingdomrain002.github... 3.配置环境变量关上命令行工具 12复制代码cd ~/ open .bash_profile复制代码增加如下配置,并保留。 1234567复制代码# add sonar-scannersSONAR_RUNNER_HOME=/usr/local/sonar-scannerPATH=$PATH:$SONAR_RUNNER_HOME/bin# add sonarqubeSONARQUBE_HOME=/usr/local/sonarqube/PATH=$PATH:$SONARQUBE_HOME/bin/macosx-universal-64复制代码在终端中执行一下命令 1复制代码source ~/.bash_profile复制代码终端输出命令 sonar-scanner -v,显示如下 12345复制代码INFO: Scanner configuration file: /usr/local/sonar-scanner/conf/sonar-scanner.propertiesINFO: Project root configuration file: NONEINFO: SonarScanner 4.3.0.2102INFO: Java 11.0.3 AdoptOpenJDK (64-bit)INFO: Mac OS X 10.15.5 x86_64复制代码4.配置数据库我本机MySQL的版本如下 ...

September 18, 2020 · 2 min · jiezi

关于ios:iOS笔记-10isKindOfClass与isMemberOfClass

iOS笔记系列目录一 Code- (void)testClassISA {id b1 = [NSObject class];id b2 = [NSObject class];id b3 = [[NSObject new] class];NSLog(@"[NSObject class] = %@ , %@, %@", b1,b2,b3);// trueBOOL res1 = [(id)[NSObject class] isKindOfClass:(id)[NSObject class]];// falseBOOL res2 = [(id)[NSObject class] isMemberOfClass:(id)[NSObject class]];// trueBOOL res3 = [(id)[[NSObject new] class] isKindOfClass:(id)[NSObject class]];// falseBOOL res4 = [(id)[[NSObject new] class] isMemberOfClass:(id)[NSObject class]];// trueBOOL res5 = [(id)[[NSObject new] class] isKindOfClass:(id)[NSObject class]];// trueBOOL res6 = [(id)[[NSObject new] class] isMemberOfClass:(id)[NSObject class]];// falseBOOL res7 = [(id)[Test class] isKindOfClass:(id)[Test class]];// falseBOOL res8 = [(id)[Test class] isKindOfClass:(id)[Test class]];// falseBOOL res9 = [(id)[[Test new] class] isKindOfClass:(id)[Test class]];// falseBOOL res10 = [(id)[[Test new] class] isMemberOfClass:(id)[Test class]];// trueBOOL res11 = [(id)[Test new] isKindOfClass:(id)[Test class]];// trueBOOL res12 = [(id)[Test new] isMemberOfClass:(id)[Test class]];// 1, 0, 1, 0, 1, 1NSLog(@"%d, %d, %d, %d, %d, %d",res1, res2, res3,res4,res5, res6);// 0, 0, 0, 0, 1, 1NSLog(@"%d, %d, %d, %d, %d, %d",res7, res8, res9,res10,res11, res12);}二 源码0.源码解析/// 类办法,返回本身+ (Class)class {return self;}/// 实例办法,查找isa(类)- (Class)class {return object_getClass(self);}Class object_getClass(id obj){if (obj) return obj->getIsa();else return Nil;}inline Classobjc_object::getIsa(){if (isTaggedPointer()) {uintptr_t slot = ((uintptr_t)this >> TAG_SLOT_SHIFT) & TAG_SLOT_MASK;return objc_tag_classes[slot];}return ISA();}inline Classobjc_object::ISA(){assert(!isTaggedPointer());return (Class)(isa.bits & ISA_MASK);}/// 类办法,沿着继承链,去断定isa(类对象isa是元类)和参数是否相等+ (BOOL)isKindOfClass:(Class)cls {for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {if (tcls == cls) return YES;}return NO;}/// 实例办法,沿着继承链,去断定isa(实例对象isa是类)和参数是否相等- (BOOL)isKindOfClass:(Class)cls {for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {if (tcls == cls) return YES;}return NO;}/// 类办法,断定isa(元类)和参数是否相等+ (BOOL)isMemberOfClass:(Class)cls {return self->ISA() == cls;}/// 实例办法,断定isa(类)和参数是否相等- (BOOL)isMemberOfClass:(Class)cls {return [self class] == cls;}总结: ...

September 17, 2020 · 3 min · jiezi

关于ios:新机未到系统先行iOS-14-的实际体验如何

苹果最新的操作系统没有像 iPhone 12 一样一次次推延,库克发表明天公布正式版后,它果然更新了。 当初,用户曾经能够下载 iOS、iPadOS 和 tvOS 的第 14 个版本,能在去年 iOS 13 版为根底的 iPhone、iPad 和 Apple TV 上间接更新。watchOS 7 也能够用于 Apple Watch Series 3、 Apple Watch Series 4 和 Apple Watch Series 5,剩下的 Apple Watch Series 1 和 Apple Watch Series 2 还将持续运行 watchOS 6。 iOS 14 更新 了iPhone 的外围体验 全新的小部件,从新设计的小部件能够放在主屏幕上,小、中和大窗口小部件尺寸使您能够抉择要显示的信息量,天气、时钟、音乐、日历、新闻等小部件都有新的设计。 应用程序,利用程序库会主动将所有利用归类,依据一天中的工夫或地位等信息显示您可能正在寻找的利用,在微动模式下,通过点按屏幕底部的点,能够暗藏主屏幕页面以更快地进入利用。 紧凑的设计,复电和 FaceTime 通话在屏幕顶部显示为横幅,画中画性能可让您在应用其余利用时观看视频或进行 FaceTime 通话。 Memoji,能够自定义 Memoji 头像,还有多种贴纸可选。 地图,自行车路线提供了沿自行车道自行车敌对路线的路线,并思考了海拔或街道的忙碌水平,指南提供餐饮场合的举荐。电动汽车路线安顿显示充电站,当在 GPS 信号较差的城市地区时,“精确定位”可实现高度准确的地位和方向。 翻译,新的翻译应用程序专为对话而设计,能够齐全脱机工作,因而对话放弃私密,反对11种语言的任意组合的语音和文本翻译。 ...

September 17, 2020 · 1 min · jiezi

关于ios:iOS笔记-9Weak与unsafeunretain

iOS笔记系列目录weak润饰的指针变量,在指向的内存地址销毁后,会在Runtime的机制下,主动置为nil。_Unsafe_Unretain不会置为nil,容易呈现悬垂指针,产生解体。然而_Unsafe_Unretain比__weak效率高。@interface MyClass()//@property (nonatomic, strong) NSMutableArray *array;//@property (nonatomic, weak) NSMutableArray *array;@property (nonatomic, unsafe_unretained) NSMutableArray *array;@end@implementation MyClass- (void)test { self.array = @[@"1",@"2"].mutableCopy; void (^block)(void) = ^ { //应用unsafe_unretained上面这行会产生解体,self.array成了僵尸对象 NSLog(@"%@",self.array); }; block(); NSLog(@"---");}

September 16, 2020 · 1 min · jiezi

关于ios:未来的编程语言是什么

世上变动得最快的事物,恐怕就是开发人员须要学习的编程语言了,编程的将来须要更新鲜的办法、更高的稳定性和更优良的实际。本文介绍了 Rust, Swift, Python 和 Kotlin 等最新的热门编程语言,并剖析了这些语言光明的前途。563513413代码的将来实质上与翻新的将来严密相连,而翻新的将来倒退方向将越来越趋势自动化和开源化。 请畅想一下将来的现象,编程会变得更快、更智能,而且因为大量的自动化保驾护航,将来的程序将蕴含更少的缺点。这些都自有它们的情理。 编程的将来须要更新鲜的办法、更高的稳定性和更优良的实际,并且也与咱们将来会有哪些行之有效的翻新成绩非亲非故。 世上变动得最快的事物,恐怕就是新开发人员须要和想要学习的编程语言了。所以,我也在致力追上潮流的步调。当然,你以前可能曾经据说过本文介绍的一些编程语言,然而我还是心愿你能从这一系列前途光明的编程语言中领会到一些新的货色。 软件工程必须一直地对本人进行优化,而这些最新的热门编程语言能够帮忙咱们做到这种优化。 RUST 图片起源: Shaun Bell , Unsplash  — “Rust” 以后有这么多编程语言,你将如何抉择学习从哪一种开始学习呢?首先,我要说的是,对于 RUST 编程语言的广泛热捧并不是空穴来风。 由 Mozilla 开发的 Rust 领有一个十分现代化的包管理系统,它能够装置在简直任何操作系统上,甚至能够利用在嵌入式硬件上。 你能够从官方网站装置 Rust,该网站还提供了该语言的技术文档。RUST 被认为“颇为特地”,是因为以下几个起因。 一般而言,低层编程语言的短处在于其运行速度和对底层的间接管制,而高层编程语言的短处在于其安全性和便捷的开发工具与调试环境,而 Rust 将二者劣势联合在一起。这真是一个绝妙的组合。 拥趸们对 Rust 的酷爱,还有其余起因。Rust 是开源的,而且保障内存平安(Rust 不容许空指针、悬空指针或数据争用),并且它领有相似于 C 和 C++ 语言的语法细节。Rust 被宽泛认为是优雅的、敌对的,尤其是对于那些不足编程教训的人而言,并且它在 web 和操作系统的开发中十分有用。还找得进去什么理由不爱 Rust 呢? 在我看来,在 web 开发人员中,Rust 是增长得最快的软件编程语言,其前景不可估量: 开源可能会挑战 C 和 C++ 等语言以后微小的市场占有率。Swift 图片起源:  Dušan Smetana ,  Unsplash  — “Swfit” TIOBE 指数是一个编程社区的统计,它由位于荷兰埃因霍温的 TIOBE 公司创立和保护,业界用该指数来掂量编程语言的受欢迎水平。 尽管值得注意的是,TIOBE 指数中 Swift 语言 7 月份的排名有所降落,但 Swift 依然是值得咱们思考的一种编程语言。 ...

September 16, 2020 · 1 min · jiezi

关于ios:iOS笔记-8SEL的使用与原理

iOS笔记系列目录一 概念SEL办法名(编号) IMP一个函数指针,保留了办法的地址 @selector(办法名)获取办法的编号,后果是SEL类型。他的行为根本能够等同于C语言中的函数指针 二 区别C语言中,能够间接把函数名赋值给一个函数指针,而且函数指针间接保留了函数地址Objc中的类不能间接利用函数指针,只能应用@selector来获取,获取的是办法的编号三 原理办法以@selector作为索引,@selector的数据类型是SEL,对应每个办法的编号,当咱们寻找办法的时候应用的是这个办法编号。类中存在一个methodLists专门用来寄存办法实现IMP和SEL的映射。办法编号SEL通过Dispatch table表寻找到对应的IMP,IMP就是一个函数指针,而后执行这个办法。 struct objc_class {    struct objc_class super_class;  /*父类*/    const char *name;                 /*类名字*/    long version;                   /*版本信息*/    long info;                        /*类信息*/    long instance_size;               /*实例大小*/    struct objc_ivar_list *ivars;     /*实例参数链表*/    struct objc_method_list **methodLists;  /*办法链表*/    struct objc_cache *cache;               /*办法缓存*/    struct objc_protocol_list *protocols;   /*协定链表*/};typedef struct objc_method *Method;typedef struct objc_ method { SEL method_name; //办法名 char *method_types; //参数类型 IMP method_imp; //办法实现};四 相干class   返回对象的类;isKindOfClass 和 isMemberOfClass查看对象是否在指定的类继承体系中;respondsToSelector 查看对象是否相应指定的音讯;conformsToProtocol 查看对象是否实现了指定协定类的办法;methodForSelector  返回指定办法实现的地址。performSelector:withObject 执行SEL 所指代的办法。

September 16, 2020 · 1 min · jiezi

关于ios:iOS笔记-7iOS消息远程推送流程

iOS笔记系列目录iOS音讯推送流程1.由App向iOS设施发送一个注册告诉,用户须要批准零碎发送推送2.iOS利用向APNS近程推送服务器发送App的Bundle Id和Device UUID3.APNS依据设施的UUID和App的Bundle Id生成deviceToken再发回App4.App再将deviceToken发送给近程推送服务器(本人的服务器),再由服务器保留到数据库中5.当本人的服务器想发送推送时,在近程推送服务器中输出想发送的音讯并抉择发给哪些用户的deviceToken,由近程推送服务器发送给APNS6.APNS依据deviceToken发送给对应的用户

September 15, 2020 · 1 min · jiezi

关于ios:iOS笔记-0iOS笔记系列目录

目录【iOS笔记 #1】SEL的原理与应用【iOS笔记 #2】多线程【iOS笔记 #3】class办法和objc_getClass办法【iOS笔记 #4】Atomic & 自旋锁【iOS笔记 #5】KVC【iOS笔记 #6】iOS自旋锁、互斥锁和递归锁 (继续更新......)

September 15, 2020 · 1 min · jiezi

关于ios:使用DCFrame轻松组合iOS界面

概述DCFrame是一个swift组合界面框架,在线上迭代了2年,目前曾经比较稳定,应用该框架能够实现: 轻松组合治理简单UI模块;零老本迁徙和重用UI模块;模块间无耦合通信。这篇文档会应用3个例子由浅如深介绍怎么应用DCFrame构建iOS界面,并且轻松实现模块间的通信。 简略列表第一个例子咱们来学习怎么应用DCFrame来创立一个繁多cell的简略列表,如下图所示: 要创立这样一个简略列表,须要如下三步: 定义一个 CellModel 和 Cell 类型;创立一个 ContainerModel 来包装 CellModel;应用 ContainerTableView 去加载 ContainerModel。创立 CellModel 和 Cell定义一个 CellModel 类型须要满足如下几个条件: 须要继承自 DCCellModel;定义Cell所须要的数据类型;设置对应Cell的类型和高度。在这个例子外面,Cell只须要一个字符串数据,所以我能够用如下形式定义 CellModel: class SimpleLabelModel: DCCellModel { var text: String = "" required init() { super.init() cellClass = SimpleLabelCell.self cellHeight = 50 }}定义一个 Cell 类型也须要3步: 须要继承自 DCCell;定义UI元素,在setupUI()办法中进行布局;在 cellModelDidUpdate() 办法中更新界面数据。在这个简略列表中,只须要一个 Label 界面元素和一个分割线,所以咱们能够这样来定义 Cell: class SimpleLabelCell: DCCell<SimpleLabelModel> { let label: UILabel = { let label = UILabel() label.font = UIFont.systemFont(ofSize: 17) return label }() let separateLine: CALayer = { let layer = CALayer() layer.backgroundColor = UIColor.lightGray.cgColor return layer }() override func setupUI() { super.setupUI() contentView.addSubview(label) contentView.layer.addSublayer(separateLine) } override func layoutSubviews() { super.layoutSubviews() let bounds = contentView.bounds let left: CGFloat = 15 let height: CGFloat = 1.0 / UIScreen.main.scale label.frame = bounds.inset(by: UIEdgeInsets(top: 8, left: left, bottom: 8, right: 15)) separateLine.frame = CGRect(x: left, y: bounds.height - height, width: bounds.width - left, height: height) } override func cellModelDidUpdate() { super.cellModelDidUpdate() label.text = cellModel.text }}留神: Cell UI 界面的赋值操作倡议放在 cellModelDidUpdate() 办法中, 因为在列表中 Cell 通常会被重用,cellModelDidUpdate() 办法会在 Cell 重用前被回调。 ...

September 15, 2020 · 6 min · jiezi

关于ios:Flutter-和-iOS-之间的-Battle手势交互谁才是老大

跨平台框架都会面对和原生平台沟通的问题,Flutter 也不例外,在理论工程落地的过程中常常会碰到手势辨认交互的问题。本文介绍了西瓜视频解决 Flutter 和 iOS 手势抵触的计划,具体内容如下。 茫茫人海中,你看到这一段文字,节约你三秒钟的工夫,欢送你来一场iOS交换技术的碰撞,互相学习,共同提高技术!563513413 Flutter 进阶:解决 iOS 手势抵触 背景客户端日常开发中,手势辨认是交互设计中不可或缺的性能,为此 Flutter 和 iOS 都提供了一套手势零碎,同时,为了让 Flutter 页面融入进 iOS 原生 UI 中,Flutter 提供了一个 UIView 的子类(这里简称 FlutterView),所有的屏幕点击信息都会通过 UIView 定义的几个办法(touchBegin/Move/Cancel/End)传入 FlutterView,从而被 Flutter 手势零碎解决。 问题西瓜视频在理论应用过程中发现了一个问题,场景是这样:西瓜 iOS 客户端所有页面都有全屏右划退出性能,这个性能的实现是将一个 PanGestureRecognizer 增加到 NavigationController 的 View 上,只有辨认到右划手势,就退出以后页面。 在测试的时候咱们发现 Flutter 页面的列表都不能划动了,怎么回事? 理解 iOS 手势的同学应该晓得一个常识:解决屏幕触摸事件时,GestureRecognizer 领有比 touchXXX 办法更高的优先级,默认状况下 GestureRecognizer 解决不了的触摸事件才会流转到 touchXXX 办法解决。 问题就是因为这个机制引起的:NavigationController 上的 PanGestureRecognizer 生产了所有的触摸事件,并没有把这些事件流转到 FlutterView,所以 Flutter 页面的所有手势都生效了。 第一次尝试既然起因是 FlutterView 没有解决触摸事件的机会,那咱们尝试的指标也明确了:让 FlutterView 有解决的机会就好了,这个也很容易实现,iOS GestureRecognizer 有一个属性 cancelsTouchesInView,这个属性会管制 GestureRecognizer 要不要将触摸事件流转给 UIView 的 touchXXX 办法解决。 ...

September 15, 2020 · 3 min · jiezi

关于ios:IOS下new-Date20200909-hhmmss报错

场景后端返回了一个工夫字符串,形如:'2020-09-09 hh:mm:ss',而后前端业务须要判断以后工夫是否大于/小于这个工夫,于是就有了这样一个比拟: let date = new Date()if(date < new Date(res.endTime) && date > new Date(res.startTime)) { // do something}然而这在安卓上运行失常,可是测试的时候在IOS上报错了。查阅一番得悉,IOS不反对这种格局'2020-09-09 hh:mm:ss'去new Date(),它只反对'2020/09/09 hh:mm:ss'这样的,而安卓下应用new Date()则两种格局都反对。 解决把后端返回的工夫格局转换一下,把'-'替换成'/': // ios下-工夫格式化不了,ios下把-替换为/export function initIosTime (val) { if (isIOS()) { return val.replace(/\-/g, '/').replace('.0', '') } return val}

September 14, 2020 · 1 min · jiezi

关于ios:iOS-代码染色原理及技术实践

背景随着业务的迅速倒退,业务代码逻辑的复杂度减少。QA 测试的品质对于产品上线后的稳定性更加重要。个别 QA 测试的工作流程分为两大项:自动化测试和人工测试。这两种测试后都须要失去代码覆盖率。自动化测试的覆盖率,在双端都有比拟成熟的计划。 本文着重介绍人工测试过程中,怎么失去对应的代码覆盖率。波及到的技术次要是代码染色。以下会先介绍整体的工作流程,再对波及到的技术一一论述。 茫茫人海中,你看到这一篇文章,欢送你来一场iOS交换技术的碰撞,互相学习,共同提高技术!iOS开发交换技术群:563513413 染色流程 流程图中波及到了双端的要害节点以及技术点。咱们重点介绍编译阶段。 编译阶段:生成染色包 (对 IR 文件插桩)须要在编译中减少编译选项,编译后会为每个可执行文件生成对应的 .gcno 文件。 运行阶段:生成二进制覆盖率文件。在测试代码中调用覆盖率散发函数,会生成对应的 .gcda 文件。 解析阶段:将二进制覆盖率文件可视化。编译阶段在上文能够看出,编译阶段最外围的操作是对 IR 文件进行插桩。 什么是 IR 文件?插桩逻辑是什么?咱们往下看。 语言解决零碎 一个残缺的语言解决零碎中,从源程序到可执行的机器代码,如下图所示,历经几个重要模块。而咱们上文提到的 IR 文件,是编译器模块中的产物,插桩解决也是在这个模块中进行。这里重点探讨下编译器。 编译器 说起编译器,咱们理解到的传统编译器架构分为前端、优化器和后端。 传统编译器的劣势是:前端和后端没有齐全拆散,耦合在了一起,因此如果要反对一门新的语言或硬件平台,须要做大量的工作。一种更加灵便,适应性更好的编译器套件应运而生——LLVM. LLVM 官网: www.aosabook.org/en/llvm.htm… LLVM 是一个开源的,模块化和可重用的编译器和工具链技术的汇合,或者说是一个编译器套件。 能够应用 LLVM 来编译 Kotlin,Ruby,Python,Haskell,Java,D,PHP,Pure,Lua 和许多其余语言。 LLVM 外围库还提供一个优化器,对风行的 CPU 做代码生成反对。 LLVM 同时反对 AOT 事后编译和 JIT 即时编译。 2012 年,LLVM 取得美国计算机协会 ACM 的软件系统大奖,和 UNIX,WWW,TCP/IP,Tex,JAVA 等齐名。 LLVM 和传统编译器最大的不同点在于,前端输出的任何语言,在通过编译器前端解决后,生成的两头码都是 IR 格局的。接下来看下 LLVM 架构下的微小劣势,iOS&MacOS 平台的编译器。 ...

September 14, 2020 · 3 min · jiezi

关于ios:iOS底层系列Category

前言Category是咱们平时用到的比拟多的一种技术,比如说给某个类减少办法,"增加"属性,或者用Category优化代码构造。 咱们通过上面这几个问题作为切入点,联合runtime的源码,探索一下Category的底层原理。 咱们在Category中,能够间接增加办法,而且咱们也都晓得,增加的办法会合并到本类当中,同时咱们也能够申明属性,然而此时的属性没有性能,也就是不能存值,这就相似于Swift中的计算属性,如果咱们想让这个属性能够贮存值,就要用runtime的形式,动静的增加。 探索1. Category为什么能增加办法不能"增加"属性首先咱们先创立一个Person类,而后创立一个Person+Run的Category,并在Person+Run中实现-run办法。 咱们能够应用命令行对Person+Run.m进行编译 xcrun -sdk iphonesimulator clang -rewrite-objc Person+Run.m失去一个Person+Run.cpp文件,在文件的底布,能够找到这样一个构造体 struct _category_t { const char *name; struct _class_t *cls; const struct _method_list_t *instance_methods; const struct _method_list_t *class_methods; const struct _protocol_list_t *protocols; const struct _prop_list_t *properties;};这些字段简直都是见名知意了。 每一个Category都会编译而后存储在一个_category_t类型的变量中 static struct _category_t _OBJC_$_CATEGORY_Person_$_Run __attribute__ ((used, section ("__DATA,__objc_const"))) = { "Person", 0, // &OBJC_CLASS_$_Person, (const struct _method_list_t *)&_OBJC_$_CATEGORY_INSTANCE_METHODS_Person_$_Run, 0, 0, 0,};因为咱们的Person+Run外面只有一个实例办法,所以从上述代码中来看,也只有对应的地位传值了。 通过这个_category_t的构造构造咱们也能够看出,变量存储在_prop_list_t,并不是类中的objc_ivar_list构造体,而且咱们都晓得property=ivar+set+get,Category中不会生成ivar,所以基本都不能"增加"成员变量。 如果咱们在分类中手动为成员变量增加了set和get办法之后,也能够调用,但实际上是没有内存来储值的,这就如同Swift中的计算属性,只起到了计算的作用,就相当于是两个办法(set和get),然而并不能领有真用的内存来存储值。 2. Category的办法是何时合并到类中的大家都晓得Category分类必定是咱们的利用启动是,通过运行时个性加载的,然而这个加载过程具体的细节就要联合runtime的源码来剖析了。 runtime源码太多了,咱们先通过大略浏览代码来定位实现性能的相干地位。 我从objc-runtime-new.mm中找到了上面这个办法。 /************************************************************************ methodizeClass* Fixes up cls's method list, protocol list, and property list.* Attaches any outstanding categories.* Locking: runtimeLock must be held by the caller**********************************************************************/static void methodizeClass(Class cls, Class previously)而且他的正文一些的很分明,修复类的办法,协定和变量列表,关联还未关联的分类。 ...

September 14, 2020 · 3 min · jiezi

关于ios:App-iOS-工程编译优化实践

引言开发效率的晋升,是开发者关注的一个永恒的话题。对于 iOS 而言,编译速度始终是影响 iOS 开发和集成测试效率要害的一环。 携程旅行 App iOS 工程编译,经验了从全源码编译到工程组件化,细分 Bundle,再到细分 Bundle 根底上的进一步优化四个阶段。每次的优化革新都是一直联合业务反馈,深刻理解 xcode 编译过程后的成绩。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 一、背景简略回顾一下在做 Bundle 拆分之前的状况,过后整个 iOS 工程的所有代码都在一起,并未做工程拆分和解耦,编译时全都是源码编译,数百万行代码全副编译实现要将近一个小时。所有的开发人员都在一个工程里开发,如果因为某个人提交的代码有问题(这是经常会产生的),导致编译了很长时间之后才报错,更是耽误时间,重大影响开发效率。对于测试人员来说,每次须要验证一个性能时打包测试都须要至多期待几十分钟,这是极大的资源节约。 这个时候的 Build 过程是全源码 complie,几千上万个文件都须要编译、链接,效率可想而知。 携程旅行App iOS工程编译优化实际 所以为了进步开发和测试的效率,进步 iOS 工程的编译速度迫不及待。 二、优化计划2.1 工程组件化第一个优化是把整个工程的编译过程打散,把代码依照业务线拆分成一个个独立的子工程,每个子工程的编译过程都是独立的。每个子工程只须要保障本人工程的源码可能编译胜利,对外输入对立的动态库和资源文件包的产物。这个产物咱们叫做 Bundle。 单个业务工程(Bundle): 携程旅行App iOS工程编译优化实际 App Build: 携程旅行App iOS工程编译优化实际 对于单个业务来说,编译工夫大大缩短,整个 Build 过程变成单工程 complie,多工程 link,极大缩小了 Build 过程中的 complie 破费的工夫。 这样有两个益处: 1)对于开发人员,每个业务开发只须要把本人这个子工程切为源码援用,把其余非本人模块的子工程全副用动态库依赖,本地编译也只须要编译本人的子工程,能够大大晋升本地开发编译速度。 2)对于测试人员,打包过程就变成了把所有曾经编译好的子 Bundle 动态库链接到一个壳工程里,不须要对每个文件进行编译,能够很快的打包测试验证。 2.2 增量编译在工程组件化之后,在继续集成平台上单个 Bundle 的打包工夫还是过长。因而框架团队开始钻研单个 Bundle 在继续集成平台上增量编译的可能性。 通过调研,最终选定 CCache 做为解决方案。CCache 是一个编译工具,能够将 Xcode 编译文件缓存起来,从而达到编译提速。 ...

September 12, 2020 · 2 min · jiezi

关于ios:iOS打包的那一些事情

一、背景在 iOS 开发中,大略每个老手都被各种配置、证书、打包和公布等事件折腾过,我亦如此。 教程一搜一大堆,照着教程 1234 也能做下来。然而在这个过程中,我会产生很多问号: 为什么程序能在模拟器上运行,却无奈在真机上运行?为什么不是每个人都能在本地打包?具备什么条件能力打包?为什么须要证书,形容文件?生成证书的原理是怎么的?… …iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 很多事件是知其然而不知其所以然。 为了解决心中的纳闷,我借着我的项目的机会,钻研了一番整个打包公布的流程,以及流程中每一步操作的背地都产生了什么。 之后便总结成了这篇文章,分享给大家,心愿能使老手 iOS 开发同学对 iOS 的打包、公布和证书体系有更直观的理解。 一个 iOS 利用最终能在用户的设施上应用,是通过了 开发 -&gt; 打包 -&gt; 公布 -&gt; 下载安装 的过程的。 为了更易于了解,以及防止从一开始就陷入细节,本文将逆序讲述整个过程。 二、iOS 利用的装置形式作为一个 iOS 用户,我能通过哪些路径装置 app? App StoreApp Store 是 Apple 官网的 App 公布 平台。在 App Store 中搜寻并装置 App,也是作为一个普通用户最罕用的装置形式。 TestFlightTestFlight 是 Apple 官网的 App 测试 平台。在上架到 App Store 之前,能够通过 TestFlight 邀请一部分用户参加测试,相似于网络游戏的公测。 App Center, FIR…除了官网的 Apple Store 之外,市面上还存在着 App Center, FIR 等非 Apple 官网的 App 治理平台 。在开发过程中,咱们通常会将各个环境的 App 上传到这些非官方的平台中,用于日常测试;另外,咱们也会将其作为企业级利用的最终公布平台。 ...

September 12, 2020 · 3 min · jiezi

关于ios:iOS多线程之GCDOperationQueue-对比和实践记录

简介     在计算的晚期,计算机能够执行的最大工作量是由 CPU 的时钟速度决定的。然而随着技术的提高和处理器设计的紧凑化,热量和其余物理束缚开始限度处理器的最大时钟速度。因而,芯片制造商寻找其余办法来进步芯片的总体性能。他们决定的解决方案是减少每个芯片上的处理器外围数量。通过减少内核的数量,一个独自的芯片能够每秒执行更多的指令,而不必减少 CPU 的速度或扭转芯片的大小或热个性。惟一的问题是如何利用额定的内核。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长!      应用程序应用多核的传统办法是创立多个线程。与依赖线程不同,iOS 采纳异步设计办法来解决并发问题。通常,这项工作波及获取一个后盾线程,在该线程上启动所需的工作,而后在工作实现时向调用方发送告诉(通常通过一个回调函数)。      iOS 提供了一些技术,容许您异步执行任何工作,而无需本人治理线程。异步启动工作的技术之一是 Grand Central Dispatch (GCD)。这种技术采纳线程治理代码,并将该代码移动到零碎级别。您所要做的就是定义要执行的工作,并将它们增加到适当的分派队列中。GCD 负责创立所需的线程,并安顿工作在这些线程上运行。因为线程治理当初是零碎的一部分,GCD 提供了工作治理和执行的整体办法,比传统线程提供了更高的效率。      OperationQueue(操作队列,api 类名为 NSOperationQueue )是 Objective-C 对象,是对 GCD 的封装。其作用十分相似于分派队列。您定义要执行的工作,而后将它们增加到 OperationQueue 中, OperationQueue 解决这些工作的调度和执行。与 GCD 一样, OperationQueue 为您解决所有线程治理,确保在零碎上尽可能疾速无效地执行工作。 GCD、OperationQueue 比照核心理念GCD的外围概念:将 工作(block) 增加到队列,并且指定执行工作的函数。NSOperation 的外围概念:把 操作(异步) 增加到 队列。区别GCD: 将工作(block)增加到队列(串行/并发/主队列),并且指定工作执行的函数(同步/异步)GCD是底层的C语言形成的APIiOS 4.0 推出的,针对多核处理器的并发技术在队列中执行的是由 block 形成的工作,这是一个轻量级的数据结构要进行曾经退出 queue 的 block 须要写简单的代码须要通过 Barrier(dispatch_barrier_async)或者同步工作设置工作之间的依赖关系只能设置队列的优先级高级性能: dispatch_once_t(一次性执行, 多线程平安); dispatch_after(提早); dispatch_group(调度组); dispatch_semaphore(信号量); dispatch_apply(优化程序不敏感大体量for循环);OperationQueue: ...

September 10, 2020 · 5 min · jiezi

关于ios:iOS-新东方面试

作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这是一个我的iOS交换群:761407670 不论你是小白还是大牛欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 1、如何进行 cell 高度的缓存?说一下 UITableView-FDTemplateLayoutCell 的实现原理? 缓存 cell 高度: 如果用的 frame ,则给 model 增加一个 cellH 的属性,而后在获取数据时计算好高度赋值给 cellH。如果用的 AutoLayout,创立相应布局等同的 cell,计算好高度而后缓存。FD 的实现: fd_heightForCellWithIdentifier: configuration: 办法会依据 identifier 以及 configuration block 提供一个和 cell 布局雷同的 template layout cell,并将其传入 fd_systemFittingHeightForConfiguratedCell: 这个公有办法返回计算出的高度。次要应用技术为 runtime 。 2、在 Block 中应用 成员变量 (如:_name) 会造成循环援用吗(比方上面的代码)?如何解决? typedef void(^TestBlock)(void);@interface DetailViewController ()@property (nonatomic, copy) NSString *name;@property (nonatomic, copy) TestBlock block;@end@implementation DetailViewController- (void)viewDidLoad { [super viewDidLoad]; self.name = @"fzh"; self.block = ^() { NSLog(@"%@", _name); };}@end复制代码会造成循环援用,因为 _name 底层也是通过 self 去获取(self->_name)。 ...

September 10, 2020 · 1 min · jiezi

关于ios:GCD梳理与总结封装

后面两节内容笔者次要对GCD的一些基本概念和罕用API做了一个简略的梳理和演绎,对照笔者提供的Demo案例,置信读者对GCD可能有个入门。通过梳理,咱们能够发现,其实GCD的概念并不是很简单,只是初学者往往会被它C语言的大串API以及网上各种很绕的概念给唬住了。剖开表象,看实质。GCD(Grand Central Dispatch)不过是多线程编程的一套API,一个多线程工具。工具自身不应该有难度。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! GCD的这套C语言API,相对来说应用起来比拟繁琐,比拟长,即便在有代码提醒的状况,编码感触也较为不顺畅,在我的项目中不论是和OC还是swift格调上都有那么一点心心相印。所以笔者决定对一些罕用的API进行封装,目标是在根本放弃原有写法构造的根底上,尽量使其更加面向对象,更加简略易用。当然,笔者所封装的只是GCD的冰山一角,目标是应酬95%的我的项目场景,所以还是倡议读者们可能正本清源,在学习好GCD的根底上,批判性的抉择应用,切不可依赖。上面我来谈谈我的封装思路,也期待宽广网友可能在这套根底上持续舔砖加瓦。 后面两章咱们谈到过三个概念:工作,队列,执行队列的形式。 工作:没什么好说的,就是咱们执行的耗时代码,咱们仍然放弃把工作增加到block里的格调。队列:咱们来看一下GCD的写法 `dispatch_queue_t queue = dispatch_queue_create("com.test.testQueue", DISPATCH_QUEUE_SERIAL);`复制代码虽说C语言没有对象的概念,然而这段代码要是用面向对面的概念来解读,不就是创立一个队列对象嘛。所以咱们把队列封装成一个对象。 `#import <Foundation/Foundation.h>@interface GCDQueue : NSObject@property (strong, readonly, nonatomic) dispatch_queue_t dispatchQueue;#pragma mark - 获取零碎队列+ (GCDQueue *)mainQueue;+ (GCDQueue *)globalQueue;+ (GCDQueue *)globalQueue_highPriority;+ (GCDQueue *)globalQueue_lowPriority;+ (GCDQueue *)globalQueue_backgroundPriority;#pragma mark - 创立队列///创立串行队列- (instancetype)initSerial:(NSString *)label;///创立并行队列- (instancetype)initConcurrent:(NSString *)label;///队列挂起- (void)suspend;///队列复原- (void)resume;@end`复制代码执行队列的形式 本来写法 `dispatch_sync(queue, ^{ NSLog(@"同步执行的工作");});dispatch_async(queue, ^{ NSLog(@"异步执行的工作");});`复制代码dispatch_async,dispatch_after诸如此类更像是静态方法的调用,所以咱们创立一个GCDDispatch类,将这些API用静态方法的写法对立封装起来,便于管理和记忆。 `///同步执行+ (void)sync:(GCDQueue *)queue execute:(dispatch_block_t)block;///异步执行+ (void)async:(GCDQueue *)queue execute:(dispatch_block_t)block;///提早执行+ (void)afterSecs:(float)delta queue:(GCDQueue *)queue execute:(dispatch_block_t)block;///反复执行+ (void)apply:(NSInteger)times queue:(GCDQueue *)queue execute:(dispatch_block_num)block;///栅栏(应用的队列应该是你本人创立的并发队列)+ (void)barrier_async:(GCDQueue *)queue execute:(dispatch_block_t)block;///同步栅栏(应用的队列应该是你本人创立的并发队列)+ (void)barrier_sync:(GCDQueue *)queue execute:(dispatch_block_t)block;`复制代码到这里根本的框架曾经搭建实现,还有罕用的如group,semaphore,timer等,都波及到对象的概念,所以咱们把这些都封装成对象,具体就不一一开展了,有趣味的同学能够下载demo查看,也比较简单。 ...

September 10, 2020 · 1 min · jiezi

关于ios:iOS-Mach异常和signal信号

摘要: 本着探索下iOS Crash捕捉的目标,学习了下Crash捕捉相干的Mach异样和signal信号处理,记录下相干内容,并提供对应的测试示例代码。Mach为XNU的微内核,Mach异样为最底层的内核级异样,在iOS零碎中,底层Crash先触发Mach异样,而后再转换为对应的signal信号。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 本着探索下iOS Crash捕捉的目标,学习了下Crash捕捉相干的Mach异样和signal信号处理,记录下相干内容,并提供对应的测试示例代码。Mach为XNU的微内核,Mach异样为最底层的内核级异样,在iOS零碎中,底层Crash先触发Mach异样,而后再转换为对应的signal信号。 iOS Mach异样1.1 XNU Darwin是Mac OS和iOS的操作系统,而XNU是Darwin操作系统的内核局部。XNU是混合内核,兼具宏内核和微内核的个性,而Mach即为其微内核。 Darwin操作系统和MacOS、iOS零碎版本号的对应如上图所示,Mac可执行下述命令查看Darwin版本号。 system_profiler SPSoftwareDataType 1.2 Mach Mach:[mk],操作系统微内核,是许多新操作系统的设计根底。 Mach微内核中有几个根底概念: Tasks,领有一组系统资源的对象,容许"thread"在其中执行。 Threads,执行的根本单位,领有task的上下文,并共享其资源。 Ports,task之间通信的一组受爱护的音讯队列;task可对任何port发送/接收数据。 Message,有类型的数据对象汇合,只能够发送到port。 1.3 模仿Mach Message发送 ● Mach提供大量API,苹果文档介绍较少。 // 内核中创立一个音讯队列,获取对应的port mach_port_allocate(); // 授予task对port的指定权限 mach_port_insert_right(); // 通过设定参数:MACH_RSV_MSG/MACH_SEND_MSG用于接管/发送mach message mach_msg(); 下述代码模仿向Mach Port发送Message,接管Message后做解决: ● 首先调用createPortAndAddListener创立Mach Port; ● 调用sendMachPortMessage:向已创立的Mach Port发送音讯; ● 执行后果示例: 2018-02-27 09:33:37.797435+0800 xxx[54456:5198921] create a port: 41731 2018-02-27 09:33:37.797697+0800 xxx[54456:5198921] Send a mach message: [100]. 2018-02-27 09:33:37.797870+0800 xxx[54456:5199525] Receive a mach message:[100], remote_port: 0, local_port: 41731, exception code: 28672 ● 示例代码: // 创立Mach Port并监听音讯 ...

September 9, 2020 · 3 min · jiezi

关于ios:iOS-开发简单的手绘应用

开发一款简略的 iOS 手绘利用, 收集点,绘制形态,给形态着色,出现给用户,如同就完了框架是 Quartz2D 1, 收集点首先须要有一个界面 UIView, 用这个界面监听用户的手势,收集点 用户按下手指location(in, 从触摸事件中,取得在画板中的坐标 var lastPoint = CGPoint.zerooverride func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touch = touches.first else { return } // ... lastPoint = touch.location(in: view) }用户挪动手指 override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { // ... }用户抬起手指override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { // ... } 2, 绘制形态,给形态着色开拓一块绘图上下文 UIGraphicsGetCurrentContext, 应用采集的点连线 ...

September 5, 2020 · 2 min · jiezi

关于ios:TrueChain分析解读

前言TrueChain中武官网 TrueChain,中文名又译为初链 什么是区块链?是一种分布式资料库最后是宽泛应用在比特币[Bitcoin]保护一份连续不断的交易记录档案每一笔材料被称为一个区块[block]每一个区块能够蕴含一笔以上的交易每个区块都会与另一个区块产生连贯[Linking]每个区块都会蕴含上个区块的hash值所有被连贯在一起的区块被称为链[chain]区块链就是由多个区块组成的链区块链如何运作?产生区块的过程会通过简单的密码学运算[cryptography]简单的密码学运算可杜绝记录篡改与订正每个区块在胜利产生之后是无奈批改的产生区块的过程又称为挖矿[Mining]负责产生区块的人又被称为旷工[Miner]负责产生区块的机器又称为挖矿机每一笔材料都能够通过连贯找出所有牢靠的历史材料[溯源性]因为是分布式数据库,所以具备去[中心化]个性[去中心化]意味着材料会散布到多个节点所有的节点会独特保护整个分布式数据库独特保护整份资料库意味着没人能够说本人的区块才是非法无效的区块独特保护整份资料库意味着少数人验证后过的区块才是非法无效的区块独特保护整份资料库意味着超过50%的节点验证过的区块才是非法无效的区块每个节点必须存储所有区块[但有新的设计可让节点仅存储局部区块]每一个节点都能够帮助验证区块的有效性任何一笔材料被篡改都将毁坏区块的完整性任何一笔材料被篡改的几率微乎及微区块链的写作蕴含两种物件类型[交易]与[区块]讲解情景:数字货币交易物件就是转账过程的残缺内容[区块物件]蕴含一系列交易的汇合[区块]之间[连接起来]就是一本账簿[Ledger]基本原理就是让所有人独特保护一个账簿[Ledger]这份独特保护的账簿必须由大伙独特认证[每个区块都必须有超过50%的节点认证过]什么是TrueChain初链?TrueChain是应用区块链为根底技术,在以太坊的根底上,开发团队臆在打造一条实现疾速,无中断,平安可拓展的根底公链,应用PBFT-fPoW混合共识无权区块链。 收费应用TrueChain承诺:无论是当初的测试网还是将来上线的主网,初链将始终放弃向所有用户收费凋谢的准则。初链始终认为,无需许可链是面向所有用户的基础设施,而非牟利工具。为每位用户提供更贴合需要、应用便捷、低成本的无需许可链开发工具不只能为将来初链寻找适合盈利起源开辟空间,更有助于整个无需许可链开发乃至区块链行业的长足发展。(起源:TrueChain白皮书) 技术初链的技术架构:底层服务:蕴含P2P 网络、LevelDB 数据库、密码学算法、分片优化;核心层: 蕴含区块链模块、TRUE 模块、共识算法模块;API 接口层,包含 TVM 虚拟机、gRPC 通信协定;智能合约层。科普PBFT:拜占庭容错,可能包容将近1/3的谬误节点误差。 其思维渊源来自拜占庭将军问题,是一种解决分布式系统容错问题的通用计划。PBFT算法的外围实践是n>=3f+1,n是零碎中的总节点数,f是容许呈现故障的节点数。换句话说,如果这个零碎容许呈现f个故障,那么这个零碎必须包含n个节点,能力解决故障。 PoW:Prove Of Work,简略了解就是一份证实,用来确认你做过一定量的工作。 混合共识机制:为实现安全性与性能之间的均衡,采纳的一种协调办法,PoW 与 PBFT 相结合的混合公式机制。保留 PBFT 疾速高效达成共识的个性的同时,将 PBFT 节点的选举、监督权交给 PoW 节点,同时疾速的验证 PBFT 给出的交易记录汇合,从而保障了整个网络的安全性。PBFT 的通信复杂度决定了参加决策的节点只能放弃在极无限的范畴内。而利用 PoW 能够接收有限节点的个性与之联合能够补救这一弱势。 fPoW:初链将Fruitchain技术整合到原来混合共识底层的PoW技术,由原来的PoW变成了fPoW。在区块链本来应用的PoW技术中,会呈现下列几个问题: 联结挖矿(矿池):集体挖矿难道高,大家各自贡献一部分计算能力挖矿,挖到后依据奉献比例均分报酬,—影响偏心自私挖矿者攻打(Selfish Mining Attack - 即25%攻打):所谓的“区块链”,岂但要有“区块”,还要有链,也就是岂但要”挖矿“,还要”接矿“。零碎就会主动抉择置信较长的矿链。当好人挖到矿,成心不把矿接到原来的矿链上,而是通过这个矿,持续往下挖,试图挖到更长的链。诚恳的挖矿者,挖到矿接到本来的矿链上,此时好人将较长的矿链接到本来的框链下来,使诚恳的挖框者致力徒劳。交易费不稳固:矿共会先将高的交易费的材料支出block中,然而每笔交易的交易费用都不一样,统一交易费不稳固。那么fPoW如何解决下面的问题呢? 1.能抵制联结挖矿 水果(Fruits)比区块(Blocks)挖矿难度低, 一般挖矿,集体均匀两年能力挖到一个矿,但水果却一天能够挖到两个,这样矿工造成的矿池的能源就变小了,从而抵制了联结挖矿,使得PoW更加偏心。 2.能抵制自私挖矿 水果在被写入区块前都不稳固,而且存在肯定的保质期,算法规定蕴含最多水果的块为主链,所以矿工挖矿须要尽快将水果收到区块里,而不能默不作声地等着节约他人的算力,从而抵制了自私挖矿; 而矿工将水果支出会先失去挖矿处分,再将肯定处分分发给包涵进区块的水果。 3.乱序挖矿:fPoW协定使得水果的挖矿程序能够为任意程序,即能够并行挖矿,在Sharding中十分有用。 分片优化:初链思维是将区块链世界观宰割成不同的“片”,在每个不同的“片”区域内,都有不同的PBFT委员会解决,把串行解决变成并行处理,从而实现性能的大幅度的晋升。 初链社区自治共建共有经济体ps:首先名字看起来十分霸气,哈哈 建设在相互合作互相制约根底上的社区自治架构。 拜占庭委员会负责日常治理经营开发者委员会负责寰球开发者招募,TRUE 技术路线演进研发,评审代码品质,并基于 每位开发者的贡献度进行激励等; 市场媒体委员会负责制订 True媒体宣传策略,并且招募寰球各地媒体退出对 True 进行宣传,并制订相干激励政策对奉献媒体进行激励; Token 社区委员会负责制订社区扩大及保护策略,并制订相干激励计划为社区做出奉献的 True 用户。 DAO 委员会负责监督:去中心化组织,代表最宽泛的社区持币者的利益。该组织行使选举权、监督权、重大提案表决权,所有持币用户主动成为 DAO 委员会成员。 作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这是一个我的iOS交换群:642363427 ,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长!

September 5, 2020 · 1 min · jiezi

关于ios:深入iOS了解静态库

简介 程序员编写的是源代码,而计算机运行的则是CPU能辨认的机器指令,因而必须要有一系列工具或程序来将源代码转化为机器指令,这个转化的过程须要经验编译和链接两个次要阶段。所谓编译就是将源代码文件转化为两头的指标文件(Object file)。指标文件的后缀个别为.o。iOS零碎的指标文件也是一种mach-o格局的文件,mach-o文件的头部构造体:struct mach_header中的filetype成员字段用来形容以后文件的类型,指标文件所对应的类型是MH_OBJECT。指标文件中的布局构造和内容和可执行文件中的布局构造和内容十分类似,编译后造成的指标文件中的代码段(__TEXT Segment)中的节(__text Section) 中的内容寄存的是曾经被编译为机器指令的二进制代码了。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 动态库和动静库的存在模式 动态库:.a 和 .framework动静库:.dylib 和 .framework动态库和动静库的区别 动态库:链接时,动态库会被残缺地复制到可执行文件中,被屡次应用就有多份冗余拷贝动静库:链接时不复制,程序运行时由零碎动静加载到内存,供程序调用,零碎只加载一次,多个程序共用,节俭内存上面就是一个指标文件的布局构造: image.png 重定位表(Relocation table) 零碎的编译操作是针对一个个源文件的独立行为。通常状况下在编写程序时会援用其余源文件或者动静库中定义的函数或者类办法以及全局变量,因而在编译阶段所有的内部援用符号的地址是无奈被确定的,此时生成的指标文件中的段(Segment)中的节(Section)中的内部函数调用指令的操作数局部以及内部全局变量符号的地址的值都将是0。在后续的链接过程中须要调整这些指令的操作数的值来进行重定位(Relocation),为此零碎在编译的指标文件中的对那些有内部符号援用的节(Section)中都会建设一个重定位表(Relocation table)。这个重定位表中的每个条目会将所有须要进行重定位的指令或者数据拜访的地位信息以及援用的内部符号的信息记录起来,以便在链接时进行更新解决。上面的图表展现了这个构造: image 简要的说一下链接步骤所做的事件 当编译器对所有的源代码文件编译实现后,接下来的步骤就是链接了。链接的次要性能就是将所有指标文件中的各个雷同段和节的信息顺次连接起来拼装成一个独自的可执行文件。同时还会将所有指标文件中须要Relocation的局部的指令进行调整,因为此时能够晓得每个援用符号的地位了。在链接时零碎会剖析每个指标文件中的依赖信息,也就是说链接成一个可执行文件中各段各节的内容总是无依赖的指标文件放在后面而有依赖的指标文件搁置在前面。 动态库的作用 每当咱们build一个工程项目时,零碎总是会先将所有源代码编译为指标文件,再将指标文件链接为可执行程序。即便是咱们扭转其中某一个文件中的源代码,而其余文件没有扭转也是如此。因而为了放慢编译速度,有些文件将不再以源代码的模式提供,而是能够将一部分指标文件先集中起来造成一个动态库。这样就能够对这部分文件略过编译而间接进行链接从而放慢编译的速度。 对于iOS零碎来说因为不反对第三方以动静库的模式集成到咱们的工程中以及上传到appstore。而第三方提供的库因为平安和知识产权以及窃密的个性不大可能以源代码的模式提供给咱们,而是以动态库的模式提供给咱们。 可见动态库的作用次要是为了放慢编译速度、进行模块划分、以及代码平安的性能。动态库是一个编译产生的后果,而动静库则是编译链接产生的后果。动态库的组成其实是一个个指标文件。

September 5, 2020 · 1 min · jiezi

关于ios:从业四年iOS开发从美团-百度-阿里-面试回来收获分享

前言 年前没有太多工夫学习,面试百度、美团到三面就被刷下来了! 疫情期间啃完了这份美团大佬整顿的iOS外围知识点,也看了不少学习视频,本想着去试试,就面试了阿里,没想到竟拿到了offer,定级P7 举荐我的面试材料专栏:https://zhuanlan.zhihu.com/c_1284124957753675776阿里的面试经验 先介绍了我的项目,而后问了一些我的项目中的问题,而后开始问根底 属性的关键字 浅拷贝和深拷贝的区别 Block的循环援用、如何解决、原理 三种Block Block和delegate的比拟 kvo的实现原理 Autorelease pool的实现原理 音讯转发机制 线程死锁的四个条件 过程和线程的区别 长久化 事务的特色 中途还探讨了Masonry的束缚应该写在哪里,我说应该写在layoutSubViews,他说会调用屡次,而后争执了一会儿 总结起来:面试官喜爱抛出一个大点,看你能讲多广多深 阿里二面 :40mins 介绍我的项目 性能优化 YYModel和AF源码 如何本人设计json转model 架构 迷之算法题 总结:阿里的面试效率是真的不提了,二面和一面间隔时间可能相差了一个月吧,我曾经从北京回到了学校开始上课了,而且这次面试感觉有点奇怪,最初那道迷之算法题咱们也有探讨,切实没搞懂计算两点间的间隔的算法还能怎么优化,面试完结后我问了面试官最优解是怎么的,面试官通知我没有最优,只有更优(微笑脸) 点击处退出属于你的iOS技术圈子 ←←← 作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这是iOS交换群:761407670 ,不论你是小白还是大牛欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长!阿里三面:2h 一个安卓的面试官。。。。。 次要问了我的项目的一些货色 和给一些场景问我如何实现 自我介绍 介绍一些我的项目难点 主线程是绝对于什么而言的 一张图片的内存占用大小是由什么决定的 索引的作用 索引的优缺点 在数组中找最小的k个数 淘宝下拉加载更多如何优化 淘宝页面发送HTTP申请的过程 介绍一下MVVM 晓得哪些设计模式 总结:三面面试官次要就聊了一些具体场景问题和一些根底,根底我感觉没太大问题。面试过程中我讲到一些货色发现面试官听不懂,才晓得面试官是做安卓的,问一些问题其实有点让我无语,然而总的来说还是答复过去了,感觉也没有太大问题,然而前面还是被挂了,很无奈。 分享下,百度、美团的面试总结吧! runtime相干问题 runtime是iOS开发最外围的常识了,如果上面的问题都解决了,那么对runtime的了解曾经很深了。runtime曾经开源了,这有一份他人调试好可运行的源码objc-runtime,也能够去官网找objc4 构造模型 介绍下runtime的内存模型(isa、对象、类、metaclass、构造体的存储信息等)为什么要设计metaclassclass_copyIvarList & class_copyPropertyList区别class_rw_t 和 class_ro_t 的区别category如何被加载的,两个category的load办法的加载程序,两个category的同名办法的加载程序category & extension区别,能给NSObject增加Extension吗,后果如何音讯转发机制,音讯转发机制和其余语言的音讯机制优劣比照在办法调用的时候,办法查问-> 动静解析-> 音讯转发 之前做了什么IMP、SEL、Method的区别和应用场景load、initialize办法的区别什么?在继承关系中他们有什么区别说说音讯转发机制的优劣内存治理 weak的实现原理?SideTable的构造是什么样的关联对象的利用?零碎如何实现关联对象的关联对象的如何进行内存治理的?关联对象如何实现weak属性Autoreleasepool的原理?所应用的的数据结构是什么ARC的实现原理?ARC下对retain & release做了哪些优化ARC下哪些状况会造成内存透露Runloop & KVO runloop runloop对于一个规范的iOS开发来说都不生疏,应该说相熟runloop是标配,上面就轻易列几个典型问题吧 ...

September 2, 2020 · 1 min · jiezi

关于ios:2020年6月最新iOS面试题总结答案篇

之前发了这篇iOS面试总结(2020年6月),没想到挺受大家欢送,原本是没打算为它写答案,但有几个人倡议我最好出一篇答案,提的人多了我就许可了下来。因为最近比较忙,断断续续总算补完了,就有了这篇文章,心愿它对大家还有用途。这些都属于参考答案,如果大家感觉有不对不精确的中央也欢送指出,我会及时更新。 对于面试题打个比方,如果把找工作了解成考大学,面试就是高考,市面上的“真题”就是模仿试卷。咱们会很容易偏向于在面试前寻找对应公司的面试“真题”,重点筹备,期待“押题”胜利。但实际上,即便面试同一家公司,它会有不同部门,不同业务线,不同面试官,即便遇到同一面试官,他也不肯定就每次考查齐全一样的内容。想想高考中那些考的好的同学,他们必定不是靠“押题”能力获得好问题吧,他们大多靠的是平时积攒及对知识点灵便把握,那面试也一样啊。执着于搜题,把面试题当做重点进行“温习”,还不如本人划出“考纲”,各个知识点逐个查看掌握情况,温习的更全面呢。 我对于面试题的认识始终是绝对激进的,这类文章个别只是内容搬运,它会存在一些偏差和误读,最重要的那就是几道题往那一扔,并没有产出有价值的货色。这也是为什么我上篇面试总结,会加了一些面试技巧,整顿面试题时,也没提他们是出自哪家公司,就是不心愿大家把题目区别对待。 说了这些并不是说面试题没用啊,而是心愿大家不要科学面试题,更多地去关注那些有品质有深度的技术文章。面试考核的是知识点而不是具体的某些题目,面试题的作用在于,掂量咱们的常识掌握情况,便于咱们查漏补缺,越说越像是针对一次“考试”了????。 总结不易,心愿这份参考答案能对你有所帮忙,如果想继续关注我,欢送订阅微信公众号:iOS成长之路。 面试题及参考答案Swift1、Swift中struct和class有什么区别? struct是值援用,更轻量,寄存于栈区,class是类型援用,寄存于堆区。struct无奈继承,class可继承。 2、Swift中的办法调用有哪些模式? 答:间接派发、函数表派发、音讯机制派发。派发形式受申明地位,援用类型,特定行为的影响。为什么Swift有这么多派发模式?为了效率。 参考文章:深刻了解 Swift 派发机制 3、Swift和OC有什么区别? Swift和OC的区别有很多,这里简要总结这几条: SwiftObjective-C语言个性动态语言,更加平安动静语言,不那么平安语法更精简简短命名空间有无办法调用间接调用,函数表调用,音讯转发音讯转发泛型/元组/高阶函数有无语言效率性能更高,速度更快略低文件个性.swift 单文件.h/.m蕴含头文件编程个性能够更好的实现函数式编程/响应式编程面向对象编程4、从OC向Swift迁徙的时候遇到过什么问题? 能够参考这篇文章:OC我的项目转Swift指南 里的混编注意事项。 5、怎么了解面向协定编程? 面向对象是以对象的视角察看整体构造,万物皆为对象。 面向协定则是用协定的形式组织各个类的关系,Swift底层简直所有类都构建在协定之上。 面向协定可能解决面向对象的菱形继承,横切关注点和动静派发的安全性等问题。 参考喵神的面向协定编程与 Cocoa 的邂逅 (上)") OC语法1、Block是如何实现的?Block对应的数据结构是什么样子的?__block的作用是什么?它对应的数据结构又是什么样子的? block实质是一个对象,底层用struct实现。 数据结构如下: struct Block_descriptor { unsigned long int reserved; unsigned long int size; void (*copy)(void *dst, void *src); void (*dispose)(void *);};struct Block_layout { void *isa; int flags; int reserved; void (*invoke)(void *, ...); struct Block_descriptor *descriptor; /* Imported variables. */};isa 指针,所有对象都有该指针,用于实现对象相干的性能。flags,用于按 bit 位示意一些 block 的附加信息,本文前面介绍 block copy 的实现代码能够看到对该变量的应用。reserved,保留变量。invoke,函数指针,指向具体的 block 实现的函数调用地址。descriptor, 示意该 block 的附加形容信息,次要是 size 大小,以及 copy 和 dispose 函数的指针。variables,capture 过去的变量,block 可能拜访它内部的局部变量,就是因为将这些变量(或变量的地址)复制到了构造体中。__block的作用是能够获取对应变量的指针,使其能够在block外部被批改。通过反编译的代码咱们能够看到该对象是这样的: ...

September 2, 2020 · 3 min · jiezi

关于ios:iOS必问面试题

在过来的一年很多人不满于公司没有福利、人际关系不好相处、没有发展前途的境遇等等,想着在开年来换一份工作来从新开始本人,那么 你 筹备好了吗? 上面是自己整顿的一份面试资料,本想本人用的,然而公司忽然给了我个惊喜,涨工资了!!! UIView和CALayer是什么关系* UIView继承自UIResponder类,能够响应事件* CALayer间接继承自NSObject类,不能够响应事件* UIView是CALayer的delegate(CALayerDelegate)* UIView次要处理事件,CALayer负责绘制* 每个UIView外部都有一个CALayer在背地提供内容的绘制和显示,并且UIView的尺寸款式都由外部的Layer所提供。两者都有树状层级构造,Layer外部有SubLayers,View外部有SubViews,然而Layer比View多了个AnchorPoint NSCache和NSMutableDictionary的相同点与区别相同点:NSCache和NSMutableDictionary性能用法根本是雷同的区别:NSCache是线程平安的,NSMutableDictionary线程不平安,Mutable开发的类个别都是线程不平安的当内存不足时NSCache会主动开释内存(所以从缓存中取数据的时候总要判断是否为空)NSCache能够指定缓存的限额,当缓存超出限额主动开释内存NSCache的Key只是对对象进行了Strong援用,而非拷贝,所以不须要实现NSCopying协定atomic的实现机制;为什么不能保障相对的线程平安(最好能够联合场景来说)atomic会对属性的setter/getter办法进行加锁,这仅仅只能保障在操作setter/getter办法是平安的。不能保障其余线程的平安例如:线程1调用了某一属性的setter办法并进行到了一半,线程2调用其getter办法,那么会执行完setter操作后,再执行getter操作,线程2会获取到线程1setter后的残缺的值;当几个线程同时调用同一属性的setter、getter办法时,会获取到一个残缺的值,但获取到的值不可控iOS 中内省的几个办法对象在运行时获取其类型的能力称为内省。内省能够有多种办法实现OC运行时内省的4个办法:判断对象类型:-(BOOL) isKindOfClass: // 判断是否是这个类或者这个类的子类的实例-(BOOL) isMemberOfClass: // 判断是否是这个类的实例判断对象/类是否有这个办法-(BOOL) respondsToSelector: // 判断实例是否有这样办法+(BOOL) instancesRespondToSelector: // 判断类是否有这个办法objc在向一个对象发送音讯时,产生了什么依据对象的isa指针找到该对象所属的类,去objc的对应的类中找办法 1.首先,在相应操作的对象中的缓存办法列表中找调用的办法,如果找到,转向相应实现并执行2.如果没找到,在相应操作的对象中的办法列表中找调用的办法,如果找到,转向相应实现执行3.如果没找到,去父类指针所指向的对象中执行1,2.4.以此类推,如果始终到根类还没找到,转向拦挡调用,走音讯转发机制5.如果没有重写拦挡调用的办法,程序报错作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这是一个我的iOS交换群:642363427不论你是小白还是大牛欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长!如有任何问题或倡议,请进群交换,谢谢。 你是否接触过OC中的反射机制?简略聊一下概念和应用class反射通过类名的字符串模式实例化对象Class class = NSClassFromString(@"student"); Student *stu = [[class alloc] init];将类名变为字符串Class class = [Student class];NSString *className = NSStringFromClass(class);SEL的反射通过办法的字符串模式实例化办法SEL selector = NSSelectorFromString(@"setName");[stu performSelector:selector withObject:@"Mike"];将办法变成字符串NSStringFromSelector(@selector(setName:)); 这个写法会出什么问题@property (nonatomic, copy) NSMutableArray *arr;增加,删除,批改数组内元素的时候,程序会因为找不到对应的办法而解体。起因:是因为copy就是复制一个不可变NSArray的对象,不能对NSArray对象进行增加/批改如何让本人的类用copy修饰符若想令本人所写的对象具备拷贝性能,则需实现NSCopying协定。如果自定义的对象分为可变版本与不可变版本,那么就要同时实现NSCopying与NSMutableCopying协定。具体步骤:1.需申明该类听从NSCopying协定2.实现NSCopying协定的办法,具体区别戳这里NSCopying协定办法为:- (id)copyWithZone:(NSZone *)zone { MyObject *copy = [[[self class] allocWithZone: zone] init]; copy.username = self.username; return copy;}为什么assign不能用于润饰对象首先咱们须要明确,对象的内存个别被调配到堆上,根本数据类型和oc数据类型的内存个别被调配在栈上如果用assign润饰对象,当对象被开释后,指针的地址还是存在的,也就是说指针并没有被置为nil,从而造成了野指针。因为对象是调配在堆上的,堆上的内存由程序员调配开释。而因为指针没有被置为nil,如果后续的内存调配中,刚好调配到了这块内存,就会造成解体而assign润饰根本数据类型或oc数据类型,因为根本数据类型是调配在栈上的,由零碎调配和开释,所以不会造成野指针请写出以下代码输入int a[5] = {1, 2, 3, 4, 5};int *ptr = (int *)(&a + 1);printf("%d, %d", *(a + 1), *(ptr + 1));参考答案:2,随机值剖析:a代表有5个元素的数组的首地址,a[5]的元素别离是1,2,3,4,5。接下来,a + 1示意数据首地址加1,那么就是a[1],也就是对应于值为2,然而,这里是&a + 1,因为a代表的是整个数组,它的空间大小为5 * sizeof(int),因而&a + 1就是a + 5。a是个常量指针,指向以后数组的首地址,指针+1就是挪动sizeof(int)个字节因而,ptr是指向int 类型的指针,而ptr指向的就是a + 5,那么ptr + 1也相当于a + 6,所以最初的(ptr + 1)就是一个随机值了。而*(ptr – 1)就相当于a + 4,对应的值就是5一个view曾经初始化结束,view下面增加了n个button(可能应用循环创立),除用view的tag之外,还能够采纳什么方法来找到本人想要的button来批改Button的值第一种:如果是点击某个按钮后,才会刷新它的值,其它不必批改,那么不必援用任何按钮,间接在回调时,就曾经将接管响应的按钮给传过来了,间接通过它批改即可第二种:点击某个按钮后,所有与之同类型的按钮都要批改值,那么能够通过在创立按钮时将按钮存入到数组中,在须要的时候遍历查找UIViewController的viewDidUnload、viewDidLoad和loadView别离什么时候调用?UIView的drawRect和layoutSubviews别离起什么作用第一个问题:在控制器被销毁前会调用viewDidUnload(MRC下才会调用)在控制器没有任何view时,会调用loadView在view加载实现时,会调用viewDidLoad第二个问题:在调用setNeedsDisplay后,会调用drawRect办法,咱们通过在此办法中能够获取到context(设置上下文),就能够实现绘图在调用setNeedsLayout后,会调用layoutSubviews办法,咱们能够通过在此办法去调整UI。当然能引起layoutSubviews调用的形式有很多种的,比方增加子视图、滚动scrollview、批改视图的frame等主动开释池工作原理主动开释池是NSAutorelease类的一个实例,当向一个对象发送autorelease音讯时,该对象会主动入池,待池销毁时,将会向池中所有对象发送一条release音讯,开释对象[pool release]、[pool drain]示意的是池自身不会销毁,而是池子中的长期对象都被发送release,从而将对象销毁苹果是如何实现autoreleasepool的autoreleasepool是由AutoreleasePoolPage以双向链表的形式实现的,次要通过下列三个函数实现: ...

September 1, 2020 · 3 min · jiezi

关于ios:iOS-编程中的-Type-System

Type System 是一项编程语言,或者说编译器所提供的便当。Pattern Matching 能够让咱们少写代码,而 Type System 能够让咱们少犯错误,缩小 Type 相干的各种 bug。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 一般来说,咱们写代码时为了升高 bug 率,一是依赖于程序员本身的教训积攒,二是靠编译器做各种动态查看,type system 则是属于动态查看这一类。Swift 较之 Objective C 的 type system 有了很大的改良,上面文章中次要是介绍 Swift 相干的一些个性。在开始之前,先聊下如何靠程序员教训来升高 bug。 Bug 从我本身的体验推断,我置信大部分程序员在写代码的时候,对于代码是否存在 bug 是有肯定感知的。只不过有些新入行的敌人,在写代码的时候操之过急,或者因为和产品经理探讨吃了胜仗情绪不佳,coding 时指标变成了写能 work 的代码,而不是写高质量的代码。 facebook 面试有一个环节叫 whiteboard coding,要求程序员能在白板上写出简直是 「bug free」的代码,这听起来有点骇人听闻,写代码没有 Xcode 提醒就罢了,bug free 更是难上加难了。写一段简直没有 bug 的代码到底有多难呢?说难不难,说易不易。 写代码时,慢一点,再慢一点。好好的想下代码有可能出错的中央在哪,想分明了 bug 就少。一般来说,要缩小 bug 量,一是靠程序员本身涵养,二是靠编译器提供的动态查看。Type System 属于第二类,在深刻之前,先简略聊下如何靠本身涵养升高 bug 率,晋升 bug 感知的第六感。 少写 Bug 的繁难准则 要晋升程序员的本身涵养来升高 bug 率,是个大话题,而且多和本身的常识积攒无关,须要长年累月的学习和养成。本文的目标不在于此,所以只介绍一个小技巧来养成感知 bug 的好习惯。 ...

September 1, 2020 · 3 min · jiezi

关于ios:iOS开发者如何摆脱迷茫冲向未来

前言每一个开发者,都有一段不愿提起的经验,很多年前,刚刚从大学毕业的时候,很多公司来校招。其中最烂俗的一个面试问题是:“你心愿你之后三到五年的倒退是什么?”。我过后的规范答复是(原话):“成为在某一方面可能独当一面的技术专家“。起初经验了几家不同的公司,换了不同的方向,才晓得这个真是一个很难的问题。因为兵无常势,什么货色都是在一直的变动,一早的时候看好的货色可能会被淘汰。 首先剖析一下现阶段iOS开发者的迷茫问题:既然是有在空闲工夫被动学习,然而始终感觉不到成长,我想更多的可能是学习办法上的问题。举荐你看看讲学习办法和提高效率的书,可能能帮你更无效的学习。例如:《刻意练习》、《搞定》、《高效能人士的七个习惯》等。*学的货色,肯定要学以致用,教或用,都能够帮忙你更快的坚固学习成绩。你能够立即用新学的货色,尝试做出点什么;或者写一篇学习心得的文章公布进去。要晓得,技术是便宜的,基本上只有投入工夫和精力、金钱,都能够学到。然而这些技术能帮你做什么,怎么做,这才是你值钱的中央。三年呆一家公司,并且也曾经意识到,是在做重复性的工作。除了阐明你自身性情上比拟虚浮之外,其实也反映了你的进取心不够,不过这样的性情,在技术岗位也没什么不好,然而要留神不要让工作耗费本人。当你只是埋头做事,而看不到成绩的时候,的确容易让人产生自我狐疑。这一点,其实能够定一些渐进式的指标来解决,当你把大指标分解成小指标,你能更容易的看到本人致力的完成度,这样对信念增长有益处。 最初说一下我的一些倡议:跳槽。没什么好眷恋的,如果在一家公司只是在做反复的工作,看不到本人的成长,这个时候就是跳槽的一个要害信号。年老的时候,和本人的职业倒退相比,薪资并不是须要太看重的中央。跳槽前,短缺的筹备。专业技能的温习是一回事,还有一些面经的文章,也能够刷一刷,实质上,面试就是通过短暂的交换,让对方看清你的能力,所以一些无效的套路是免不了的。同时,筹备短缺也能让你在面试的时候更有信念。跳槽前,先找一些公司面试,练练手。面试也是考究形式办法的,你三年没有进来面试了,和面试相干的货色可能会比拟陌生,这就可能会导致施展不好,这些教训是看材料无奈取得的,没什么更好的方法,多练多尝试就好了。把重要的面试往后放,当你有信念面对更好的面试的时候,找一些指标公司投简历,想方法取得面试机会,除了走公开渠道投简历之外,内推也是一个不错的渠道。抉择公司也很重要。跳槽的老本很高,所以肯定要选好下一家公司。我不太分明你的技术水平,简略来说,选公司就是选平台,平台越好,你今后的倒退就会有更多的机会。职业倒退的迷茫,这个只能由你本人解决了,谁也不能决定你变成什么样的人,这件事件还是须要你本人思考。实质上来说,你想成为什么样的人,你就应该向着什么方向致力,把大指标划分成小指标去实现。 举荐????:020 继续更新,精品小圈子每日都有新内容,干货浓度极高。牢固人脉、探讨技术 你想要的这里都有!领先入群,跑赢同龄人!(入群无需任何费用)(间接搜寻群号:642363427,疾速入群)点击此处,与iOS开发大牛一起交流学习 申请即送:BAT大厂面试题、独家面试工具包,材料收费支付,包含 数据结构、底层进阶、图形视觉、音视频、架构设计、逆向安防、RxSwift、flutter,

September 1, 2020 · 1 min · jiezi

关于ios:CocoaPods仅在本地Pod对应的Podfile和Podspec如何写

个别咱们制作的pod私有库或者是公有库都放在近程,并且每次批改都须要push;如果仅仅是放在本地进行调试的模块/组件,那么对应的podfile文件以及podspec应该如何编写呢? 1、搭建测试项目以及framework1)先创立一个测试项目 2)创立一个framework,放到和测试项目同一个目录下 3)再创立一个类MTPopView 4)关掉MTPopView,而后在MTShopList我的项目中通过Add Files增加MTPopView 5)依照失常的target互相调用那样,增加framework,以及import MTPopControl 6)编译MTShopList报错 须要在class MTPopView后面加上public 再编译运行就ok了。 这里swift报错起因大家应该是很相熟了;swift拜访权限总共有private、fileprivate、internal、public、open 5种,默认状况下是internal润饰,而咱们目前是2个不同的target进行拜访,属于不同的模块,所以另一个target无法访问,须要批改拜访权限为public即可(这里是否用open,它们的区别你晓得吗?)。 2、编写pod文件1)如何编写本地测试的podspec? 通过命令pod spec create MTPopControl生成主动的podspec文件,而后替换以及删除本人不想要的命令;这里就间接简化写了,如下: Pod::Spec.new do |spec| spec.name = "MTPopControl" spec.version = "0.0.1" spec.summary = "A short description of MTPopControl." spec.homepage = "http://EXAMPLE/MTPopControl" spec.license = "MIT" spec.author = { "xk" => "" } #近程push的写法 #spec.source = {:git => 'https://github.com/xxx/xxxxx.git', :tag => spec.version} spec.source = { :path => '.' } spec.source_files = "MTPopControl" spec.requires_arc = true spec.swift_version = "5.0" spec.ios.deployment_target = "11.0" end次要是关注属性spec.source的写法不同了,咱们这里是本地 ...

September 1, 2020 · 1 min · jiezi

关于ios:Podspec语法

前言 长时间不写Podspec文件,容易遗记外面的一些属性含意,所以本文把 官网Podspec语法v1.9.0 翻译进去并且加上了一部分本人的了解,不便后续在用到的时候能够间接拿过去看。 CocoaPods版本升级后会放弃对本文进行更新。 一、Root specification相干root标准存储了相干库特定版本的信息。 上面的属性只能写在root标准上,而不能写在“sub-spec”上。 1、必须的字段. namespec.name = 'AFNetworking'pod search 搜寻的关键词,这里肯定要和.podspec的名称一样,否则会报错; . versionspec.version = '0.0.1'Pod最新的版本。 . authorsspec.author = 'Darth Vader'spec.authors = 'Darth Vader', 'Wookiee'spec.authors = { 'Darth Vader' => 'darthvader@darkside.com', 'Wookiee' => 'wookiee@aggrrttaaggrrt.com' }库维护者(而不是Podspec维护者)的名称和电子邮件地址。 . licensespec.license = 'MIT'spec.license = { :type => 'MIT', :file => 'MIT-LICENSE.txt' }spec.license = { :type => 'MIT', :text => <<-LICENSE Copyright 2012 Permission is granted to... LICENSE }Pod的许可证 ...

September 1, 2020 · 3 min · jiezi

关于ios:iOS项目中通过shell脚本批量替换第三方资源文件

1、需要咱们在做开发过程中,会用到很多第三方库,并且通过CocoaPods进行治理,有时候引入的这个必要的库在UI上并不能齐全满足产品的需要,比方背景图片、铃声等资源,须要对第三方库资源文件进行更改; 如果每次通过手动的形式去找对应bundle外面的资源文件,而后一个个去替换很是麻烦,并且也很容易弄错,所以能够思考写一个shell脚本进行批量的替换操作。 2、shell脚本源码#!/bin/shecho "\n----------- 开始???? --------------\n"source_path=/xxxxxxdestination_path=/xxxxxarray_icon=( chat_to_bg_normal@2x.png chat_from_bg_normal@2x.png default_portrait_msg@2x.png default_portrait_msg@3x.png default_group_portrait@2x.png default_group_portrait@3x.png)echo "替换资源文件数量为: ${#array_icon[@]}个\n"for file in ${array_icon[@]}do echo $file cp -f $source_path/$file $destination_path/$file doneecho "\n----------- 实现✅ --------------\n"执行替换脚本: $ ./replace.sh ----------- 开始???? --------------替换资源文件数量为: 6chat_to_bg_normal@2x.pngchat_from_bg_normal@2x.pngdefault_portrait_msg@2x.pngdefault_portrait_msg@3x.pngdefault_group_portrait@2x.pngdefault_group_portrait@3x.png----------- 实现✅ --------------从新运行我的项目,就能够看到对应的资源文件曾经替换胜利了。

September 1, 2020 · 1 min · jiezi

关于ios:对Swift协议RawRepresentable的理解

前言对于枚举原始值,零碎默认只能是字符串、整型、浮点型字面量,那么咱们能不能减少其它类型呢? 答案是能够的,通过协定RawRepresentable就能够实现 注释首先定义一个枚举 enum Terrain: String { case forest = "F" case mountain = "M" case water = "W"}1、RawRepresentable协定该协定定义了一个初始化结构器,当传入有效的原始值时结构器会返回nil;还定义了一个rawValue计算属性。 当定义上述枚举时,编译器将生成如下等价的代码: enum Terrain { case forest case mountain case water}extension Terrain: RawRepresentable { typealias RawValue = String init?(rawValue: RawValue) { switch rawValue { case "F": self = .forest case "M": self = .mountain case "W": self = .water default: return nil } } var rawValue: RawValue { switch self { case .forest: return "F" case .mountain: return "M" case .water: return "W" } }}2、rawValue实质rawValue实质是一个计算属性 ...

September 1, 2020 · 2 min · jiezi

关于ios:在Swift开发中关于Optionals你需要知道的5件事译

Optionals是Swift的外围,并且在第一个版本中就曾经存在;optional润饰的值容许咱们在关注可能为nil值的时候书写整洁的代码。 如果你刚开始接触Swift,那么你可能须要相熟在属性中增加?的语法;只有你相熟了这个语法你就能够从中受害,比方extensions。 在Swift中什么是可选值?在咱们深刻理解optionals之前须要理解基本知识。 属性、办法、下标可能返回一个可选值,这个值可能不为nil可能为nil。多个援用能够链接在一起,这称为可选链接。这是强制解包的另一种形式,稍后将对其进行更具体的解说。 上面的示例代码展现了自定义可选的String并且print字符数的可选链接。 let name: String? = "Antoine van der Lee"print(name?.count ?? 0)1. 在Swift中强制解包可选值强制解包可选值可能返回一个存在的值或者是一个导致runtime运行时谬误的空值。 然而在咱们深刻理解强制解包之前,让咱们先来看看在没有强制的状况下解包可选值有哪些可能性。 如何解包一个可选值在Swift中有很多办法能够解包可选值。你能够应用guard申明: let name: String? = "Antoine van der Lee"guard let unwrappedName = name else { return}print(unwrappedName.count)或者能够应用if let申明: let name: String? = "Antoine van der Lee"if let unwrappedName = name { print(unwrappedName.count)}或者你能够应用??运算符,也称为nil合并运算符。如果它存在,这种将会返回一个可选值或者比方上面自定义的默认值0: let name: String? = "Antoine van der Lee"print(name?.count ?? 0)应用!强制解包可选值能够在可选值前面应用!进行强制解包。 var name: String? = "Antoine van der Lee"print(name!.count)当上述示例中的name变量设置为nil的时候它将导致致命的运行时谬误,比方上面这种谬误: ...

September 1, 2020 · 2 min · jiezi

关于ios:iOS-WebView通信链路安全

最近在整顿技术点的时候发现电脑上存有一些知识点的记录,是以前在开发的过程中遇到的一些问题,当初再从新梳理了进去 我的项目需要:避免webview外面的数据被抓包,给app中的webview也加上https校验,避免攻打https校验原理、加密原理、证书制作等曾经有很多文章介绍,置信大家曾经很相熟了;本文只讲在多家服务器资源拜访的状况下对web实现https校验的局部。 一、相干知识点个别状况下很多公司对于ATS的web content设置都是关上了的,没有对证书进行校验,或者只是做了单向的证书校验,这样的话伪造一个假的无效证书web局部是很容易被他人抓到包的,这次要说的是web content设置为NO,并且是双向验证,采纳的是证书锁定的校验模式,证书锁定须要客户端本地也存储一份证书,工作原理是首先会验证域名有效期等信息,其次会验证本地证书和服务器证书是否统一,统一则握手链接,不统一则断开链接,如果设置了代理并且即便配置了一个非以后公司服务器的无效证书也无奈抓到数据,能够达到避免中间人攻打的成果。不论下面app采纳哪一种校验形式,都是由服务器配置参数clientAuth来决定:参数形容clientAuth=false单向SSL验证clientAuth=true双向SSL验证clientAuth=want不强制验证客户端证书二、实现过程上面展现的是惯例的web双向https校验 SecTrustResultType result;SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCerts);OSStatus status = SecTrustEvaluate(serverTrust, &result); if (status == errSecSuccess && (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)) { NSURLCredential *card = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,card); } else { completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); }以上就是惯例的web实现https双向校验,然而使用到目前的我的项目始终校验失败;失常来说当web通过https申请数据的时候,服务器会返回全副证书链,一个域名和一个证书是一一对应的,不能更改,而一个证书链外面又会蕴含有几级证书,根证书-二级证书-…..,目前咱们web申请返回的每个证书链外面有3级证书;最初通过调试才发现某一个h5页面在加载的时候,返回了除了咱们公司本人的证书以外还返回了阿里云的证书(*.oss.aliyuncs.com),并且每个h5界面返回的证书程序还可能不一样,返回的第一个证书链可能是咱们公司本人的证书链,也可能是oss阿里云的,程序不肯定,这就是问题所在,所以以后h5页面校验会失败无奈失常关上。更改思路,通过CFBridgingRelease(SecCertificateCopySubjectSummary(SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, 0)))取出服务器证书的概要信息,判断如果是以后本人公司域名下的证书,那么进行校验,不是比方oss阿里云的不校验,间接信赖通过,通过测试不论本人服务器证书链在哪个程序或者有没有都能够失常显示,并且测试无奈抓包: 如果比方下面返回了oss.aliyun.com的证书,那么在plist中加上这个白名单就不会有阿里云的证书链返回了,就不须要进行校验,这样也是一种思路。三、最终实现的代码如下//从证书链中获取概要信息 NSString *summary = CFBridgingRelease(SecCertificateCopySubjectSummary(SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, 0))); NSLog(@"以后申请证书概要=%@",summary); //获取信赖治理对象,外面蕴含了待验证的证书,和自定义的策略 SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { if ([summary containsString:@".xxxx.com"]) { NSString *path = [[NSBundle mainBundle] pathForResource:@"xxxx" ofType:@"der"]; NSData *certData = [NSData dataWithContentsOfFile:path]; //从der数据中创立证书对象 NSMutableArray *pinnedCerts = [NSMutableArray arrayWithObjects:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData), nil]; SecTrustResultType result; SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCerts); OSStatus status = SecTrustEvaluate(serverTrust, &result); if (status == errSecSuccess && (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)) { NSURLCredential *card = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,card); } else { //中断本次链接 completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); } }else { NSURLCredential *card = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,card); } }else { NSURLCredential *card = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, card); }四、拓展1.通过测试对于设置了web的ATS=NO,plist是否加白名单状况:(1)加了白名单不论是https还是http都能够失常拜访,因为设置了ATS=NO,必须校验,代理会收到校验的回调(2)未加白名单a、https能够拜访,前提条件(1)这个域名服务器证书无效没有过期(2)webview的校验代理没有和本地证书匹配,间接通过,比方不是本人公司的域名拜访b、http无奈失常拜访 ...

September 1, 2020 · 1 min · jiezi

关于ios:iOS基础教程SQLite数据库

学生名单治理界面实现数据库的增删改操作 数据库操作最根本的无非就是减少,删除,改变,查问四个性能 批改数据分为下图中的几个步骤 第一步 sqlite3_open 关上数据库 第二步 sqlite3_prepare_v2 预处理 SQL 语句操作 第三步 sqlite3_bind_text 函数绑定参数 第四步 sqlite3_step 函数执行 SQL 语句 第五步 sqlite3_finalize 和 sqlite3_close 开释资源 咱们新建一个SQLManager的治理类,把所有根本数据库操作的办法进行封装解决。下图是Demo工程的全副文件。 以下是代码局部: SQLManager.h文件 #import <Foundation/Foundation.h>#import "sqlite3.h"#import "StudentModel.h"@interface SQLManager : NSObject{ sqlite3 * db;}+(SQLManager *)shareManager;//查问- (StudentModel *)searchWithIDNum:(StudentModel *)model;//插入-(int)insert:(StudentModel *)model;//删除-(void)remove:(StudentModel *)model;//批改-(void)modify:(StudentModel *)model;@endSQLManager.m文件 #import "SQLManager.h"@implementation SQLManager//定义宏的目标在于:咱们操作数据库就相当于对本地文件的一个解决,首先要获取文件门路,去拼接它的名字,所以为了不便当前咱们调用这个文件,先把文件名取好#define kNameFile (@"Student.sqlite")//创立单例static SQLManager * manager = nil;+(SQLManager *)shareManager{ static dispatch_once_t once; dispatch_once(&once,^{ manager = [[self alloc] init]; [manager createDataBaseTableIfNeeded]; }); return manager;}//获取数据库的残缺门路-(NSString *)applicationDocumentsDirectoryFile{ NSArray * paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString * documentDirectory = [paths firstObject]; NSString * filePath = [documentDirectory stringByAppendingPathComponent:kNameFile]; return filePath;}//再定义一个函数,接下来的操作是创立数据库,在进行数据库操作之前,确保数据库存在,不存在的时候必须要进行创立- (void)createDataBaseTableIfNeeded{ //尽管说咱们的数据库是SQLite内置了,然而仍属于第三方,开发时如果想要应用它的类库,须要再进行配置增加 //NameList配置文件-> TARGETS -> General -> LinkedFrameworks and Libraries,点击+号,搜书sqlit,抉择libsqlite3.tbd。而后能力持续后续的操作。 NSString * writetablePath =[self applicationDocumentsDirectoryFile]; NSLog(@"数据库的地址是:%@",writetablePath); //关上数据库 //第一个参数数据库文件所在的残缺门路 //第二个参数是数据库 DataBase 对象 if (sqlite3_open([writetablePath UTF8String], &db) != SQLITE_OK) { //SQLITE_OK 是苹果为咱们定义的一个常量如果是OK的话,就代表咱们的数据库关上是胜利了 //失败 //数据库敞开 sqlite3_close(db); NSAssert(NO, @"数据库关上失败!");//抛出错误信息 }else{ //胜利 char * err; NSString * createSQL =[NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS StudentName (idNum TEXT PRIMARYKEY, name TEXT);"]; //SQLite的执行函数 /* 第一个参数 db对象 第二个参数 语句 第三个和第四个参数 回调函数和回调函数参数 第五个参数 是一个错误信息 */ if (sqlite3_exec(db, [createSQL UTF8String], NULL, NULL, &err) !=SQLITE_OK) { //失败 //数据库敞开 sqlite3_close(db); NSAssert1(NO, @"建表失败!%s", err);//抛出错误信息 } sqlite3_close(db); }}//查问数据/* 1.应用sqlite3_prepare_v2函数预处理SQL语句 2.应用sqlite3_bind_text函数绑定参数 3.应用sqlite3_step函数执行SQL语句,遍历后果集 4.应用sqlite3_column_text等函数提取字段数据 */- (StudentModel *)searchWithIDNum:(StudentModel *)model{ NSString * path =[self applicationDocumentsDirectoryFile]; if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) { sqlite3_close(db); NSAssert(NO, @"关上数据库失败!"); }else{ NSString * qsql =@"SELECT idNum,name FROM StudentName where idNum = ?"; sqlite3_stmt * statement;//语句对象 //第一个参数:数据库对象 //第二个参数:SQL语句 //第三个参数:执行语句的长度 -1是指全副长度 //第四个参数:语句对象 //第五个参数:没有执行的语句局部 NULL //预处理 if(sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, NULL) ==SQLITE_OK){ //进行 按主键查询数据库 NSString * idNum = model.idNum; //第一个参数 语句对象 //第二个参数 参数开始执行的序号 //第三个参数 咱们要绑定的值 //第四个参数 绑定的字符串的长度 //第五个参数 指针 NULL //绑定 sqlite3_bind_text(statement, 1, [idNum UTF8String], -1, NULL); //遍历后果集 /* 有一个返回值 SQLITE_ROW常量代表查出来了 */ if (sqlite3_step(statement) == SQLITE_ROW) { //提取数据 /* 第一个:语句对象 第二个:字段的索引 */ char * idNum = (char *)sqlite3_column_text(statement, 0); //数据转化 NSString * idNumStr =[[NSString alloc]initWithUTF8String:idNum]; char * name =(char *)sqlite3_column_text(statement, 1); NSString * nameStr =[[NSString alloc]initWithUTF8String:name]; StudentModel * model =[[StudentModel alloc] init]; model.idNum = idNumStr; model.name = nameStr; //开释 sqlite3_finalize(statement); sqlite3_close(db); return model; } } sqlite3_finalize(statement); sqlite3_close(db); } return nil;}//批改-(int)insert:(StudentModel *)model{ NSString * path =[self applicationDocumentsDirectoryFile]; if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) { sqlite3_close(db); NSAssert(NO, @"数据库关上失败!"); }else{ NSString * sql =@"INSERT OR REPLACE INTO StudentName (idNum, name) VALUES (?,?)"; sqlite3_stmt * statement; //预处理过程 if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, NULL) ==SQLITE_OK) { sqlite3_bind_text(statement, 1, [model.idNum UTF8String], -1, NULL); sqlite3_bind_text(statement, 2, [model.name UTF8String], -1, NULL); if (sqlite3_step(statement) != SQLITE_DONE) { NSAssert(NO, @"插入数据失败!"); } sqlite3_finalize(statement); sqlite3_close(db); } } return 0;}//删除-(void)remove:(StudentModel *)model{ /* 第一步 sqlite3_open 关上数据库 第二步 sqlite3_prepare_v2 预处理 SQL 语句操作 第三步 sqlite3_bind_text 函数绑定参数 第四步 sqlite3_step 函数执行 SQL 语句 第五步 sqlite3_finalize 和 sqlite3_close 开释资源 */ NSString * path =[self applicationDocumentsDirectoryFile]; if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) { sqlite3_close(db); NSAssert(NO, @"数据库关上失败"); }else{ NSString * sql =@"DELETE FROM StudentName where idNum = ?"; sqlite3_stmt * statement; //预处理 if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, NULL) ==SQLITE_OK) { sqlite3_bind_text(statement, 1, [model.idNum UTF8String], -1, NULL); sqlite3_bind_text(statement, 2, [model.name UTF8String], -1, NULL); if (sqlite3_step(statement) != SQLITE_DONE) { NSAssert(NO, @"删除数据失败!"); } sqlite3_finalize(statement); sqlite3_close(db); } }}StudentModel.h文件 ...

August 31, 2020 · 4 min · jiezi

关于ios:iOS性能优化之内存优化

iOS App 通常状况下的三种内存类型Clean MemoryDirty MemoryCompressed MemoryiOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! Clean MemoryClean Memory 是指那些能够用以 Page Out(当内存不足的时候,零碎会依照肯定策略来腾出更多空间供应用,比拟常见的做法是将一部分低优先级的数据挪到磁盘上) 的内存。 Codeframeworks (每个 frameworks 都有 _DATA_CONST 段,当 App 在运行时应用到了某个 framework,它所对应的 _DATA_CONST 的内存就会由 Clean 变为 Dirty)。memory-mapped files (被加载到内存中的文件)Dirty MemoryDirty Memory 是指那些被 App 写入过数据的内存。 Heap allocations (所有堆区的对象)图像解码缓冲区database caches ( 咱们对数据进行缓存的目标是想缩小 CPU 的压力,然而过多的缓存又会占用过大的内存。因为内存压缩机制的存在,咱们须要依据缓存数据大小以及重算这些数据的老本,在 CPU 和内存之间进行衡量。 在一些须要缓存数据的场景下,能够思考应用 NSCache 代替 NSDictionary,因为 NSCache 能够主动清理内存,在内存吃紧的时候会更加正当。 )留神:Clean memory,也包含 App 所用到的 frameworks。每个 framework 都会有 _DATA 段和 _DATA_DIRTY 段,它们的内存是 Dirty 的。 Compressed Memory当内存吃紧的时候,零碎会将不应用的内存进行压缩,直到下一次拜访的时候进行解压。 ...

August 31, 2020 · 1 min · jiezi

关于ios:优化iOS程序性能的方法

1. 用ARC治理内存ARC(Automatic ReferenceCounting, 主动援用计数)和iOS5一起公布,它防止了最常见的也就是常常是因为咱们遗记开释内存所造成的内存泄露。它主动为你治理retain和release的过程,所以你就不用去手动干涉了。忘掉代码段结尾的release几乎像记得吃饭一样简略。而ARC会主动在底层为你做这些工作。除了帮你防止内存泄露,ARC还能够帮你进步性能,它能保障开释掉不再须要的对象的内存。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 2.尽量把views设置为通明如果你有通明的Views你应该设置它们的opaque属性为YES。 起因是这会使零碎用一个最优的形式渲染这些views。这个简略的属性在IB或者代码里都能够设定。 Apple的文档对于为图片设置通明属性的形容是: (opaque)这个属性给渲染零碎提供了一个如何解决这个view的提醒。如果设为YES,渲染零碎就认为这个view是齐全不通明的,这使得渲染系统优化一些渲染过程和进步性能。如果设置为NO,渲染零碎失常地和其它内容组成这个View。默认值是YES。 在绝对比拟静止的画面中,设置这个属性不会有太大影响。然而当这个view嵌在scroll view里边,或者是一个简单动画的一部分,不设置这个属性的话会在很大水平上影响app的性能。 你能够在模拟器中用Debug\Color Blended Layers选项来发现哪些view没有被设置为opaque。指标就是,能设为opaque的就全设为opaque! 这里有一点须要留神,只有是有中文字符的Label,哪怕你设置成不通明,模拟器中这个Label仍然会变红,这个猜想是字符绘制的时候出的问题,这个目前没找到好的解决办法。 3.防止过于宏大的XIBiOS5中退出的Storyboards(分镜)正在疾速取代XIB。然而XIB在一些场景中依然很有用。比方你的app须要适应iOS5之前的设施,或者你有一个自定义的可重用的view,你就不可避免地要用到他们。 如果你不得不XIB的话,使他们尽量简略。尝试为每个Controller配置一个独自的XIB,尽可能把一个View Controller的view层次结构扩散到独自的XIB中去。 须要留神的是,当你加载一个XIB的时候所有内容都被放在了内存里,包含任何图片。如果有一个不会即刻用到的view,你这就是在节约贵重的内存资源了。Storyboards就是另一码事儿了,storyboard仅在须要时实例化一个view controller. 当家在XIB是,所有图片都被chache,如果你在做OS X开发的话,声音文件也是。Apple在相干文档中的记述是: 当你加载一个援用了图片或者声音资源的nib时,nib加载代码会把图片和声音文件写进内存。在OS X中,图片和声音资源被缓存在named cache中以便未来用到时获取。在iOS中,仅图片资源会被存进named caches。取决于你所在的平台,应用NSImage 或UIImage的imageNamed:办法来获取图片资源。 这个问题我深有体会,用xib写的界面加载速度比间接用代码写的要慢好多 4. 在Image Views中调整图片大小如果要在UIImageView中显示一个来自bundle的图片,你应保障图片的大小和UIImageView的大小雷同。在运行中缩放图片是很消耗资源的,特地是UIImageView嵌套在UIScrollView中的状况下。 如果图片是从远端服务加载的你不能管制图片大小,比方在下载前调整到适合大小的话,你能够在下载实现后,最好是用background thread,缩放一次,而后在UIImageView中应用缩放后的图片。 5. 抉择正确的Collection学会抉择对业务场景最合适的类或者对象是写出能效高的代码的根底。当解决collections时这句话尤其正确。 一些常见collection的总结: Arrays: 有序的一组值。应用index来lookup很快,应用value lookup很慢,插入/删除很慢。 Dictionaries: 存储键值对。用键来查找比拟快。 Sets: 无序的一组值。用值来查找很快,插入/删除很快。因为Set用到了哈希,所以插入删除查找速度比Array快很多 6. 关上gzip压缩大量app依赖于远端资源和第三方API,你可能会开发一个须要从远端下载XML, JSON, HTML或者其它格局的app。 问题是咱们的指标是挪动设施,因而你就不能指望网络情况有多好。一个用户当初还在edge网络,下一分钟可能就切换到了3G。不论什么场景,你必定不想让你的用户等太长时间。 减小文档的一个形式就是在服务端和你的app中关上gzip。这对于文字这种能有更高压缩率的数据来说会有更显著的效用。 好消息是,iOS曾经在NSURLConnection中默认反对了gzip压缩,当然AFNetworking这些基于它的框架亦然。像Google App Engine这些云服务提供者也曾经反对了压缩输入。 7. 重用和提早加载(lazy load) Views更多的view意味着更多的渲染,也就是更多的CPU和内存耗费,对于那种嵌套了很多view在UIScrollView里边的app更是如此。 这里咱们用到的技巧就是模拟UITableView和UICollectionView的操作:不要一次创立所有的subview,而是当须要时才创立,当它们实现了使命,把他们放进一个可重用的队列中。 这样的话你就只须要在滚动产生时创立你的views,防止了不划算的内存调配。 创立views的能效问题也实用于你app的其它方面。设想一下一个用户点击一个按钮的时候须要出现一个view的场景。有两种实现办法: 创立并暗藏这个view当这个screen加载的时候,当须要时显示它;当须要时才创立并展现。每个计划都有其优缺点。用第一种计划的话因为你须要一开始就创立一个view并放弃它直到不再应用,这就会更加耗费内存。然而这也会使你的app操作更敏感因为当用户点击按钮的时候它只须要扭转一下这个view的可见性。 第二种计划则相同-耗费更少内存,然而会在点击按钮的时候比第一种稍显卡顿。 8.衡量渲染办法在iOS中能够有很多办法做出丑陋的按钮。你能够用整幅的图片,可调大小的图片,或者能够用CALayer, CoreGraphics甚至OpenGL来画它们。当然每个不同的解决办法都有不同的复杂程度和相应的性能。 简略来说,就是用当时渲染好的图片更快一些,因为如此一来iOS就免去了创立一个图片再画货色下来而后显示在屏幕上的程序。问题是你须要把所有你须要用到的图片放到app的bundle外面,这样就减少了体积–这就是应用可变大小的图片更好的中央了:你能够省去一些不必要的空间,也不须要再为不同的元素(比方按钮)来做不同的图。 ...

August 29, 2020 · 1 min · jiezi

关于ios:消息转发机制

1.动静办法解析对象在收到无奈解决的音讯时,会调用上面的办法,前者是调用类办法时会调用,后者是调用对象办法时会调用 //未实现类办法调用+ (BOOL)resolveClassMethod:(SEL)sel//未实现实例办法调用+ (BOOL)resolveInstanceMethod:(SEL)sel在该办法中,须要给对象所属类动静的增加一个办法,并返回YES,表明能够解决 + (BOOL)resolveInstanceMethod:(SEL)sel{ NSString *method = NSStringFromSelector(sel); if ([@"playPiano" isEqualToString:method]) { /** 增加办法 @param self 调用该办法的对象 @param sel 抉择子 @param IMP 新增加的办法,是c语言实现的 @param 新增加的办法的类型,蕴含函数的返回值以及参数内容类型,eg:void xxx(NSString *name, int size),类型为:v@i */ class_addMethod(self, sel, (IMP)playPiano, "v"); return YES; } return NO;}应用这种方法的前提是:相干办法代码曾经实现,只是在运行时将改办法动静增加到指标类中。例如CoreData中应用的@dynamic属性,就是在运行时动静增加办法实现。 2.备援接收者经验了第一步后,如果该音讯还是无奈解决,那么就会调用上面的办法,查问是否有其它对象可能解决该音讯。 - (id)forwardingTargetForSelector:(SEL)aSelector在这个办法里,咱们须要返回一个可能解决该音讯的对象 - (id)forwardingTargetForSelector:(SEL)aSelector{ NSString *seletorString = NSStringFromSelector(aSelector); if ([@"playPiano" isEqualToString:seletorString]) { Student *s = [[Student alloc] init]; return s; } // 持续转发 return [super forwardingTargetForSelector:aSelector];}3.残缺的音讯转发经验了前两步,还是无奈解决音讯,那么就会做最初的尝试,先调用methodSignatureForSelector:获取办法签名,而后再调用forwardInvocation:进行解决,这一步的解决能够间接转发给其它对象,即和第二步的成果等效,然而很少有人这么干,因为音讯解决越靠后,就示意解决音讯的老本越大,性能的开销就越大。所以,在这种形式下,会扭转音讯内容,比方减少参数,扭转抉择子等等。 ...

August 29, 2020 · 2 min · jiezi

关于ios:ReactiveCocoa框架程序定位

应用RAC形式与传统形式做定位性能的比照 首先,因为应用定位性能,所以要在info.plist文件外面做申请形容设置增加上面两个字段: Privacy - Location Always Usage Description Privacy - Location When In Use Usage Description 而后是代码局部: .h文件`#import "ViewController.h" @import ReactiveCocoa; @interface ViewController ()<CLLocationManagerDelegate> @property (nonatomic,strong)CLLocationManager * manager;//地位管理器@property (nonatomic) CLGeocoder * geocoder;//返地理位置编码@property (weak, nonatomic) IBOutlet UILabel *placeLabel; @end @implementation ViewController -(CLLocationManager * )manager{ if (!_manager) { _manager = [[CLLocationManager alloc]init]; _manager.delegate = self;}return _manager;} -(CLGeocoder *)geocoder{ if (!_geocoder) { _geocoder = [[CLGeocoder alloc]init];}return _geocoder;} -(RACSignal *)authorizedSignal{ ...

August 29, 2020 · 2 min · jiezi

关于ios:iOS-各种UI控件属性设置

//视图曾经加载完了,能够进行ui的增加了- (void)viewDidLoad { [superviewDidLoad]; // Do any additional setup after loading the view. //初始化UILabel留神指定该对象的地位及大小 UILabel *lb = [[UILabelalloc]initWithFrame:CGRectMake(0,20,300,200)]; //设置文字 lb.text =@"label测试我在学习中学些ui story水电费水电费未入围 i肉煨入味哦水电费水电费水电费"; //设置背景色 lb.backgroundColor = [UIColorcolorWithRed:0green:191.0/255.0blue:243.0/255.0alpha:1.0]; //设置文字色彩 lb.textColor = [UIColorwhiteColor]; //文字大小,文字字体 lb.font = [UIFontsystemFontOfSize:25]; NSLog(@"零碎字体名字:%@",lb.font.familyName); //打印文字字体列表 NSArray *arrFonts = [UIFontfamilyNames]; NSLog(@"零碎字体列表:%@",arrFonts); //文字对齐 lb.textAlignment =NSTextAlignmentJustified;// NSTextAlignmentLeft = 0, //居左对齐,默认// NSTextAlignmentCenter = 1, //居中对齐// NSTextAlignmentRight = 2, //居右对齐// NSTextAlignmentJustified = 3, // Fully-justified. The last line in a paragraph is natural-aligned.// NSTextAlignmentNatural = 4, // Indicates the default alignment for script //换行模式 lb.lineBreakMode =NSLineBreakByCharWrapping;// NSLineBreakByWordWrapping = 0, //每一行的结尾以字或者一个残缺单词换行(若不够一个单词的地位)// NSLineBreakByCharWrapping,//在每一行的结尾以字母进行换行// NSLineBreakByClipping,// Simply clip// NSLineBreakByTruncatingHead,// Truncate at head of line: "...wxyz"// NSLineBreakByTruncatingTail,// Truncate at tail of line: "abcd..."// NSLineBreakByTruncatingMiddle// Truncate middle of line: "ab...yz" //指定行数,0为不限度行树,能够指定具体的数字 lb.numberOfLines =0; //加圆角 lb.layer.cornerRadius =30; //此行必须加,将原来的矩形角剪掉 lb.clipsToBounds =YES; //加边框色彩,宽度,留神给layer加的色彩是CGColor类型 lb.layer.borderColor = [[UIColorredColor]CGColor]; lb.layer.borderWidth =1.0; //把label增加到视图上,并且会显示 [self.viewaddSubview:lb];}Label的首行缩进始终是个很头疼的问题,当初IOS6只有有一个 attributedText的属性值得咱们深究,能够达到咱们自定义的行高,还有首行缩进,各种行距和距离问题。上面这个是两个Label, 一个是UserName,另一个是Content文本多行信息 ...

August 28, 2020 · 3 min · jiezi

关于ios:面试题-拓展常用框架和第三方框架

类变量的@protected,@private,@public,@package申明各有什么含意@private:作用范畴只能在本身类 @protected:作用范畴在本身类和继承本人的子类(默认) @public:作用范畴最大,能够在任何中央被拜访 @package:这个类型最罕用于框架类的实例变量,同一个包内能用,跨包就不能拜访。 对于框架类的拓展: iOS罕用根底框架Foundation:提供OC根底类(例如NSObject)、根本数据类型等 UIKit:创立和管理应用程序的用户界面 QuartzCore:提供动画特效以及通过硬件进行渲染的能力 CoreGraphics:提供2D绘制的基于C的Api SystemConfiguration:检测以后网络是否可用和硬件设施状态 AVFoundation:提供音频录制和回放的底层API,同时也负责管理音频硬件 CFNetWork:拜访和配置网络,像HTTP、FTP和Bonjour Services CoreFoundation:提供形象的罕用数据类型,比方Unicode strings、XML、URL等 CoreLocation:应用GPS和WIFI获取地位信息 GameKit:为游戏提供网络性能:点对点互联和游戏中的语音交换 AddressBook:提供拜访用户联系人信息的性能 AddressBookUI:提供一个用户界面,用于显示存储在地址薄中的联系人信息 AudioToolBox:提供音频录制和回放的底层API,同时也负责管理音频硬件 AudioUnit:提供一个接口,让咱们的应用程序能够对音频进行解决 MapKit:为应用程序提供内嵌地图的接口 MediaPlayer:提供播放视频和音频的性能 MessageUI:提供视图管制接口用以解决M-mail和短信 OpenGLES:提供动画特效以及通过硬件进行渲染的能力 StoreKit:为应用程序提供在程序运行中生产的反对 罕用的第三方开源框架:1.JSON json编码解码 2.GTMBase64 base64编码解码 3.TouchXML 解析 4.SFHFKeychainUtils 平安保留用户明码到keychain中 5.MBProgressHUD很棒的一个加载期待特效框架 6.ASIHTTPRequest 等相干协定封装 7.EGORefreshTableHeaderView 下拉刷新代码 8.AsyncImageView 异步加载图片并缓存代码 9.相似setting的竖立也分栏程序 10.MBProgressHUD——停顿批示符库 11.Flurry——详尽的应用统计 12.CorePlot——2D图形绘图仪 13.GData client——iPhone上所有Google相干服务的类库 14.SDWebImage——简化网络图片解决 15.RegexKitLite——正则表达式反对 作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这是一个我的iOS交换群:642363427不论你是小白还是大牛欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长!

August 28, 2020 · 1 min · jiezi

关于ios:iOS-开发技术栈与进阶

iOS 技术栈 这里按我的了解给 iOS 相干技术分个类,以工程实现的角度,分成了根底、需要、效率、品质四个类别。根底指程序开发和 iOS 开发的基础知识和技能,需要就是产品的需要,有了根底技能,实现了产品需要后,剩下的事件就都是为了进步我的项目品质和晋升开发效率。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 根底 根底包含语言、框架、内存、网络、存储、渲染、线程。 语言目前 iOS 开发就是 OC 和 Swift,国内仍以 OC 为主,对于 OC 除了语法外,最好理解它的对象模型,动静机制等个性。Swift 方面若要在团队里应用,目前还是危险大收益小的,但集体最好放弃对它的关注。 框架就是 Foundation / UIKit 以及苹果零碎封装好的各种框架,Foundation 和 UIKit 每个做 iOS 开发的人都熟知这套,iOS 性能越来越多,苹果提供的框架也越来越多,像 StoreKit / MessageUI / AVFoundation 等能够在应用到再去理解。 接着是客户端里最常见流程里的四个要害局部:从网络拉取数据,存储到本地文件系统,再从本地取出来放进内存,最初渲染进去。而这里所有的解决都在操作系统的过程和线程中执行。 网络方面若要深刻的话内容很多,客户端个别只须要关怀 http / https / dns 这几个协定,理解 https 的原理,解决运营商劫持 dns 劫持等状况,另外须要解决好各种异常情况做好重试机制,iOS 作为挪动端网络不稳固,要看状况优化弱网络下的连贯,做好离线机制,以及留神防止消耗太多流量。还有客户端跟后盾的通信协议,数据结构个别用 json 或 protobuf,因为客户端本地会保留一部分内容,很多 APP 都会须要做数据的增量更新。 存储方面次要是 sqlite,sqlite 作为存储引擎是大多数 APP 的外围,也是性能优化的关键点,最根本的须要晓得主键索引事务等数据库基本概念,再深刻须要理解具体的存储机制/索引的实现/sqlite的七层构造等,能力在遇到问题时找到最佳的解决方案。客户端上 nosql 用得较少,除了 sqlite 个别就剩单文件存储,XML存文件或对象序列化成二进制存储,也是罕用的存储形式,近期有 realm 这种新型数据库,也值得理解一下。 ...

August 28, 2020 · 1 min · jiezi

关于ios:腾讯开发10年大佬iOS开发现状与发展浅析给你一个职业规划的方向

前言之前负责挪动端基础架构相干的工作,并做了一段时间技术框架输入,所以对挪动端的现状以及挪动端开发这个行业有肯定理解,与大家分享下。 挪动端开发时代已完结?过来两年里,挪动端开发始终在被唱衰,Objective-C 的语言热门度逐年降落,可参见 TIOBE 公布的排名。 2017~2018 开发语言排名变动 Objective-C 作为开发 iOS 利用的最次要语言,排名在 3~5 年前时也是前五的存在,现在已根本位于十名开外,过来一年兜兜转转,进入了前十名。 在风口上时,猪都能飞,但风口过来,当一个待业市场不再那么火爆时,期待的必然是弱者的淘汰。作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这是一个我的iOS交换群:761407670 ,不论你是小白还是大牛欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 二、程序员的职业倒退分类程序员的职业倒退大体分为四类。 1)始终钻研技术 说到底打铁还需本身硬,对于程序员这靠技术吃饭的职业,技术当然是至关重要的。 所以,对于那些酷爱技术,编码能低潮的技术男这是一个好的方向,能坐住板凳,沉闷于各大技术论坛,始终钻研技术,而后在一家企业把控核心技术,就算职业生涯有变,凭借在相干畛域的小名,也能在另外一家企业混口饭吃。这类人是幸福的,能够把趣味当作职业,每个公司都会有这样的人。 2)技术转治理 这是更加常见的一类,个别在一家公司工作几年之后,因为经验丰富,又熟悉业务就会成为项目经理,而后失常的话就是部门经理、技术总监一步一步的升职加薪,逐步进入管理层。 这是很多人的谋求,毕竟江湖传言:程序员是吃青春饭的,对于很多公司,中层管理者和基层管理者个别会抉择本人公司造就,所以机会还是很多的。 然而你要晓得这一过程是一个淘汰的过程,越靠近金字塔顶人就会越少,所以这一类人肯定是同一批或者公司中同程度中的佼佼者,能力一步步怀才不遇,很多公司的中层和基层的领导都是这一类的。 3)自主守业 这是近几年很热的一类,本人懂技术又接触到一个自认为很好的点子,说干就干找几个气味相投的人,或者被人画了饼,写策动,找天使投资,而后说不定本人摇身一变就成了公司老总了。 自主守业为什么这么热?就是有了很多屌丝逆袭的实例,加上有很大的可操作性,也的确有很多人胜利,然而肯定要苏醒,要晓得 jack ma 说过百分之九十互联网守业的人都守业失败了。 4)适时转型 转型分为很多种,比方转型去讲课,比方转型去出书,比方转型成为一名自在工作者,本人接需要,提供咨询服务等。 比起这些,还有小的转型,比方当年很火的打工皇帝唐骏就是转测试,取得了巨大成功,咱们公司也有一些技术转产品很胜利的例子。 总之,俗话说的好,树挪死,人挪活,当本人意识到处在瓶颈期,要学会转换思维,目前很多讲课网站,技术类公众号,培训班等渠道让很多程序员顺利转型。 三、所须要把握的常识体系逆向安防、算法、架构设计、多线程,网络进阶,还有底层、音视频、Flutter等等等知识点: 一起进阶的敌人能够退出咱们iOS 底层 分享式 高性能群:761407670 四、程序员可抉择的职业倒退方向其实可抉择的职业倒退方向也就是下面提到的大多数程序员的职业倒退,这里重点要说的是对于这四类人员要着重造就的哪些能力。对于想致力于钻研技术的小伙伴们,首先咱们要记住老祖宗通知咱们的话:人外有人,天外有天。其实很多程序员都是自负的,特地是公司中难不倒的人,或者畛域内小有名气的人,有成就有本事自负当然无可非议,然而若想更上一层楼,或是想始终靠技术吃饭就要时刻关注新技术。 现在技术更新换代何等的快,可能前几年还是公司的问不到,固步自封的话很快就会被新人所取代,这就是为什么说程序员是吃青春饭的起因。即便很有教训,技术很强,然而年轻人成长速度是很快的,并且成本低!所以各大互联网公司平均年龄一再刷新最年老的记录。甚至很多公司间接拿年龄作为硬规范裁员,所以这一类人肯定要一直晋升本身,多交换,多分享,多学习。对于想沉下心来技术转治理的小伙伴,首先如果是从一名一般的程序员干起的话,肯定要经得起钱的引诱,不能频繁跳槽。 虽说程序员的定律,跳槽 = 涨工资,然而转治理的前提就是足够相熟公司业务,能解决各种突发事件,这是须要工夫教训的积攒的,而且据说很多大的互联网公司曾经明令不收在一个企业工作不满三年的员工了。所以这一类人要在编码之余多关怀公司业务,还要晋升本身人际交往能力,领导要协调各方,交换能力必不可少。 对于想本人守业的人,肯定不要急于求成,本人有一个好的想法或者接触到好的主见就头脑一热说干就干,先要全面的评估一下可行性,特地是团队中没有有教训的人,很容易思考的不全面,守业失败率可是高的吓人! 守业除了要有好的想法,还要有天时地利人和,没资本没人脉守业和找死根本没什么区别,所以这一类人千万不能心急,肯定要先积攒本人,包含人脉和资本,而后放弃一颗沉闷的心,抓住机遇才有可能胜利。 对于想适时转型的人来说,如果不想在 996,能够在工作之余接触一些自媒体,把本人的劣势转化为资本,而且尽快。因为可能你当初善于的畛域,过几年就被淘汰了。所以要及时总结,如果对某一技术有深入研究和实际过,并且表达能力能够,能够录制一些视频,或者间接来一场 Chat 也是十分好的抉择。 此外还能够接一些我的项目本人做,积攒得多了能够出书,如果想要成为一名自由职业者的话,肯定要先保障在一段时间内没有经济起源的状况下不被饿死再去辞职。 五、程序员要时刻记住的三件事1)锻炼身体 身材是反动的成本! 好的身材对于程序员来说真的特地重要,去年团队中一个共事因为颈椎病在家躺了一个多月,他才二十多岁的年纪! 网上调侃,程序员最初读的书是《颈椎病痊愈指南》,尽管工作工夫长、压力大,然而也要时刻揭示本人锻炼身体,眼保健操,一周几次的静止肯定要放弃,最良久坐两头找个工夫站起来流动流动。 很多公司都有很多静止社团和健身房,都是不错的抉择。 2)晋升本人涵养 今人提倡内外兼修,好的涵养会在很多方面帮忙到本人,包含人际交往之中,好的涵养会在举手投足之间会让人感觉很难受,从而给本人减少很多机会。 利用一些业余时间多读读书,旅旅行,是晋升本人外在好的抉择,读万卷书行万里路,也会让本人眼界和胸襟开阔,在人生不如意的时候想得开、放得下,兴许没有比这个更重要的了。 3)增强技术和业务水平 这一点是陈词滥调了,无论怎样布局本人的职业生涯,虚浮致力的晋升本人技术和业务水平都是不可或缺的,所以无论你当初生存的是难受还是挣扎,都不要忘了晋升本人,给本人一直减轻是一个程序员时刻要记着的事。 防患未然,毋让悲剧重演。

August 27, 2020 · 1 min · jiezi

关于ios:Flutter-详解七深入了解绘制原理

## Widget 在flutter中,every is widget,了解起来很容易,咱们所应用的显示文字的Text,展现图片的Image,展现地位信息的Padding,都是Widget.在浏览Flutter源码的,你可能会留神到Widget的定义: @immutableabstract class Widget extends DiagnosticableTree { ... const Widget({ this.key }); final Key key; static bool canUpdate(Widget oldWidget, Widget newWidget) { return oldWidget.runtimeType == newWidget.runtimeType && oldWidget.key == newWidget.key;} ...}官网这样讲: A widget is an immutable description of part of a user interface.小部件是对用户界面的不可变的形容。 咱们留神到左上角有@immutable,这个很重要,窗口小部件中的所有属性都必须为final,一旦实例化,就无奈跟更改外部属性,然而事实上,咱们的UI不可能变化无穷的,因而Flutter如何治理UI的状态呢? Flutter有三棵树,Widget树、Element树、RenderObjects树,这些树分工不同,将他们组合在一起,来优化UI的各种可能性。 Element是什么记录一个Widget的地位信息 An instantiation of a [Widget] at a particular location in the tree.它是树的可变局部,用于治理UI更新和更改,您能够将它看做是治理widget的生命周期的元素。每个元素都援用了一个widget,很简略的。 RenderObject是什么在Flutter绘制UI时,它不会查看Widget的树,而是查看RenderObjects,它管制大小,布局并保留用于绘制理论widget的所有逻辑,这就是渲染对象实例化很好性能的起因。 为了更好的展现这三棵树,咱们看上面小部件: class HomeRoute extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Text('Hello world'), ); }}当咱们启动利用时 ...

August 27, 2020 · 1 min · jiezi

关于ios:iOS-Runtime常用示例总结

前言Runtime是iOS外面十分重要的基础知识,首次与它见面时,甚是糊涂,但没有关系,万事万物都是要由生疏到相熟。学就完了。 注释常常有小伙伴私下在Q上问一些对于Runtime的货色,问我有没有Runtime的相干博客,之前还真没正儿八经的总结过。之前只是在解析第三方框架源码时,聊过一些用法,也就是这些第三方框架中用到的Runtime。比方属性关联,动静获取属性等等。本篇博客就针对Runtime这个主题来总结一些其罕用的一些办法. 本篇博客所聊的Runtime的内容大略有:动静获取类名、动静获取类的成员变量、动静获取类的属性列表、动静获取类的办法列表、动静获取类所遵循的协定列表、动静增加新的办法、类的实例办法实现的替换、动静属性关联、音讯发送与音讯转发机制等。当然,本篇博客总结的是运行时罕用的性能,并不是所有Runtime的内容。 一、构建Runtime测试用例本篇博客的内容是依靠于实例的,所以咱们在本篇博客中先构建咱们的测试类,Runtime将会对该类进行相干的操作。下方就是本篇博客所波及Demo的目录,下面的RuntimeKit类是讲Runtime罕用的性能进行了简略的封装,而下方的TestClass以及相干的类目就是咱们Runtime要操作的对象了。下方会对TestClass以及类目中的内容进行具体介绍。 下方的代码就是咱们的测试类TestClass的次要局部,因为TestClass是专门用来测试的类,所以其波及的内容要尽量的全面。TestClass遵循了NSCoding, NSCopying这两个协定,并且为其增加了私有属性、公有属性、公有成员变量、 私有实例办法、公有实例办法、类办法等。这些增加的内容,都将是咱们Runtime的操作对象。下方那几个TestClass的类目稍后在应用Runtime时再进行介绍。 TestClass.h@interface TestClass : NSObject <NSCoding, NSCopying> @property (nonatomic, strong) NSArray *publicProperty1;@property (nonatomic, strong) NSString *publicProperty2; + (void)classMethod:(NSString *)value;- (void)publicTestMethod1:(NSString *)value1 Second:(NSString *)value2;- (void)publicTestMethod2; - (void)method1; @end TestClass.m@interface TestClass() { NSInteger _var1; int _var2; BOOL _var3; double _var4; float _var5;} @property (nonatomic, strong) NSMutableArray *privateProperty1;@property (nonatomic, strong) NSNumber *privateProperty2;@property (nonatomic, strong) NSDictionary *privateProperty3; @end @implementation TestClass + (void)classMethod: (NSString *)value { NSLog(@"publicTestMethod1");} - (void)privateTestMethod1 { NSLog(@"privateTestMethod1");} - (void)privateTestMethod2 { NSLog(@"privateTestMethod2");} #pragma mark - 办法替换时应用- (void)method1 { NSLog(@"我是Method1的实现");} @end二、RuntimeKit的封装接下来咱们就来看看RuntimeKit中的内容,其中对Runtime罕用的办法进行了简略的封装。次要是动静的获取类的一些属性和办法的,以及动静办法增加和办法替换的。本局部的干货还是不少的。 ...

August 27, 2020 · 3 min · jiezi

关于ios:iOS-高效使用的多线程

一、多线程简述线程是程序执行流的最小单元,一个线程包含:独有ID,程序计数器 (Program Counter),寄存器汇合,堆栈。同一过程能够有多个线程,它们共享过程的全局变量和堆数据。 这里的 PC (Program Counter) 指向的是以后的指令地址,通过 PC 的更新来运行咱们的程序,一个线程同一时刻只能执行一条指令。当然咱们晓得线程和过程都是虚构的概念,实际上 PC 是 CPU 外围中的寄存器,它是理论存在的,所以也能够说一个 CPU 外围同一时刻只能执行一个线程。 不论是多处理器设施还是多核设施,开发者往往只须要关怀 CPU 的外围数量,而不需关怀它们的物理形成。CPU 外围数量是无限的,也就是说一个设施并发执行的线程数量是无限的,当线程数量超过 CPU 外围数量时,一个 CPU 外围往往就要解决多个线程,这个行为叫做线程调度。 线程调度简略来说就是:一个 CPU 外围轮流让各个线程别离执行一段时间。当然这两头还蕴含着简单的逻辑,后文再来剖析。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 二、多线程的优化思路在挪动端开发中,因为零碎的复杂性,开发者往往不能冀望所有线程都能真正的并发执行,而且开发者也不分明 XNU 何时切换内核态线程、何时进行线程调度,所以开发者要常常思考到线程调度的状况。 1、缩小线程切换当线程数量超过 CPU 外围数量,CPU 外围通过线程调度切换用户态线程,意味着有上下文的转换(寄存器数据、栈等),过多的上下文切换会带来资源开销。尽管内核态线程的切换实践上不会是性能累赘,开发中还是应该尽量减少线程的切换。 2、线程优先级衡量通常来说,线程调度除了轮转法以外,还有优先级调度的计划,在线程调度时,高优先级的线程会更早的执行。有两个概念须要明确: IO 密集型线程:频繁期待的线程,期待的时候会让出工夫片。CPU 密集型线程:很少期待的线程,意味着长时间占用着 CPU。非凡场景下,当多个 CPU 密集型线程霸占了所有 CPU 资源,而它们的优先级都比拟高,而此时优先级较低的 IO 密集型线程将继续期待,产生线程饿死的景象。当然,为了防止线程饿死,零碎会逐步提高被“冷清”线程的优先级,IO 密集型线程通常状况下比 CPU 密集型线程更容易获取到优先级晋升。 尽管零碎会主动做这些事件,然而这总归会造成工夫期待,可能会影响用户体验。所以笔者认为开发者须要从两个方面衡量优先级问题: 让 IO 密集型线程优先级高于 CPU 密集型线程。让紧急的工作领有更高的优先级。比方一个场景:大量的图片异步解压的工作,解压的图片不须要立刻反馈给用户,同时又有大量的异步查问磁盘缓存的工作,而查问磁盘缓存工作实现过后须要反馈给用户。 图片解压属于 CPU 密集型线程,查问磁盘缓存属于 IO 密集型线程,而后者须要反馈给用户更加紧急,所以应该让图片解压线程的优先级低一点,查问磁盘缓存的线程优先级高一点。 值得注意的是,这里是说大量的异步工作,意味着 CPU 很有可能满负荷运算,若 CPU 资源入不敷出的状况下就没那个必要去解决优先级问题。 ...

August 27, 2020 · 1 min · jiezi

关于ios:iOS事件处理-UIResponder

UIResponder是iOS中用于解决用户事件的API,能够解决触摸事件、按压事件(3D touch)、近程管制事件、硬件静止事件。能够通过touchesBegan、pressesBegan、motionBegan、remoteControlReceivedWithEvent等办法,获取到对应的回调音讯。 _**UIResponder**不只用来接管事件,还能够解决和传递对应的事件,_如果以后响应者不能解决,则转发给其余适合的响应者解决。 应用程序通过响应者来接管和处理事件,响应者能够是继承自UIResponder的任何子类,例如UIView、UIViewController、UIApplication等。当事件来到时,零碎会将事件传递给适合的响应者,并且将其成为第一响应者。 第一响应者未解决的事件,将会在响应者链中进行传递,传递规定由UIResponder的nextResponder决定,能够通过重写该属性来决定传递规定。当一个事件到来时,第一响应者没有接管音讯,则顺着响应者链向后传递。 查找第一响应者根底API查找第一响应者时,有两个十分要害的API,查找第一响应者就是通过一直调用子视图的这两个API实现的。 调用办法,获取到被点击的视图,也就是第一响应者。 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; hitTest:withEvent:办法外部会通过调用这个办法,来判断点击区域是否在视图上,是则返回YES,不是则返回NO。 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; 查找第一响应者应用程序接管到事件后,将事件交给keyWindow并转发给根视图,根视图依照视图层级逐级遍历子视图,并且遍历的过程中一直判断视图范畴,并最终找到第一响应者。 从keyWindow开始,向前逐级遍历子视图,一直调用UIView的hitTest:withEvent:办法,通过该办法查找在点击区域中的视图后,并持续调用返回视图的子视图的hitTest:withEvent:办法,以此类推。如果子视图不在点击区域或没有子视图,则以后视图就是第一响应者。 在hitTest:withEvent:办法中,会从上到下遍历子视图,并调用subViews的pointInside:withEvent:办法,来找到点击区域内且最下面的子视图。如果找到子视图则调用其hitTest:withEvent:办法,并继续执行这个流程,以此类推。如果子视图不在点击区域内,则疏忽这个视图及其子视图,持续遍历其余视图。 能够通过重写对应的办法,管制这个遍历过程。通过重写pointInside:withEvent:办法,来做本人的判断并返回YES或NO,返回点击区域是否在视图上。通过重写hitTest:withEvent:办法,返回被点击的视图。 此办法在遍历视图时,疏忽以下三种状况的视图,如果视图具备以下特色则疏忽。然而视图的背景色彩是clearColor,并不在疏忽范畴内。 视图的hidden等于YES。视图的alpha小于等于0.01。视图的userInteractionEnabled为NO。如果点击事件是产生在视图外,但在其子视图外部,子视图也不能接管事件并成为第一响应者。这是因为在其父视图进行hitTest:withEvent:的过程中,就会将其疏忽掉。 作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这是一个我的iOS交换群:642363427不论你是小白还是大牛欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长!事件传递传递过程UIApplication接管到事件,将事件传递给keyWindow。keyWindow遍历subViews的hitTest:withEvent:办法,找到点击区域内适合的视图来处理事件。UIView的子视图也会遍历其subViews的hitTest:withEvent:办法,以此类推。直到找到点击区域内,且处于最上方的视图,将视图逐渐返回给UIApplication。在查找第一响应者的过程中,曾经造成了一个响应者链。应用程序会先调用第一响应者处理事件。如果第一响应者不能处理事件,则调用其nextResponder办法,始终找响应者链中能解决该事件的对象。最初到UIApplication后依然没有能解决该事件的对象,则该事件被废除。

August 26, 2020 · 1 min · jiezi

关于ios:GCD队列组合多变化

GCD四队列六组合四队列1、主队列(是串行队列) // dispatch_queue_t mainQueue = dispatch_get_main_queue();2、全局并行队列 // dispatch_queue_t concu = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//两个参数,前者是优先级,后者目前用不到3、创立串行队列 // dispatch_queue_t queueSerial = dispatch_queue_create("je", DISPATCH_QUEUE_SERIAL);//两个参数,前者是名字(留神是c字符串),后者是队列类型。4、创立并行队列(个别应用零碎带的全局并行队列即可) // dispatch_queue_t queueConcu = dispatch_queue_create("jr2", DISPATCH_QUEUE_CONCURRENT);六种组合1.同步执行+串行队(不会开拓子线程) // dispatch_sync(queueSerial, ^{// [NSThread sleepForTimeInterval:2];// NSLog(@"1111%@", [NSThread currentThread]);// });// // dispatch_sync(queueSerial, ^{// [NSThread sleepForTimeInterval:2];//// NSLog(@"2222%@", [NSThread currentThread]);// });2.同步执行+并行队列(不会开拓子线程) // dispatch_sync(queueConcu, ^{// [NSThread sleepForTimeInterval:2];//// NSLog(@"3333%@", [NSThread currentThread]);// });// // dispatch_sync(queueConcu, ^{// [NSThread sleepForTimeInterval:2];//// NSLog(@"4444%@", [NSThread currentThread]);// });3.异步执行+串行队列(开启一条子线程,且程序执行) // dispatch_async(queueSerial, ^{// [NSThread sleepForTimeInterval:2];// NSLog(@"5555%@", [NSThread currentThread]);// });// // dispatch_async(queueSerial, ^{// [NSThread sleepForTimeInterval:2];// NSLog(@"6666%@", [NSThread currentThread]);// });4.异步执行+并行队列(开启多条子线程,且并发执行) ...

August 26, 2020 · 1 min · jiezi

关于ios:iOS-多线程面试题

iOS中的多线程 1.过程与线程 过程: 1.过程是一个具备肯定独立性能的程序对于某次数据汇合的一次运行流动,它是操作系统分配资源的根本单元. 2.过程是指在零碎中正在运行的一个应用程序,就是一段程序的执行过程,咱们能够了解为手机上的一个app. 3.每个过程之间是独立的,每个过程均运行在其专用且受爱护的内存空间内,领有独立运行所需的全副资源线程 1.程序执行流的最小单元,线程是过程中的一个实体. 2.一个过程要想执行工作,必须至多有一条线程.应用程序启动的时候,零碎会默认开启一条线程,也就是主线程过程和线程的关系 1.线程是过程的执行单元,过程的所有工作都在线程中执行 2.线程是 CPU 分配资源和调度的最小单位 3.一个程序能够对应多个过程(多过程),一个过程中可有多个线程,但至多要有一条线程 4.同一个过程内的线程共享过程资源次要有三种:NSThread、NSoperationQueue、GCD 1. NSThread:轻量级别的多线程技术iOS开发交换技术群:[563513413](正在跳转),不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 是咱们本人手动开拓的子线程,如果应用的是初始化形式就须要咱们本人启动,如果应用的是结构器形式它就会主动启动。只有是咱们手动开拓的线程,都须要咱们本人治理该线程,不只是启动,还有该线程应用结束后的资源回收 NSThread \*thread = \[\[NSThread alloc\] initWithTarget:self selector:@selector(testThread:) object:@"我是参数"\]; // 当应用初始化办法进去的主线程须要start启动 \[thread start\]; // 能够为开拓的子线程起名字 thread.name = @"NSThread线程"; // 调整Thread的权限 线程权限的范畴值为0 ~ 1 。越大权限越高,先执行的概率就会越高,因为是概率,所以并不能很精确的的实现咱们想要的执行程序,默认值是0.5 thread.threadPriority = 1; // 勾销以后曾经启动的线程 \[thread cancel\]; // 通过遍历结构器开拓子线程 \[NSThread detachNewThreadSelector:@selector(testThread:) toTarget:self withObject:@"结构器形式"\];performSelector...只有是NSObject的子类或者对象都能够通过调用办法进入子线程和主线程,其实这些办法所开拓的子线程也是NSThread的另一种体现形式。 在编译阶段并不会去查看办法是否无效存在,如果不存在只会给出正告* //在以后线程。提早1s执行。响应了OC语言的动态性:提早到运行时才绑定办法 \[self performSelector:@selector(aaa) withObject:nil afterDelay:1\]; // 回到主线程。waitUntilDone:是否将该回调办法执行完在执行前面的代码,如果为YES:就必须等回调办法执行实现之后能力执行前面的代码,说白了就是阻塞以后的线程;如果是NO:就是不等回调办法完结,不会阻塞以后线程 \[self performSelectorOnMainThread:@selector(aaa) withObject:nil waitUntilDone:YES\]; //开拓子线程 \[self performSelectorInBackground:@selector(aaa) withObject:nil\]; //在指定线程执行 \[self performSelector:@selector(aaa) onThread:\[NSThread currentThread\] withObject:nil waitUntilDone:YES\]须要留神的是:如果是带afterDelay的延时函数,会在外部创立一个 NSTimer,而后增加到以后线程的Runloop中。也就是如果以后线程没有开启runloop,该办法会生效。在子线程中,须要启动runloop(留神调用程序) ...

August 26, 2020 · 1 min · jiezi

关于ios:Auto-Layout的使用

这是对于主动布局的第一篇文章。 >> Stack View的应用主动布局(Auto Layout)可能依据对视图的束缚(Constraint),动静地计算视图层次结构中所有视图的大小和地位。 基于束缚的Auto Layout使咱们可能搭建动静响应外部、内部变动的用户界面。内部变动包含用户扭转窗口大小(OS X)、旋转设施(iOS)、在iPad上进入或来到宰割视图(iOS)、不同屏幕尺寸,外部变动包含app显示内容长度变动、字体大小变动、对国际化的反对等。 大部分的内部变动会在运行时产生,这就要求app要动静的调整视图布局。只管屏幕尺寸不会扭转,但创立一个主动布局的界面就能够实用于iPhone SE、iPhone 7 Plus、甚至iPad不同尺寸屏幕的设施。 当用户界面中视图或控件大小变动时会导致外部变动。如对国际化的反对,把用户界面上的文字扭转为其余语言时,新的语言可能占用不同大小空间;不同的语言有不同布局方向,如英语、中文都是自左向右,而阿拉伯语自右向左,这时中、英文界面右下角的按钮在阿拉伯语中应在左下角。如app反对调整字体大小,调整后用户界面中任何文本的高度和宽度都会发生变化,此时须要调整布局。 1. Auto Layout与Frame-Based Layout比拟布局用户界面形式有三种,第一种是代码形式,第二种是应用Autoresizing masks,第三种是应用Auto Layout。 通过代码形式来布局用户界面时须要设定视图在其父视图坐标系中的地位和大小。 为布局界面,你必须计算视图层级中每一个视图的地位和大小。如果其中一个产生了扭转,你就须要再次计算所有受影响的视图。在许多方面,以代码形式构建的界面会更灵便、更弱小。当界面有变动时,你能够操作其它视图的变动。也正因为你须要管制其它视图的变动,构建一个简略的界面可能须要大量工作,构建一个自适应的界面就变的更加艰难。 第二种形式是应用Autoresizing masks来构建界面,Autoresizing masks指定视图如何随父视图的变动而扭转,这简化了适应内部变动布局的复杂度。Autoresizing masks用于较小数量的可能布局,对于简单的用户界面,须要联合应用代码布局。另外,Autoresizing masks只实用于内部变动,不响应外部变动。 第三种形式为应用Auto Layout增加一系列束缚来构建界面,这些束缚代表两个视图间的关系,最初Auto Layout依据这些束缚计算出视图的地位和大小。Auto Layout动静的响应外部、内部变动。 视图层次结构布局被定义为一系列线性方程。每个束缚示意一个方程。指标是申明一系列方程,最初只有一个可能的布局计划。下图是一个示例方程。 这个束缚示意Red视图的Leading必须在Blue视图Trailing后8points,该方程由以下几局部组成: Item 1:方程式中的第一项,这里指Red视图。第一项必须是视图或布局参考线(Layout Guide)。Attribute 1:在Item 1增加束缚的地位。在这里是Red视图的Leading。Relationship:左右两侧的关系,能够是equal、greater than or equal和less than or equal之一。在这里左右两侧相等。Multiplier:第二项的值乘以该浮点值。在这里,乘数是1.0。Item 2:方程式中的第二项,在这里是Blue视图。与第一项不同,这一项能够为空。Attribute 2:在Item 2增加束缚的地位。在这里是Blue视图的Trailing。如果Item 2为空,这里也要为空。Constant:浮点类型的常量。在这里是8.0,该值被增加到Attribute 2。通过创立这样的方程能够创立多种束缚,能够定义两个视图间的间隔,对齐视图、定义两个视图大小关系、定义视图宽高比(Aspect Ratio)。 须要阐明的是下面方程式中的=是相等,不是赋值。当Auto Layout布局界面时,会计算Attribute 1和Attribute 2的值直到等式成立,而不会间接把右侧的值赋值给左侧。因而咱们能够调换等式左右两侧的值,但恪守上面规定的束缚更易于保护。不合乎上面规定的束缚能够通过调换等式两侧解决。 Multiplier优先应用整数而非分数。常量优先应用负数而非正数。如果可能,视图更应该自上而下,自左向右布局。束缚既能够用来形容界面中两个视图间的关系,也能够定义一个视图中不同属性间的关系。例如设置视图高度和宽度的高宽比。 在主动布局中,可供束缚的属性有左右高低四边(leading,trailing,top和bottom)、宽、高、程度居中和垂直居中等。 2. 创立demo这里创立一个Single View Application模板的利用,Product Name为AutoLayout,Language为Objective-C,Devices为Universal,抉择文件地位,创立工程。 上面通过几个示例来体验Auto Layout。 ...

August 25, 2020 · 2 min · jiezi

关于ios:Flutter-详解-六深入了解Stream

FutureFuture有三种状态未实现、实现带有值、实现带有异样,应用Future能够简化事件工作。 如果你有一个按钮,点击之后开始下载图片,首先事件循环机制会解决你的点击事件,而后开始下载图片,当下载实现,你能够应用then来注册回调,而后获取到图片并显示进去。 通常咱们不会间接创立,网络下载图片会返回一个Future,文件I/O会返回一个Future,那咱们怎么创立一个呢?只须要关键字async就示意该函数异步执行,返回类型是Future<T>。 Future<String> getStr()async{ var str = HttpRequest.getString('www.fgyong.cn'); return str;}应用http申请地址www.fgyong.cn获取数据,而后返回。 如何接管文本呢? 其实很简略,只须要应用await关键字即可,用来注册then回调。 main(List<String> args) async { String string = await getStr(); print(string);}等同于: main(List<String> args) async { getStr().then((value) { print(value); });}官网比拟举荐前者,因为前者看起来很像同步函数,少了层层嵌套,不便开发者了解代码。网络下载想提早动画暗藏工夫,能够应用Future.delayed()。 await Future.delayed(Duration(seconds: 2), () {hideAnimation();});如果曾经带有值的想异步去执行,那么能够应用Future.value() Streamdart:async库蕴含对许多Dart API很重要的两种类型:Stream和Future。如果Future示意单个计算的后果,则流是一系列后果。您侦听流以获取无关后果(数据和谬误)以及流敞开的告诉。您还能够在收听流时暂停播放或在流实现之前进行收听。 如何应用Stream流能够通过多种形式创立,后续在认真解说,然而它们都能够以雷同的形式应用:异步for循环(通常仅称为await for)遍历流的事件,如for循环迭代遍历。例如: Future<int> sumStream(Stream<int> stream) async { var sum = 0; await for (var value in stream) { sum += value; } return sum;}此代码仅接管整数事件流中的每个事件,将它们相加,而后返回(和)其和。当循环主体完结时,函数将暂停,直到下一个事件达到或流实现为止。 该函数标记有async关键字,在应用await for循环时须要此关键字。 以下示例通过应用async *函数生成简略的整数流来测试后面的代码: ...

August 25, 2020 · 4 min · jiezi

关于ios:MachO运行时优化

App 运行实践编译器做了什么 预处理符号化 (Tokenization)宏定义的开展#include的开展语法和语义剖析将符号化后的内容转化为一棵解析树 (parse tree)解析树做语义剖析输入一棵_形象语法树_(Abstract Syntax Tree* (AST))生成代码和优化将 AST 转换为更低级的两头码 (LLVM IR)对生成的两头码做优化生成特定指标代码输入汇编代码汇编器将汇编代码转换为指标对象文件。链接器将多个指标对象文件合并为一个可执行文件 (或者一个动静库)所以总的流程以流程图来示意的话如下图所示 main() 执行前产生的事Mach-O 格局虚拟内存根底Mach-O 二进制的加载实践速成Mach-O 术语Mach-O 是针对不同运行时可执行文件的文件类型。 文件类型: Executable: 利用的次要二进制Dylib: 动态链接库(又称 DSO 或 DLL)Bundle: 不能被链接的 Dylib,只能在运行时应用 dlopen() 加载,可当做 macOS 的插件。Image: executable,dylib 或 bundle Framework: 蕴含 Dylib 以及资源文件和头文件的文件夹 Mach-O 镜像文件Mach-O 被划分成一些 segement,每个 segement 又被划分成一些 section。 segment 的名字都是大写的,且空间大小为页的整数。页的大小跟硬件无关,在 arm64 架构一页是 16KB,其余为 4KB。 section 尽管没有整数倍页大小的限度,然而 section 之间不会有重叠。 简直所有 Mach-O 都蕴含这三个段(segment): __TEXT,__DATA 和 __LINKEDIT: __TEXT 蕴含 Mach header,被执行的代码和只读常量(如C 字符串)。只读可执行(r-x)。__DATA 蕴含全局变量,动态变量等。可读写(rw-)。__LINKEDIT 蕴含了加载程序的『元数据』,比方函数的名称和地址。只读(r–)。Mach-O Universal 文件FAT 二进制文件,将多种架构的 Mach-O 文件合并而成。它通过 Fat Header 来记录不同架构在文件中的偏移量,Fat Header 占一页的空间。 ...

August 23, 2020 · 4 min · jiezi

关于ios:1-版本管理工具及-Ruby-工具链环境

CocoaPods 历险记这个专题是 Edmond 和冬瓜 是对于 iOS / macOS 工程中版本管理工具 CocoaPods 的实现细节、原理、源码、实际与教训的分享记录,旨在帮忙大家可能更加理解这个依赖管理工具,而不仅局限于 pod install 和 pod update。本文常识目录 背景CocoaPods 作为业界规范,各位 iOS 开发同学应该都不生疏。不过很多同学对 CocoaPods 的应用根本停留在 pod install 和 pod update 上。一旦我的项目组件化,各业务线逻辑拆分到独立的 Pod 中后,光理解几个简略 Pod 命令是无奈满足需要的,同时还面临开发环境的一致性,Pod 命令执行中的各种异样谬误,都要求咱们对其有更深层的认知和 ????。 对于 CocoaPods 深刻的文章有很多,举荐 ObjC China 的这篇,深刻了解 CocoaPods,而本文心愿从依赖管理工具的角度来谈谈 CocoaPods 的治理理念。 Version Control System (VCS)Version control systems are a category of software tools that help a software team manage changes to source code over time. Version control software keeps track of every modification to the code in a special kind of database.软件工程中,版本控制系统是麻利开发的重要一环,为后续的继续集成提供了保障。Source Code Manager (SCM) 源码治理就属于 VCS 的范畴之中,熟知的工具有如 Git 。而 CocoaPods 这种针对各种语言所提供的 Package Manger (PM)也能够看作是 SCM 的一种。 ...

August 21, 2020 · 6 min · jiezi

关于ios:GrowingIO-数据采集-iOS-SDK-测试实践

作者:吕雨强 GrowingIO iOS 测试工程师,次要负责 iOS SDK 功能测试、自动化测试 。 GrowingIO 是基于用户行为数据的增长平台,精准采集用户行为数据是公司业务的基石,只有及时、精确、牢靠的采集到数据,能力撑持下层的数据分析,用户画像,经营等业务,所以公司始终十分重视数据采集 SDK(Software Development Kit) 的质量保证工作。 为了满足客户的各种业务与技术的需要,GrowingIO 提供了 Web、Android、 iOS、Hybrid、各种小程序(微信、支付宝、头条、QQ 等 )、微信内嵌页等多种平台,以及 React Native、Flutter 、Cordova、Weex 、API Cloud 、AppCan 泛滥开发框架的 SDK,这无疑为 SDK 的测试工作带来的微小的挑战。 本文次要介绍 GrowingIO 在 iOS SDK 测试方面的具体实际,心愿对从事 iOS 测试的同学提供一些参考。 1. 数据采集 SDK 是如何工作的?要测试一个软件或零碎首先必须要先理解其业务逻辑和技术实现,接下来咱们简略看下数据采集 SDK 是如何工作的。 GrowingIO 的数据采集 SDK 反对无埋点(全埋点)数据采集以及埋点数据采集,以满足不同的业务需要,其繁难构造如下: 在用户关上 App ,浏览不同的页面,点击不同的元素(如按钮,文本框,图片),敞开 App 时,无埋点事件采集模块会将用户的具体行为主动采集并保留到手机的本地存储(对于无埋点数据采集的具体实现,欢送关注 GrowigIO 后续的文章分享,这里不再详述)。 埋点事件采集与之相似,不同之处是埋点事件是由 App 被动调用 SDK 的埋点 API 触发事件采集,当然不同事件的具体数据格式有所不同。 接下来是数据发送模块,其次要负责将数据通过 HTTP API 上报到数据接管服务。须要阐明的是,为了节约用户的数据流量和电量,发送程序并不是实时上报的,它会依据设施的电量、网络类型、以及数据量进行发送机会的抉择,而且发送前还会对数据进行压缩和混同以升高传输数据量并晋升数据安全性。当然数据发送程序还会解决数据上报中的各种数据发送失败,网络异样等谬误,采取适当的重试机制。 2. 如何测试?通过以上构造剖析,能够看出数据发送模块跟外围的数据采集业务关系不大,并且很稳固,简直不会改变,因而咱们测试的重点次要是数据采集局部,尤其是无埋点数据采集。 ...

August 21, 2020 · 3 min · jiezi

关于ios:iOS开发之如何跳到系统设置里的各种设置界面

跳到更多设置界面除了跳到WiFi设置界面,能不能跳到其余的设置界面呢?比方:定位服务、FaceTime、音乐等等。都是能够的,一起来看看如何实现的! iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 定位服务定位服务有很多APP都有,如果用户敞开了定位,那么,咱们在APP外面能够提醒用户关上定位服务。点击到设置界面设置,间接跳到定位服务设置界面。代码如下: //定位服务设置界面NSURL *url = [NSURL URLWithString:@"prefs:root=LOCATION_SERVICES"];if ([[UIApplication sharedApplication] canOpenURL:url]){ [[UIApplication sharedApplication] openURL:url];}复制代码这样就能够跳到零碎设置的定位服务界面啦!咱们持续看几个列子。 FaceTime //FaceTime设置界面NSURL *url = [NSURL URLWithString:@"prefs:root=FACETIME"];if ([[UIApplication sharedApplication] canOpenURL:url]){ [[UIApplication sharedApplication] openURL:url];}复制代码音乐//音乐设置界面NSURL *url = [NSURL URLWithString:@"prefs:root=MUSIC"];if ([[UIApplication sharedApplication] canOpenURL:url]){ [[UIApplication sharedApplication] openURL:url];}复制代码墙纸设置界面//墙纸设置界面NSURL *url = [NSURL URLWithString:@"prefs:root=Wallpaper"];if ([[UIApplication sharedApplication] canOpenURL:url]){ [[UIApplication sharedApplication] openURL:url];}复制代码蓝牙设置界面//蓝牙设置界面 NSURL *url = [NSURL URLWithString:@"prefs:root=Bluetooth"]; if ([[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url]; }复制代码iCloud设置界面//iCloud设置界面NSURL *url = [NSURL URLWithString:@"prefs:root=CASTLE"];if ([[UIApplication sharedApplication] canOpenURL:url]{ [[UIApplication sharedApplication] openURL:url];}复制代码大家能够依据本人的需要,跳到不同的设置界面。你喜爱这篇文章的话,欢送分享给更多的敌人,也能够珍藏起来,以备不时之需! ...

August 20, 2020 · 1 min · jiezi

关于ios:iOS开发GCD

在iOS开发中常常会用到GCD,如果你在求职过程中GCD的应用也是面试官必问的,那么明天就来说说GCD的无关内容,不喜勿喷。 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! 一、GCD的概念1.GCD全称是Grand Central Dispatch,可译为“CPU的中枢调度器”,是C语言,提供了十分多的弱小的函数 2.GCD的劣势:GCD是苹果公司为多核的并行运算提出的解决方案,它会主动利用更多的CPU内核(比方四核),而且它会主动治理线程的生命周期(创立线程、调度工作、销毁线程),开发者只需通知GCD想要执行什么工作,不需编写任何线程治理代码。 二、GCD的外围GCD的两个核心内容:工作和队列。 1.工作:执行什么样的操作; 2.队列:拿来寄存工作。 三、GCD中执行工作的函数1、同步函数:用同步的形式执行工作 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); 2、异步函数:用异步的形式执行工作 dispatch_async(dispatch_queue_t queue, dispatch_block_t block) 同步和异步的区别: 同步:在以后线程中执行 异步:在另一条线程中执行 四、GCD相干内容1.GCD中有4个术语比拟容易混同:同步、异步、并发、串行 2.同步和异步二者的次要影响:是否开启新的线程; 同步:在以后线程中执行工作,不具备开启新线程的能力 异步:在新的线程中执行工作,具备开启新线程的能力 3.并发和串行二者的次要影响:工作的执行形式 并发:多个工作并发(同时)执行 串行:一个工作执行结束后,再执行下一个工作 留神:同步函数+主队列 == 死锁(会卡死) (值得注意的是,同步工作有一个个性是,只有一增加到队列中就要立马执行,主队列中永远就只有一条线程——主线程,此时主线程在期待着主队列调度同步工作,而主队列发现主线程上还有工作未执行完,就不会让同步工作增加到主线程上,由此就造成了相互期待(主队列在期待主线程执行完已有的工作,而主线程又在期待主队列调度同步工作,此时就造成所谓的死锁了。) 五、创立(获取)队列的形式1、串行队列: (1). 应用dispatch_queue_create函数创立串行队列 dispatch_queue_t queue =dispatch_queue_create("Lotheve", NULL); //参数别离为队列名称、队列属性(个别用NULL即可) (2).获取主队列(主队列是一种非凡的串行队列,放在主队列中的工作,都会放到主线程中执行) dispatch_queue_t queue = dispatch_get_main_queue(); 2、并发队列: 应用dispatch_get_global_queue函数取得全局并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 第一个参数别离为全局队列优先级,过程中存在3个全局队列:低、中(默认)、高三个优先级队列,这里抉择默认的。第二个参数临时无用,用0即可。 论断:明天的分享到这就完结了。

August 19, 2020 · 1 min · jiezi

关于ios:前端面试每日-31-第491天

明天的知识点 (2020.08.19) —— 第491天 (我也要出题)[html] 如何在IOS下启用WebApp全屏模式?[css] 你当初还常常写css代码吗?[js] 写一个办法,计算有N个数(可反复),别离放到M个地位中,有多少种排列?[软技能] 本地开发时如何不必批改hosts能够绑定域名开发?《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!!欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨!心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

August 19, 2020 · 1 min · jiezi

关于ios:Swift语言的特性

Swift语言有各种各样不足(或没有)文档记录的个性(attribute)放在那里等着被应用 iOS开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻 ,分享BAT,阿里面试题、面试教训,探讨技术, 大家一起交流学习成长! inline这个个性为编译器提供了内联提醒。无效的取值是__always和never。除非我认为必须要用这两个值,否则就不会应用它(特地是__always)。到目前为止与其相干的规定还不是很明确,在无限的测试下,它能够失常地工作,但还要视具体情况而定。 进一步的解释:只管底层虚拟机(Low Level Virtual Machine, LLVM)有强制内联的概念,但咱们目前还不晓得这个inline个性是否与其间接映射,也不晓得是否存在大小方面的限度,但这将会导致编译器疏忽这一点而跳过内联。实践上说应该是这样的,但我不保障肯定是。 留神:当优化设置敞开时在调试模式下的构建将疏忽inline。 transparent我最后并未将这个个性列出来。该个性会导致编译器在管道(pipeline)中更早地将函数内联。它用于[“像+(Int, Int)这样十分原始的函数”,而“不应该用于独立函数”] 甚至在没有优化设置的调试模式下transparent个性函数就会被内联,所以在调用“1+1”这样的函数的时候并不会特地慢。另外这个个性与inline(__always)十分相似。 availability这个个性能够用来标识某些函数只在某些平台或版本上可用。第一个参数是平台,能够用星号(*)代表所有可用,还能够是iOS或OS X。因为如果须要针对不同的平台,就要指定多个availability属性。 如果须要示意该函数在某个给定的平台齐全不可用时,能够将第二个参数置为unavailable。此外,还能够用introduced,deprecated和obsoleted来指定一个或是多个版本的组合:obsoleted意味着该项曾经删除,deprecated仅仅示意如果应用就会给予正告。最初你能够设置message的值,如果该项被应用了就由编译器输入。 noreturn正如该个性所形容的那样:编译器能够假设这个函数是一个永远循环运行的终点,例如while true { },或者假设是函数abort或者exit过程的状况。 评论者Marco Masser指出,如果调用另一个被标记为noreturn的函数,那么编译器会疏忽掉以后函数中缺失的返回值(missing return values),因为编译器了解程序的控制流。 asmname该属性给出了函数、办法或属性实现的符号名称。如果你曾经晓得对应的函数参数及其类型,那么就能够间接调用Swift的外部规范库函数,甚至不必头文件,也能够不便地调用C语言编写的函数: Java代码 asmname("function") func f() unsafe_no_objc_tagged_pointer下面这个依然是个谜,但我猜想它是在通知Swift与Objective-C分割的时候不要应用tagged pointer。 semantics参数看起来像是array.mutate_unknown或array.init这样的字符串数组。想必这是要通知编译器(或动态分析器)函数是如何工作的。

August 18, 2020 · 1 min · jiezi

关于ios:iOS开发中设计并发任务技术与注意事项

Dispatch Queues简述Dispatch Queues是基于C语言的,执行自定义工作的技术,从字面意思了解其实就是执行工作的队列,应用GCD执行的工作都是放在这个队列中执行的,当然队列的数量能够有多个,类型也不止一种。一个Dispatch queue能够串行的执行工作,也能够并行的执行工作,但不论哪种执行工作的形式,都遵循先进先出的准则。串行队列一次只能执行一个工作,当前任务执行完后能力执行下一个工作,并且执行工作的程序和增加工作的程序是统一的。并行队列天然是可同时执行多个工作,不须要期待上个工作实现后才执行下个工作。咱们来看看Dispatch queue还有哪些好的个性: 有简略宜用,通俗易懂的编程接口。 提供了主动治理的线程池。 可主动调节队列装载工作的速度。 更优的内存使用率。 使用户不必放心死锁的问题。 提供了比线程锁更优的同步机制。 应用Dispatch Queue时,须要将工作封装为一个函数或者一个block,block是Objective-C中对闭包的实现,在OS X 10.6和iOS 4.0时引入的,在Swift中间接为闭包 Dispatch Sources简述Dispatch Source是GCD中的一个根本类型,从字面意思可称为调度源,它的作用是当有一些特定的较底层的零碎事件产生时,调度源会捕捉到这些事件,而后能够做其余的逻辑解决,调度源有多种类型,别离监听对应类型的零碎事件。咱们来看看它都有哪些类型: Timer Dispatch Source:定时调度源。 Signal Dispatch Source:监听UNIX信号调度源,比方监听代表挂起指令的SIGSTOP信号。 Descriptor Dispatch Source:监听文件相干操作和Socket相干操作的调度源。 Process Dispatch Source:监听过程相干状态的调度源。 Mach port Dispatch Source:监听Mach相干事件的调度源。 Custom Dispatch Source:监听自定义事件的调度源。 Dispatch Source是GCD中很有意思也很有用的一个个性,依据不同类型的调度源,咱们能够监听较为底层的零碎行为,不管在实现性能方面还是调试性能方面都十分游有用,后文中会再具体讲述。 Operation Queues简述Operation Queue与Dispatch Queue很相似,都是有工作队列或操作队列的概念,只不过它是由Cocoa框架中的NSOperationQueue类实现的,它俩最次要的区别是工作的执行程序,在Dispatch Queue中,工作永远都是遵循先进先出的准则,而Operation Queue退出了其余的工作执行程序个性,使下一个工作的开始不再取决于上个工作是否已实现。 应用Dispatch Queue时,须要将工作封装为一个函数或者闭包。而在Operation Queue中,须要将工作封装为一个NSOpertaion对象,而后放入操作队列执行。同时该对象还自带键值察看(KVO)告诉个性,能够很不便的监听工作的执行过程。 设计并发工作时应该留神的事项尽管并发执行工作能够进步程序对用户操作的响应速度,最大化应用内核,晋升利用的效率,然而这些都是建设在正确正当应用并发工作技术,以及应用程序的确须要应用这类技术的前提下。如果应用不得当,或者对简略的应用程序画龙点睛,那么反而会因为应用了并发工作技术而导致应用程序性能降落,另一方面开发人员面对的代码复杂度也会减少,保护老本同样会回升。所以在筹备应用这类技术前肯定要三思而行,从性能、开发成本、保护老本等多个方面去思考是否须要应用并发工作技术。 思考是否须要用只是第一步,当确定应用后更不能自觉的就开始开发,因为并发工作技术的应用须要侵入应用程序的整个开发生命周期,所以在利用开发之初,就是思考如何依据这类技术去设计并发工作,思考利用中工作的类型、工作中应用的数据结构等等,否则亡羊补牢也为时已晚。这一节次要说说在设计并发工作时应该留神哪些事。 1.梳理应用程序中的工作 在入手写代码前,尽量依据需要,穷举利用中的工作以及在工作中波及到的对象何数据结构,而后剖析这些工作的优先级和触发类型,比方列举出哪些工作是由用户操作触发的,哪些是工作是无需用户参加触发的。 当把工作依据优先级梳理好后,就能够从高优先级的工作开始一一剖析,思考工作在执行过程中波及到哪些对象和数据结构,是否会批改变量,被批改的变量是否会对其余变量产生影响,以及工作的执行后果对整个程序产生什么影响等。举个简略的例子,如果一个工作中对某个变量进行了批改,并且这个变量不会对其余变量产生影响,而且工作的执行后果也绝对比拟独立,那么像这种工作就最合适让它异步去执行。 2.进一步细分工作中的执行单元 工作能够是一个办法,也能够是一个办法中的一段逻辑,不论是一个办法还是一段逻辑,咱们都能够从中拆分出若干个执行单元,而后进一步剖析这些执行单元,如果多个执行单元必须得依照特定得程序执行,而且这一组执行单元的执行后果想对独立,那么能够将这若干执行单元视为执行单元组,能够思考让该执行单元组异步执行,其余不须要依照特定程序的执行单元能够别离让它们异步执行。能够应用的技术能够用GCD或者Operation Queue。 在拆分执行单元时,尽量拆的细一点,不要放心执行单元的数量过多,因为GCD和Operation Queue有着高性能的线程管理机制,不须要放心过多的应用工作队列会造成性能损耗。 3.确定适合的队列 当咱们将工作合成为一个个执行单元并剖析之后,下一步就是将这些执行单元封装在block中或者封装为NSOperation对象来应用GCD或Operation Queues,但在这之前还须要咱们依据执行单元确定好适宜的队列,不论是Dispatch queue还是Operation queue,都须要明确是应用串行队列还是并行队列,确定是将多个执行单元放入一个队列中还是别离放入多个队列中,以及应用正确优先级的队列。

August 15, 2020 · 1 min · jiezi

关于ios:iOS技术面试题及答案

一、如何绘制UIView?绘制一个UIView最灵便的办法就是由它本人实现绘制。实际上你不是绘制一个UIView,而是子类化一个UIView并赋予绘制本人的能力。当一个UIView须要执行绘制操作时,drawRect:办法就会被调用,笼罩此办法让你取得绘图操作的机会。当drawRect:办法被调用,以后图形的上下文也被设置为属于视图的图形上下文,你能够应用Core Graphic或者UIKit提供的办法将图形画在该上下文中。 二、什么是MVVM?次要目标是什么?长处有哪些?MVVM即 Model-View-ViewModel 1.View次要用于界面出现,与用户输出设施进行交互、 2.ViewModel是MVVM架构中最重要的局部,ViewModel中蕴含属性,办法,事件,属性验证等逻辑,负责View与Model之间的通信 3.Model就是咱们常说的数据模型,用于数据的结构,数据的驱动,次要提供根底实体的属性。 MVVM次要目标是拆散视图和模型 MVVM长处:低耦合,可重用性,独立开发,可测试 三、get申请与post申请的区别1.get是向服务器发索取数据的一种申请,而post是向服务器提交数据的一种申请 2.get没有申请体,post有申请体 3.get申请的数据会裸露在地址栏中,而post申请不会,所以post申请的安全性比get申请号 4.get申请对url长度有限度,而post申请对url长度实践上是不会收限度的,然而实际上各个服务器会规定对post提交数据大小进行限度。 四、谈谈你对多线程开发的了解?ios中有几种实现多线程的办法?益处: 1.应用多线程能够把程序中占据工夫长的工作放到后盾去解决,如图片,视频的下载; 2.施展多核处理器的劣势,并发执行让零碎运行的更快,更晦涩,用户体验更好; 毛病: 1.大量的线程升高代码的可读性; 2.更多的线程须要更多的内存空间; 3当多个线程对同一个资源呈现抢夺的时候要留神线程平安的问题。 ios有3种多线程编程的技术:1.NSThread,2.NSOperationQueue,3.gcd; 五、XMPP工作原理;xmpp零碎特点原理: 1.所有从一个client到另一个client的jabber音讯和数据都要通过xmpp server 2.client链接到server 3.server利用本地目录零碎的证书对其认证 4.server查找,连贯并进行互相认证 5.client间进行交互 特点:1)客户机/服务器通信模式;2)分布式网络;3)简略的客户端;4)XML的数据格式 六、地图的定位是怎么实现的?1.导入了CoreLocation.framework 2.ios8当前,如果须要应用定位性能,就须要申请用户受权,在首次运行时会弹框提醒 3.通过本机自带的gps获取地位信息(即经纬度) 七、苹果内购实现流程程序通过bundle存储的plist文件失去产品标识符的列表。 程序向App Store发送申请,失去产品的信息。 App Store返回产品信息。 程序把返回的产品信息显示给用户(App的store界面) 用户抉择某个产品 程序向App Store发送领取申请 App Store解决领取申请并返回交易实现信息。 App获取信息并提供内容给用户。 八、支付宝,微信等相干类型的sdk的集成1.在支付宝开发平台创立利用并获取APPID 2.配置密钥 3.集成并配置SDK 4.调用接口(如交易查问接口,交易退款接口) 九、 gcd产生死锁的起因及解锁的办法产生死锁的必要条件:1.互斥条件,2.申请与放弃条件,3.不剥夺条件,4.循环期待条件。 解决办法:采纳异步执行block。 十、生成二维码的步骤1.应用CIFilter滤镜类生成二维码 2.对生成的二维码进行加工,使其更清晰 3.自定义二维码背景色、填充色 4.自定义定位角标 5.在二维码核心插入小图片 总结以上就是这篇文章的全部内容了,心愿本文的内容对各位iOS开发者们在面试的时候能有所帮忙。

August 14, 2020 · 1 min · jiezi

关于ios:iOS编译器调试工具包管理器系统框架漫谈

本文次要介绍1.Clang与LLVM2.GDB与LLDB3.homebrew与CocoaPods等4.iOS零碎框架1.Clang与LLVMLLVM我的项目的倒退起源于2000年伊利诺伊大学厄巴纳-香槟分校维克拉姆·艾夫(Vikram Adve)与克里斯·拉特纳(Chris Lattner)的钻研,他们想要为所有动态及动静语言发明出动静的编译技术。LLVM是以BSD受权来倒退的开源软件。2005年,苹果电脑雇用了克里斯·拉特纳及他的团队为苹果电脑开发应用程序零碎,LLVM为现今Mac OS X及iOS开发工具的一部分。 LLVM的命名最早源自于底层虚拟机(Low Level Virtual Machine)的首字母缩写,因为这个我的项目的范畴并不局限于创立一个虚拟机,这个缩写导致了宽泛的纳闷。LLVM开始成长之后,成为泛滥编译工具及低级工具技术的统称,使得这个名字变得更不贴切,开发者因此决定放弃这个缩写的意涵,现今LLVM已单纯成为一个品牌,实用于LLVM下的所有我的项目,蕴含LLVM中介码(LLVM IR)、LLVM除错工具、LLVM C++规范库等。 Xcode3之前,用的是GCCXcode3,GCC依然保留,然而也推出了LLVM,苹果举荐LLVM-GCC混合编译器,但还不是默认编译器Xcode4,LLVM-GCC成为默认编译器,但GCC仍保留Xcode4.2,LLVM3.0成为默认编译器,纯用GCC不复可能Xcode4.6,LLVM降级到4.2版本Xcode5,LLVM-GCC被遗弃,新的编译器是LLVM5.0,从GCC过渡到LLVM的时代正式实现Clang - a C language family frontend for LLVMClang(发音为/klæŋ/) 是一个C、C++、Objective-C和Objective-C++编程语言的编译器前端。它采纳了底层虚拟机(LLVM)作为其后端。它的指标是提供一个GNU编译器套装(GCC)的替代品。作者是克里斯·拉特纳,在苹果公司的资助反对下进行开发,而源代码受权是应用类BSD的伊利诺伊大学厄巴纳-香槟分校开源码许可。 Clang我的项目包含Clang前端和Clang动态分析器等。 Clang的在出世之前就曾经明确了他的使命——干掉该死的GCC。有了LLVM+Clang,从此,苹果的开发风貌面目一新。从此解脱了GCC的限度。主观的说GCC是有很多的长处,例如反对多平台,很风行,基于C无需C++编译器即可编译。这些长处到苹果那就可能是毛病了,苹果须要的是——快。这正是Clang的长处,除了快,它还有与GCC兼容,内存占用小,诊断信息可读性强,易扩大,易于IDE集成等等长处。有个测试数据:Clang编译Objective-C代码时速度为GCC的3倍。 iOS编译过程Objective-C与swift都采纳Clang作为编译器前端,编译器前端次要进行语法分析,语义剖析,生成中间代码,在这个过程中,会进行类型查看,如果发现错误或者正告会标注进去在哪一行。编译器后端会进行机器无关的代码优化,生成机器语言,并且进行机器相干的代码优化,依据不同的零碎架构生成不同的机器码。 C++,Objective C都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码。 如上图所示,在xcode按下cmd+B之后的工作流程。 预处理(Pre-process):他的次要工作就是将宏替换,删除正文开展头文件,生成.i文件。 词法剖析 (Lexical Analysis):将代码切成一个个 token,比方大小括号,等于号还有字符串等。是计算机科学中将字符序列转换为标记序列的过程。 语法分析(Semantic Analysis):验证语法是否正确,而后将所有节点组成形象语法树 AST 。由 Clang 中 Parser 和 Sema 配合实现 动态剖析(Static Analysis):应用它来示意用于剖析源代码以便主动发现错误。 两头代码生成(Code Generation):开始IR中间代码的生成了,CodeGen 会负责将语法树自顶向下遍历逐渐翻译成 LLVM IR,IR 是编译过程的前端的输入后端的输出。 优化(Optimize):LLVM 会去做些优化工作,在 Xcode 的编译设置里也能够设置优化级别-01,-03,-0s,还能够写些本人的 Pass,官网有比拟残缺的 Pass 教程: Writing an LLVM Pass — LLVM 5 documentation 。如果开启了 bitcode 苹果会做进一步的优化,有新的后端架构还是能够用这份优化过的 bitcode 去生成。生成指标文件(Assemble):生成Target相干Object(Mach-o) 链接(Link):生成 Executable 可执行文件 ...

August 14, 2020 · 6 min · jiezi

关于ios:iOS开发设计面试题汇总

1.常见问题你为什么热衷于软件开发? 你对哪一种控制系统比拟相熟? 是否参加过GitHub我的项目? 是否参加过GitHub或其余同类型网站的iOS开源我的项目? 是否熟知CocoaPods?它是什么?如何运行的? 请概括一下你在构建iOS利用时的测试过程。iOS利用如何实现对其余语言、日期格局以及货币单位的反对? 请形容一下Instruments及其作用 2.对于iOS技术请解释一下Handoff是什么,并简述它是如何实现iOS、Mac/网页利用互通的。 iOS扩大是指?是否列举一些热门或常见的范例? VoiceOver是什么?请举例解释一下iOS中的辅助性能(Accessibility)。开发者如何应用这些性能? 请解释一下NSUserDefaults。就你而言,你会如何在磁盘中对数组对象进行序列化? AirPlay是如何运行的?换做是你,你会如何通过编程进步利用的实用性以及演示成果? 传感器,IO以及WiFi、拨号等连贯形式如何在iOS平台上运作?它们有何利用价值?请简要地谈谈你的观点。 iPad 2,iPad mini 1-3,iPad Retina,iPad Air 2,iPhone 5、5S、6以及6+在硬件性能方面有何差别?这对重视性能的利用有何限度? 3.对于编程Cocoa Touch蕴含什么?不蕴含什么? 为什么Cocoa Touch的类名称是以两个大写字母结尾的? Swift和Objective-C别离是什么?两者相比有何不同之处,又有何分割? 为什么Optional在Swift语言中十分重要? 请解释一下NSError。在Swift中,什么状况下能应用NSError ,什么状况下不能? 请阐明如何应用Instancetype及其重要性。 在Swift中,什么时候该用let,什么时候该用var? 为什么map函数必不可少?该在什么状况下应用它? 你会抉择什么工具来追踪Bug? 如果在Cocoa中发现一个Bug,你会如何解决? 你认为iOS须要增加或改良哪些API? 4.对于界面请解释一下Interface Builder的作用以及NIB文件的概念。 iOS UI的图像贮存类型是什么? 请形容一下Storyboard和规范NIB文件的差异。 设施状态栏(Device Status Bar)是什么?高度如何?是否通明?在手机通话或者导航状态下,它是如何显示的? 导航栏(Navigation Bar)是什么?是否拿出你的iPhone,指出你下载的哪些利用使用了导航栏? 选项卡(Tab Bar)和工具栏(Toolbar)别离是什么?两者之间有何共同点和不同点? 5.对于设计iOS利用图标是指什么?请尽可能具体地形容一下。 最小尺寸和最大尺寸的利用图标别离是什么样子的? 利用图标是否蕴含通明的局部? Newsstand的图标与惯例利用有何不同? 请解释一下启动画面(Launch Images)。 主动布局(Auto Layout)的作用是什么?请概括一下它是如何运行的。 设计软件时为什么要加上动画 论断最好能始终跟上iOS世界的变动,那对你来说是很无利的.即便你有很大概率在新工作中并不需要晓得所有那些常识,对新常识持凋谢态度总是好的,并且,你能够让面试官晓得你始终在一直的学习。

August 13, 2020 · 1 min · jiezi

关于ios:iOS开发隐藏键盘方法总结

一、暗藏本身软键盘当对于有多个UITextField控件都想通过点击“Return”来暗藏本身软键盘的状况,这时的最好方法是应用Did End on Exit事件。在点击软键盘右下角的“Return”按钮后,会触发该事件。 该事件有一个sender参数示意以后文本框,这样便能够编写一个通用的事件处理办法(.m文件)。 - (IBAction)TextField_DidEndOnExit:(id)sender {// 暗藏键盘.[sender resignFirstResponder];}而后在.h文件中填写该办法的申明—— - (IBAction)TextField_DidEndOnExit:(id)sender; 回到storyboard,并按command+option+enter关上辅助窗口,使辅助窗口显示.h文件。 选中一个UITextField控件,点击鼠标右键弹出面板,鼠标左键按住Did End on Exit事件旁边的圆圈,而后拖曳到右侧.h文件的TextField_DidEndOnExit办法上,便会建设好事件连贯。 随后依照同样的做法,将其余UITextField控件的Did End on Exit事件也连贯到TextField_DidEndOnExit办法。 运行一下,可发现每个文本框的软键盘都能够通过点击“Return”来暗藏了 二、点击Return主动转到下个文本框当页面中有很多个文本框时,如果每次都须要点文本框激活软键盘、输出后点击Return暗藏软键盘、再点击下一个文本框……这样操作起来太繁琐了。 于是咱们心愿可能实现点击Return时可能主动转到下一个文本框。尤其是对于最初一个文本框,心愿可能在点击Return时执行下一步操作。 例如对于登录页面。它下面有 账号文本框(nameTextField)、明码文本框(passTextField)、登录按钮(loginButton)。 咱们心愿——点击账号文本框软键盘的Return时跳转到明码文本框,点击明码文本框软键盘的Return时执行登录。 因为这两个文本框的性能不同,不能像上一节那样写一个TextField_DidEndOnExit做对立解决,而应该别离建设各自的事件处理办法。 回到storyboard,右击账号文本框(nameTextField)弹出面板,按住Did End on Exit事件旁边的圆圈,而后拖曳到右侧.h文件的空白中央,此时会弹出一个对话框给办法命名。输出名称 (nameTextField_DidEndOnExit)后回车确定,便主动生成了该事件办法。 随后依照同样的做法,为明码文本框(passTextField)的Did End on Exit事件连贯办法(passTextField_DidEndOnExit)。 来到.m文件,填写具体代码—— - (IBAction)nameTextField_DidEndOnExit:(id)sender { // 将焦点移至下一个文本框. [self.passTextField becomeFirstResponder];}- (IBAction)passTextField_DidEndOnExit:(id)sender {// 暗藏键盘.[sender resignFirstResponder];// 触发登陆按钮的点击事件.[self.loginButton sendActionsForControlEvents:UIControlEventTouchUpInside];}对于账号文本框转明码文本框,不须要暗藏软键盘,只须要调用becomeFirstResponder激活新的文本框就行了。 对于明码文本框Return后执行登录。因为不再须要显示软键盘,所以还是得调用resignFirstResponder暗藏软键盘,而后触发登录按钮(loginButton)的UIControlEventTouchUpInside事件进行登录。 运行一下,可发现曾经达到咱们心愿的成果了。点击账号文本框软键盘的Return时跳转到明码文本框,点击明码文本框软键盘的Return时执行登录。 怎么都是“Return”,转换文本框与执行登录明明是不同的性能? 于是将账号文本框的Return Key属性设为“Next”,将明码文本框的Return Key属性设为“Done”,使界面与性能统一。 三、轻触背景暗藏软键盘只能通过Return敞开软键盘太不灵便了,应该提供轻触背景暗藏软键盘的性能。 在storyboard,点击背景View,将它的Custom Class设置为UIControl,这样才会呈现Touch Down事件。 右击背景View弹出面板,按住Touch Down事件旁边的圆圈,而后拖曳到右侧.h文件的空白中央建设该事件的解决办法。 来到.m文件,填写具体代码—— - (IBAction)View_TouchDown:(id)sender {// 发送resignFirstResponder.[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];}

August 12, 2020 · 1 min · jiezi

关于ios:ObjectiveC之内存管理漫谈

内存治理是程序在运行时分配内存、应用内存,并在程序实现时开释内存的过程。在Objective-C中,也被看作是在泛滥数据和代码之间调配无限内存资源的所有权(Ownership)的一种形式。 内存治理关怀的是清理或回收不必的内存,以便内存可能再次利用。如果一个对象不再应用,就须要开释对象占用的内存。Objective-C提供了两种内存治理的办法:手动治理内存计数(MRR)和主动援用计数(ARC)。这两种办法都采纳了一种称为“援用计数”的模型来实现,该模型由Foundation框架的NSObject类和运行时环境(Runtime Environment)独特提供。上面,咱们就先来介绍下什么是援用计数。 1 援用计数援用计数(Reference Count)是一个简略而无效的治理对象生命周期的形式,个别概念是:当创立一个新的对象时,初始的援用计数为1。为保障对象的存在,每当创立一个援用到该对象时,通过给对象发送retain音讯,为援用计数加1;当不再须要对象时,通过给对象发送release音讯,为援用计数减1;当对象的援用计数为0时,零碎就晓得这个对象不再应用了,通过给对象发送dealloc音讯,销毁对象并回收内存。个别在retain办法之后,援用计数通常也被称为保留计数(retain count)。 为了更好地论述援用计数的机制,这里援用开关房间灯的例子来阐明: 假如办公室的照明设备只有一个,进入办公室的人须要照明,来到办公室的人不须要照明。因而,为保障办公室仅有的照明设备失去很好的治理,只有办公室还有人,就会须要照明,灯就得开着,而当办公室没人的时候,就须要关灯。为了判断办公室是否还有人,咱们导入计数性能来计算“须要照明的人数”: 第一个进入办公室的人,须要照明,此时,“须要照明的人数”为1,计数值从0变为1,须要开灯。第二个进入办公室的人,也须要照明,此时,“须要照明的人数”为2,计数值从1变为2。之后,每一个进入办公室的人都须要照明,此时“须要照明的人数”顺次减少,计数值也顺次加1。当第一个人来到办公室时,不再须要照明,此时“须要照明的人数”减1,计数值也减1。之后,只有有人来到办公室,就不再须要照明,此时“须要照明的人数”顺次缩小,计数值顺次减1。当最初一个人来到办公室时,不再有人须要照明,“须要照明的人数”为0,计数值减至0,须要关灯。在Objective-C中,对象就相当于办公室的照明设备,而对象的应用环境就相当于进入办公室下班的人。其对应关系能够用以下表格来示意:进入办公室下班的人对照明设备所做的动作 对象的应用环境对Objective-C对象所做的动作 进入办公室下班的人对照明设备所做的动作对象的应用环境对Objective-C对象所做的动作开灯生成对象须要照明持有对象不再须要照明开释对象关灯销毁对象2 手动治理内存 MRR手动治理内存,即MRR(manual retain-release),是基于援用计数来实现的,通过本人跟踪对象来明确治理内存。它与ARC之间的惟一区别是:在MRR中,对象的保留和开释都是由咱们手动解决,而在ARC中是主动解决的。 2.1 MRR内存治理的根本准则为了不便了解,咱们先通过一个例子看下MRR中的内存治理是如何工作的,之后会有总结。 首先关上Xcode,创立一个新的我的项目(File\New\Project...),在这里咱们将项目名称写为MemoryManagementDemo。为了确保咱们的代码是在MRR环境下,在进行任何操作之前,咱们须要先查看以后我的项目是否启用了ARC,如果是,将它敞开,如下图所示: 咱们来总结一下手动治理内存的规定: 以alloc、new、copy或mutableCopy结尾的办法创立的对象,咱们领有该对象,应用实现后须要调用release或autorelease开释。在init办法中为了获取对象的所有权,或者在某些状况下防止对象被移除,能够应用retain保留对象。在应用完对象后,须要应用release进行开释。对应用了retain、copy、mutableCopy、alloc或new办法的任何对象,以及具备retain和copy个性的属性进行开释,须要重写dealloc办法,使得在对象被开释的时候可能开释这些实例变量。给对象发送release音讯并不一定立刻销毁这个对象,只有当对象的援用计数减至0时,对象才会被销毁,而后零碎会发送dealloc音讯给这个对象用于开释它的内存。如果在办法中不再须要用到某个对象,但须要将其返回,能够给该对象发送autorelease音讯用以标记提早开释,对象的援用计数会在以后主动开释池的开端减1。当应用程序终止时,内存中的所有对象都会被开释,不管它们是否在主动开释池中。当不再须要一个对象时,必须放弃所领有的该对象的所有权。不能放弃一个你所不领有的对象的所有权。2.2 主动开释池(autorelease pool)下面有说到主动开释,在这里咱们简略介绍下主动开释池。 主动开释池创立的目标就是心愿能够帮忙追踪须要提早一些工夫开释的对象。 通过给对象发送autorelease音讯,就能够将一个对象增加到由主动开释池保护的对象列表中: [object autorelease];程序中应用来自Foundation、UIKit、AppKit框架的类时,首先须要创立一个主动开释池,这样来自这些框架的类才会创立并返回主动开释的对象,须要在程序中应用@autoreleasepool指令(个别在我的项目中的main.m文件中就会看到该语句): @autoreleasepool { statements}当执行到autorelease块的开端时,零碎就会对池中的每个对象发送release音讯,这将影响到所有发送过autorelease音讯并被增加到主动开释池中的对象,当这些对象的援用计数减至0时,会发送出dealloc音讯,并且它们的内存将会被开释。 须要留神的是,主动开释池并不蕴含理论的对象,只是蕴含对象的援用,对象将在主动开释池清理的时候被开释。在ARC中,主动开释池次要用于升高内存峰值,只是咱们不再须要手动增加autorelease的代码了。 2.3 应用拜访器办法简化内存治理手动治理内存时,在代码中应用retain或release来保留或开释对象难免会出错,为此,咱们能够应用拜访器办法来缩小内存治理中的问题。 通常所说的拜访器(accessor)办法指的是设值办法(setter)和取值办法(getter),又统称为存取方法。设值办法即设置实例变量值的办法,次要目标是将办法参数设为对应的实例变量的值,个别不会返回任何值。取值办法即检索实例变量值的办法,次要目标是获取存储在对象中的实例变量的值,并通过程序返回发送进来,所以取值办法必须返回实例变量的值作为return的参数。 上面咱们持续延用之前的例子,在TableViewController.h文件中为两个实例变量增加设值办法和取值办法: @interface TableViewController : UITableViewController{ NSArray *_titles; NSString *_lastTitleSelected;}- (void)setTitles:(NSArray *)titles;- (NSArray *)titles;- (void)setLastTitleSelected:(NSString *)lastTitleSelected;- (NSString *)lastTitleSelected;@end而后在TableViewController.m文件的底部增加实现办法: #pragma mark - Accessor method- (void)setTitles:(NSArray *)titles{ [titles retain]; [_titles release]; _titles = titles;}- (NSArray *)titles{ return _titles;}- (void)setLastTitleSelected:(NSString *)lastTitleSelected{ [lastTitleSelected retain]; [_lastTitleSelected release]; _lastTitleSelected = lastTitleSelected;}- (NSString *)lastTitleSelected{ return _lastTitleSelected;}下面的getter办法容易了解,它们只返回了实例变量。而在setter办法中,咱们首先应用retain保留新传入的参数变量以减少援用计数,而后应用release开释掉旧的实例变量以缩小援用计数,最初将实例变量的值设置为传入的参数变量。这样,只有设置对象,就能保障在实例变量中存储的对象有正确的援用计数。另外,应用这样的程序设置实例变量,能够避免将实例变量设置为同一对象的状况。还有,如果你仔细观察下面的设值办法,你就会明确咱们在最开始命名实例变量的时候要应用下划线的起因,最次要的是为了防止由实例变量名称和参数变量名称雷同而引起的抵触。 ...

August 11, 2020 · 3 min · jiezi

关于ios:Swift-53的进化语法标准库调试能力大幅提升

概括Swift 从 5.0 的 ABI 稳固到5.1 的模块稳固,Swift 终于不是《Swift 入门到重学》了。本次 WWDC2020,Swift 5.3 正式公布,Swift 仍旧朝着平安、高效、易读的方向继续发力,一直的在改良语法,加强代码的表达能力和易用性。因为 Swift 的模块稳固,SPM 当初也反对了二进制模块的散发,逐步欠缺的社区生态也在一直拓宽 Swift 能够涉足的畛域,而不仅仅是在 Apple 平台之上。 下图展现了 WWDC2020 中 Swift 相干内容的脑图,心愿能够帮忙大家疾速理解。 ( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...   本篇内容来自于阿里巴巴淘系技术部,无线开发工程师星志。 更多精彩内容可关注【淘系技术】公众号。) 语言环境的欠缺和拓展一门欠缺编程语言有三个最根本的因素:语法、规范库、调试能力。语法设计决定了语言的编程范式;规范库决定了语言的根本能力;调试能力决定了开发者的体验和语言的稳定性。苹果在 Swift 的迭代过程中一直的强化这几点,咱们能够来看看 Swift 又失去了哪些晋升。 语法个性Swift 的语法设计外围还是 OOP,然而这不障碍 Swift 的语法在反对 POP 和函数式编程甚至 DSL 失去的强化。Swift 也因为 SDL 个性的退出,开始逐步的适应申明式编程的方向倒退,比方后文提到的 @main 等等。 Multiple trailing closure 这个改良解决了当函数最初几个参数为闭包的状况下,导致的括号嵌套的问题,API 更加简洁也更加具备表白性。SwiftUI 利用这个语言个性,也变得更加简洁易懂。 KeyPath as Function 当初 KeyPath 能够当做函数来应用了。这个语法糖解决的问题当咱们应用相似 map 一样的函数时,只须要取出对应数据模型中的某一个属性,为此咱们不得不写相似 map { $0.property } 的代码,有了这个语法糖,事件就能够简化成了 map(\.property)。 ...

August 11, 2020 · 3 min · jiezi

关于ios:Swift-53的进化语法标准库调试能力大幅提升

概括Swift 从 5.0 的 ABI 稳固到5.1 的模块稳固,Swift 终于不是《Swift 入门到重学》了。本次 WWDC2020,Swift 5.3 正式公布,Swift 仍旧朝着平安、高效、易读的方向继续发力,一直的在改良语法,加强代码的表达能力和易用性。因为 Swift 的模块稳固,SPM 当初也反对了二进制模块的散发,逐步欠缺的社区生态也在一直拓宽 Swift 能够涉足的畛域,而不仅仅是在 Apple 平台之上。 下图展现了 WWDC2020 中 Swift 相干内容的脑图,心愿能够帮忙大家疾速理解。 ( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...   本篇内容来自于阿里巴巴淘系技术部,无线开发工程师星志。 更多精彩内容可关注【淘系技术】公众号。) 语言环境的欠缺和拓展一门欠缺编程语言有三个最根本的因素:语法、规范库、调试能力。语法设计决定了语言的编程范式;规范库决定了语言的根本能力;调试能力决定了开发者的体验和语言的稳定性。苹果在 Swift 的迭代过程中一直的强化这几点,咱们能够来看看 Swift 又失去了哪些晋升。 语法个性Swift 的语法设计外围还是 OOP,然而这不障碍 Swift 的语法在反对 POP 和函数式编程甚至 DSL 失去的强化。Swift 也因为 SDL 个性的退出,开始逐步的适应申明式编程的方向倒退,比方后文提到的 @main 等等。 Multiple trailing closure 这个改良解决了当函数最初几个参数为闭包的状况下,导致的括号嵌套的问题,API 更加简洁也更加具备表白性。SwiftUI 利用这个语言个性,也变得更加简洁易懂。 KeyPath as Function 当初 KeyPath 能够当做函数来应用了。这个语法糖解决的问题当咱们应用相似 map 一样的函数时,只须要取出对应数据模型中的某一个属性,为此咱们不得不写相似 map { $0.property } 的代码,有了这个语法糖,事件就能够简化成了 map(\.property)。 ...

August 11, 2020 · 3 min · jiezi

关于ios:Core-ImageiOS图像处理技术追踪

简介Core Image是苹果官网提供的图像处理框架,通过丰盛的built-in(内置)或自定义Filter(过滤器)高效解决动态图片、动静图片或视频。开发者还能够通过结构Filter链或自定义Core Image Kernel来实现更丰盛的成果。 在WWDC20中,苹果官网针对Core Image技术在以下三方面做了优化:Core Image对视频/动图的反对、基于Metal构建Core Image (CI) Kernel以及Core Image的Debug反对。这三方面会在下文逐个提到,文末笔者也会浅谈Core Image在手淘图片库中的利用可能以及对Core Image技术的瞻望。 ( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...   本篇内容来自于阿里巴巴淘系技术部,无线开发工程师越伯。 更多精彩内容可关注【淘系技术】公众号。) 优化Core Image对视频/动图的反对1. 创立CIContext创立CIContext时,须要遵循一个view一个context的准则。因为视频的每一帧都会发生变化,将CIContext的cacheIntermediates属性设置为false能够大大减少内存耗费。 如果在应用Core Image时将同时使用Metal(作为输出或输入),通过设置MTLCommandQueue属性创立CIContext将会是较好抉择。在不应用MTLCommandQueue的状况下,每一个Metal或CoreImage执行的工作都在不同队列中并以wait命令分隔开,导致工作执行效率低。通过设置MTLCommandQueue创立的CIContext和相应的Metal工作在同一队列中,能进步app的运行效率。 图一、不应用MTLCommandQueue的工作流程 图二、应用MTLCommandQueue的工作流程 2. 编写Core Image Kernel(在Metal中实现)为了将成果解决得更丰盛,通过Metal来实现自定义CI Kernel是个高效的抉择。苹果官网提供了的许多不便部署的内置工具(都通过Metal实现),如内置CI滤镜。通过Metal实现自定义CI Kernel,不仅app的runtime编译工夫将会大大减少(这段工作会移至app构建实现后进行),开发者还能取得高性能语言个性(如gather-reads、group-writes、半精度浮点数)、高效开发体验(如缩进查看、缩进高光)等性能。 3. 抉择适合的View类如果要对视频/动图利用特效,动态内容View如UIImageView或NSImageView该当被防止。AVPlayerView和MetalKit View(MTKView)是个两个不错的抉择。前者为简略抉择,后者为进阶抉择。 应用AVPlayerView时,须要创立AVMutableVideoComposition对象,CI滤镜在block中执行图像处理工作。在进行断点debug时,通过点击CIImage对象地址右侧的眼睛图示能够浏览CI滤镜解决流程的详细信息。官网提供的案例中,Core Image还将10位的HDR视频帧数据主动从HLG转化成了Core Image working space。 图三、CI Image断点测试中展示的解决流程 应用MTKView时,开发者须要以frame和device作为参数重载init办法。VIew对应的CIContext也将在init函数中被创立。如果咱们在macOS中开发反对HDR的view,color-Pixel-Format属性须要被设定为rgba16Float,wants-Extended-Dynamic-Range-Content属性须要被设定为true。设定完init办法后,开发者须要实现draw-in view办法。须要留神的是,此处并未间接将Metal材质传入CIRenderDestination函数,而是创立了一个会返回texture的block。这使得CIContext能在后面的帧尚未实现时将Metal工作入队。之后该办法会执行渲染工作(至指定目的地)并创立command buffer将以后绘制后果渲染至view。 自己也亲自尝试了通过Core Image解决视频的整个流程。以下案例应用CIVortexDistortion滤镜对视频进行逐帧解决并渲染,展现内容蕴含外围代码、原视频、CI滤镜解决后视频以及断点测试的滤镜逐帧解决图示。 代码一、测试外围代码 断点调试时Core Image对每帧的解决流程 基于Metal构建Core Image Kernel应用CI Kernel有诸多劣势,包含上文提及的缩短runtime编译工夫、高性能语言个性(如gather-reads、group-writes、半精度浮点数)、高效开发体验(如缩进查看、缩进高光)。基于Metal构建CI Kernel有5步流程,会在下文进行逐个介绍。 1. 在我的项目中减少自定义构建规定苹果官网举荐在我的项目target中减少两项自定义构建规定。第一个构建规定针对以“.ci.metal”为后缀名的文件。该构建规定会创立一个以“.ci.air”为后缀名的二进制输入文件。 图五、针对“*.ci.metal”文件的构建规定 第二个构建规定针对以“.ci.air”为后缀名的文件(上一个构建规定的输入后果)。该构建规定会在app的资源文件夹内创立以“.ci.metallib”为后缀名的输入文件。 ...

August 10, 2020 · 1 min · jiezi

关于ios:基于系统派生类自定义KVO

作为 iOSer,想必大家对 KVO 并不生疏,其原理概括起来大抵3个步骤: 创立派生子类 NSKVONotifying_Person批改被察看对象 p 的 isa 指针,使其指向新类 NSKVONotifying_Person重写 setter 办法,赋值并且告诉观察者 observer 对象 p 的属性值产生了扭转 然而,零碎的 KVO 着实不好用,察看多个属性时,须要在 observeValueForKeyPath:ofObject:change:context: 中写上大量的判断条件,于是,基于以上的KVO实现原理咱们能够自定义KVO实现。 那么,如何自定义KVO? 基于自定义派生类的KVO零碎办法的派生类 NSKVONotifying_Person,咱们绕过这个零碎派生类,自定义一个派生类,比方叫做 CustomKVO_Person,应用其替换 NSKVONotifying_Person。 这种形式在自定义的办法中是可行的,然而一旦和零碎的 addObserver:forKeyPath:options:context: 一起应用就会crash; 其解决方案也是有的,在 iOS大解密:玄之又玄的KVO 一文中,给出的解决方案是: 给自定义派生类调配 0x68 空间,拷贝零碎派生类的 indexedIvars 到此空间,保障 setter 时 _NSSetIntValueAndNotify 能正确获取KVO信息,防止其crash;借助 FishHook 来 hook 零碎的 object_setClass 操作,判断 isa 指针为自定义派生类且继承于零碎派生类时跳过 setClass 操作,这样一来,即便调用零碎办法也能保障 isa 指针指向自定义派生类,防止自定义KVO生效;以上两步联合就能够解决自定义派生类KVO与零碎办法混用导致的问题了。 然而,如果仅是自定义一个KVO就要引入 FishHook 的话,这感觉可不太好;那么有没有不必引入任何框架,也能实现KVO并且不与零碎抵触的办法呢? 上面,咱们来看看另一种思路 基于零碎派生类自定义的KVO这种思路不须要创立自定义的派生类,代码实现上与自定义派生类KVO大同小异,先调用零碎办法生成零碎派生类,再批改零碎派生类的setter办法IMP,调用咱们自定义的block回调。 代码实现如下: #import "NSObject+EasyKVO.h"#import <objc/message.h>#import "MRCEasyKVOTools.h"typedef void(^_EasyKVOChangedBlock)(id newValue, id oldValue);static NSString * __EasyKVOTipsDic = @"__EasyKVOTipsDic";@implementation NSObject (EasyKVO)#pragma mark - public- (void)addObserver:(NSObject*)observer forKeyPath:(NSString *)keyPath changedBlock:(_EasyKVOChangedBlock)block{ if (!observer || keyPath.length < 1) return; /* 应用零碎办法取得派生类 */ if (![NSStringFromClass(object_getClass(self)) containsString:@"NSKVONotifying_"]) { [self addObserver:observer forKeyPath:keyPath options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil]; } NSString *pairClsName = NSStringFromClass(object_getClass(self)); Class pairCls = NSClassFromString(pairClsName); if (!pairCls) { pairCls = objc_allocateClassPair(object_getClass(self), pairClsName.UTF8String, 0x68); [MRCEasyKVOTools object_copyIndexedIvars:object_getClass(self) toTarget:pairCls size:0x68]; objc_registerClassPair(pairCls); object_setClass(self, pairCls); /* 批改 isa 指针 */ } /* 保留 block 信息 */ [_tipsMap(self, _cmd) setObject:[block copy] forKey:[NSString stringWithFormat:@"_%@_%@_block", NSStringFromClass(object_getClass(self)), keyPath]]; /* 扭转setter办法 */ NSString *format = [keyPath stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[[keyPath substringToIndex:1] uppercaseString]]; SEL setSel = NSSelectorFromString([NSString stringWithFormat:@"set%@:", format]); Method setMethod = class_getInstanceMethod(object_getClass(self), setSel); if (![self _containSelector:setSel]) { /* 避免增加屡次 */ class_addMethod(object_getClass(self), setSel, (IMP)_setterFunction, method_getTypeEncoding(setMethod)); } else { class_replaceMethod(object_getClass(self), setSel, (IMP)_setterFunction, method_getTypeEncoding(setMethod)); }}- (void)removeObserver:(NSObject *)observer blockForKeyPath:(NSString *)keyPath { [self removeObserver:observer forKeyPath:keyPath]; NSString *blockKeyName = [NSString stringWithFormat:@"_%@_%@_block", @"NSKVONotifying_", keyPath]; NSMutableDictionary *tips = _tipsMap(self, _cmd); [tips removeObjectForKey:blockKeyName];}#pragma mark - privatevoid _setterFunction(id self, SEL _cmd, id newValue) { NSString *setterName = NSStringFromSelector(_cmd); if (setterName.length < 4) return; NSString *format = [setterName substringWithRange:NSMakeRange(3, setterName.length -4)]; NSString *keyPath = [format stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[[format substringToIndex:1] lowercaseString]]; if (keyPath.length < 1) return; id oldValue = [self valueForKeyPath:keyPath]; if (![oldValue isEqual:newValue]) { //调用父类setter struct objc_super supercls = { .receiver = self, .super_class = class_getSuperclass(object_getClass(self)) }; void (* msgSendSuper)(void *, SEL, id) = (void *)objc_msgSendSuper; msgSendSuper(&supercls, _cmd, newValue); } _EasyKVOChangedBlock block = (_EasyKVOChangedBlock)[_tipsMap(self, _cmd) objectForKey:[NSString stringWithFormat:@"_%@_%@_block", NSStringFromClass(object_getClass(self)), keyPath]]; if (block) block(newValue, oldValue);}NSMutableDictionary *_tipsMap(id self, SEL _cmd) { NSMutableDictionary * _tipsDic = objc_getAssociatedObject(self, &__EasyKVOTipsDic); if (!_tipsDic) { _tipsDic = [[NSMutableDictionary alloc] init]; objc_setAssociatedObject(self, &__EasyKVOTipsDic, _tipsDic, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return _tipsDic;}- (BOOL)_containSelector:(SEL)selector { Class cls = object_getClass(self); unsigned int count = 0; Method *methods = class_copyMethodList(cls, &count); for (int i=0; i<count; i++) { SEL sel = method_getName(methods[i]); if (selector == sel) { free(methods); return YES; } } free(methods); return NO;}@end其中 MRCEasyKVOTools 用到了 MRC 环境下的 API: ...

August 10, 2020 · 2 min · jiezi

关于ios:txt-小说阅读器指南-功能开发的-5-个老套路

本文介绍本地 .txt 小说阅读器性能开发的 5 个相干技术点。 网络 .txt 小说开发,则多了下载和缓存两步 一本书有什么,即书的数据结构一本书有书名,有注释,有目录 手机书架上的书很多,需给书调配一个 id,去除反复 小说用户的常见操作有两种,以后浏览进度记录和书签列表 小说的次要模型 ReadModel书的两个天然属性: ID 和目录 ( 一本书有书名,这里与 ID 合并 ) 书的两个用户操作属性,浏览记录和书签 class ReadModel: NSObject,NSCoding { /// 小说ID, 书名 let bookID:String /// 目录, 章节列表 // 书的注释,依照章节拆分,保留在 ChapterBriefModel 关联的 ReadChapterModel 中 var chapterListModels = [ChapterBriefModel]() /// 以后浏览记录 var recordModel:ReadRecordModel? /// 书签列表 var markModels = [ReadMarkModel]() }小说的目录模型 ChapterBriefModelclass ChapterBriefModel{ /// 章节ID var id: Int! /// 小说ID var bookID:String! /// 章节名称 var name:String!}有了目录,要浏览,须要注释 ...

August 9, 2020 · 10 min · jiezi

关于ios:ios-学习之基础-UI-组件-一

开始你认为学完 swift 之后就能够开发 App 啦?还早呢,UI 组件学一学吧 ???? UILabel // 应用代码增加 UILabel 横向为 X ,纵向为 Y,坐标原点在左上角 let label = UILabel(frame: CGRect(x: 20, y: 40, width: 200, height: 30)) label.text = "Hello World" // 增加到以后视图 self.view.addSubview(label) let label2 = UILabel(frame: CGRect(x: 20, y: 60, width: 200, height: 30)) label2.text = "Geer" // 设置字体为 20 号加粗的零碎字体 label2.font = UIFont.boldSystemFont(ofSize: 20) // 设置字体色彩为红色 label2.textColor = UIColor.red // 设置暗影色彩 label2.shadowColor = UIColor.green // 设置暗影偏移 label2.shadowOffset = CGSize(width: 2, height: 2) // 设置字体对其 label2.textAlignment = NSTextAlignment.center self.view.addSubview(label2) // 多行文本 let text = """ 除了自定义连贯表的表名,你还能够通过传递额定的参数到 belongsToMany 办法来定义该表中字段的键名。第三个参数是定义此关联的模型在连贯表里的外键名,第四个参数是另一个模型在连贯表里的外键名: """ let label3 = UILabel(frame: CGRect(x: 20, y: 80, width: 200, height: 150)) label3.text = text // 设置显示行数 label3.numberOfLines = 7 self.view.addSubview(label3)UIButton // 创立 button 实例,指定 button 的类型 let button = UIButton(type: .system) // 设置地位与尺寸 button.frame = CGRect(x: 20, y: 40, width: 100, height: 30) // 设置按钮背景色彩 button.backgroundColor = .purple // 设置按钮题目 button.setTitle("我是按钮", for: UIControl.State()) // 设置题目背景色彩 button.setTitleColor(.white, for: UIControl.State()) // 为按钮增加事件 // 第一个传入触发事件时事件办法的执行者,比方以后则是 self // 第二个参数传入一个#selector选择器实例,这个参数决定要执行的办法 // 第三个参数设置触发的条件,列入按钮被按下,按钮被按下并抬起 button.addTarget(self, action: #selector(touchBegin), for: UIControl.Event.touchUpInside) self.view.addSubview(button)@objc func touchBegin(){ print("click button") }UIImageView // 创立图片实例 let image = UIImage(named: "img1") // 创立图片 View let imageView = UIImageView(image: image) // 设置 view 的地位 imageView.frame = CGRect(x: 40, y: 50, width: 200, height: 200) self.view.addSubview(imageView) // 动画 var imageArray = Array<UIImage>() for index in 1...2 { if let fImage = UIImage(named: "f\(index)") { imageArray.append(fImage) } } // 创立 View let fImageView = UIImageView(frame: CGRect(x: 30, y: 250, width: 200, height: 100)) // 设置动画数组 fImageView.animationImages = imageArray // 设置播放时长 fImageView.animationDuration = 3 // 设置动画播放次数 fImageView.animationRepeatCount = 0 self.view.addSubview(fImageView) // 开始播放 fImageView.startAnimating()UITextField // 创立实例 设置尺寸 let textField = UITextField(frame: CGRect(x: 20, y: 30, width: 100, height: 30)) // 设置边框输出格调 textField.borderStyle = .line // 设置文字色彩 textField.textColor = .red // 设置对齐形式 textField.textAlignment = .center // 设置提醒文字 textField.placeholder = "请输出姓名" // 设置代理为自身 textField.delegate = self self.view.addSubview(textField) let textField2 = UITextField(frame: CGRect(x: 20, y: 90, width: 100, height: 30)) // 设置边框输出格调 textField2.borderStyle = .line // 设置文字色彩 textField2.textColor = .red // 设置对齐形式 textField2.textAlignment = .center // 设置提醒文字 textField2.placeholder = "请输出姓名" // 左视图 let imageView1 = UIImageView(image: UIImage(named: "img1")) imageView1.frame = CGRect(x: 0, y: 0, width: 30, height: 30) // 右视图 let imageView2 = UIImageView(image: UIImage(named: "f1")) imageView2.frame = CGRect(x: 0, y: 0, width: 30, height: 30) // 设置左右视图 textField2.leftView = imageView1 textField2.rightView = imageView2 // 设置视图模式 textField2.leftViewMode = .always textField2.rightViewMode = .always self.view.addSubview(textField2)代理办法// 在输入框行将进入编辑状态时调用 func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { print("行将进入编辑状态时调用") return true } // 曾经开始编辑时调用 func textFieldDidBeginEditing(_ textField: UITextField) { print("曾经开始编辑时调用") } // 按 return 时调用 func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true }UISwitch let swi = UISwitch() swi.frame = CGRect(x: 20, y: 20, width: 100, height: 20) // 设置视图中心点的坐标 swi.center = CGPoint(x: 100, y: 100) // 设置开启状态的色彩 swi.onTintColor = .green // 设置一般状态的色彩 swi.tintColor = .red // 设置滑动的色彩 swi.thumbTintColor = .purple // 设置开关的初始状态 swi.isOn = true swi.addTarget(self, action: #selector(switchChange), for: UIControl.Event.valueChanged) self.view.addSubview(swi)@objc func switchChange(swi: UISwitch){ print(swi.isOn) }UIPageController // 创立 let pageControl = UIPageControl(frame: CGRect(x: 20, y: 100, width: 280, height: 30)) // 设置页数 pageControl.numberOfPages = 10 // 设置背景色彩 pageControl.backgroundColor = .red // 设置页码点背景色彩 pageControl.pageIndicatorTintColor = .green // 设置选中的页码点色彩 pageControl.currentPageIndicatorTintColor = .blue // 设置以后选中的页数 pageControl.currentPage = 3 pageControl.addTarget(self, action: #selector(uiPageChange), for: UIControl.Event.valueChanged) self.view.addSubview(pageControl) @objc func uiPageChange(pageControl: UIPageControl){ print("以后 \(pageControl.currentPage)") }UISegmentedControl let items = ["按钮1","按钮2","按钮三"] let segmentedControl = UISegmentedControl(items: items) // 设置地位与尺寸 segmentedControl.frame = CGRect(x: 100, y: 100, width: 200, height: 30) // 设置控件格调与色彩 segmentedControl.tintColor = .blue segmentedControl.addTarget(self, action: #selector(segmentedControlChange), for: UIControl.Event.valueChanged) self.view.addSubview(segmentedControl)@objc func segmentedControlChange(seg: UISegmentedControl){ print("抉择了 \(seg.selectedSegmentIndex)") // 插入新的按钮 seg.insertSegment(withTitle: "按钮5", at: 0, animated: true) }UISlider let slider = UISlider(frame: CGRect(x: 20, y: 100, width: 280, height: 30)) // 设置最小值 slider.minimumValue = 0 slider.maximumValue = 10 // 初始滑块的值 slider.value = 5 // 设置滑块左侧进度条的色彩 slider.minimumTrackTintColor = .red // 设置滑块右侧的色彩 slider.maximumTrackTintColor = .green // 设置滑块的色彩 slider.thumbTintColor = .blue // 设置进行滑动才触发事件 slider.isContinuous = false slider.addTarget(self, action: #selector(uISliderChange), for: UIControl.Event.valueChanged) self.view.addSubview(slider)@objc func uISliderChange(slider: UISlider){ print(slider.value) }UIActivityIndicatorView let activity = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium) activity.center = self.view.center activity.color = .blue // 开始播放 activity.startAnimating() self.view.addSubview(activity)UIProgressView let progressView = UIProgressView(progressViewStyle: UIProgressView.Style.default) // 设置地位和宽度 progressView.frame = CGRect(x: 20, y: 100, width: 280, height: 30) // 设置以后进度 progressView.progress = 0.5 // 设置已走过的进度条进度 progressView.progressTintColor = .red // 设置未走过的色彩 progressView.trackTintColor = .blue self.view.addSubview(progressView)UIStepper let steper = UIStepper(frame: CGRect(x: 100, y: 100, width: 0, height: 0)) // 设置背景色彩 steper.backgroundColor = UIColor.red // 设置控件色彩 steper.tintColor = .blue // 设置最小值 steper.minimumValue = 0 steper.maximumValue = 10 // 设置控件的步长 steper.stepValue = 1 self.view.addSubview(steper)UIPickerView let pickerView = UIPickerView(frame: CGRect(x: 20, y: 100, width: 280, height: 200)) // 设置代理 须要增加 UIPickerViewDelegate pickerView.delegate = self // 设置数据源 须要增加 UIPickerViewDataSource pickerView.dataSource = self self.view.addSubview(pickerView)代理 // pickView 此办法须要选择器控件的分组数量 func numberOfComponents(in pickerView: UIPickerView) -> Int { return 2 } // 此办法须要返回每个分组的行数 func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return 10 } // 此办法返回每个分组中的每行数据的题目 func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return "第\(component + 1)组第\(row)行" } func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { print("用户抉择了 \(component)组\(row)行") }UIDataPicker let dataPicker = UIDatePicker(frame: CGRect(x: 20, y: 100, width: 280, height: 200)) // 设置工夫选择器的模式 dataPicker.datePickerMode = .dateAndTime dataPicker.addTarget(self, action: #selector(uiDataPickerChange), for: UIControl.Event.valueChanged) self.view.addSubview(dataPicker)@objc func uiDataPickerChange(dataPicker: UIDatePicker){ print(dataPicker.date) }UISearchBarlet searchBar = UISearchBar(frame: CGRect(x: 20, y: 100, width: 280, height: 30)) // 设置控件的格调 searchBar.searchBarStyle = .minimal searchBar.placeholder = "请输出商品题目" // 显示勾销按钮 searchBar.showsCancelButton = true // 显示控件的书库按钮 searchBar.showsBookmarkButton = true self.view.addSubview(searchBar)完结今日先学这么多,今天再持续 ...

August 7, 2020 · 5 min · jiezi

关于ios:iOS-分辨率-屏幕快照规范

截图 / Default设施尺寸分辨率设计分辨率倍率iPhoneXSMax6.52688x1242896x4143iPhoneXR5.8179~~~~2x828896x4142iPhoneX/XS5.82436x1125812x3753iPhone6Plus/7Plus/8Plus5.52208x1242736x4143iPhone6/7/84.71334x750667x3752iPhone5/SE41136x640568x3602iPhone4/4s3.5960x600480x3602iPad sd7.5/9.71024x7481024x7481iPad hd7.5/9.72048x15361024x7482iPad Pro10.52224x16681112x8342iPad Pro112388x16681112x8342iPad Pro12.12732x20481366x10242Mac16:101280x800----1440x900----2560x1600----2880x1800--tvOS16:91920x1080----3840x2160--iWatch142mm390x312-iWatch138mm340x272-iWatch440mm394x324-iWatch444mm448x368-参考:https://help.apple.com/itunes-connect/developer/#/devd274dd925 预览视频规格设施要求预览<500MB, H.264 格局, 30 帧/秒, .mov、.m4v、.mp4, 15s-30siPhoneX886x1920, 1920x886iPhone6/7/8750x1334, 1334x750iPhone6Plus/7Plus/8Plus1080x1920, 1920x1080iPhone51080x1920, 1920x1080iPad900x1200, 1200x900iPad Pro101200x1600, 1600x1200iPad Pro121200x1600, 1600x1200, 900x1200, 1200x900Mac/TV1920x1080

August 3, 2020 · 1 min · jiezi

关于ios:避风头库克表示安卓才是全球手机第一大操作系统垄断跟-iOS-没关系

技术编辑:徐九丨发自:思否编辑部 美东工夫周三,美国众议院司法委员会召开了数字市场竞争问题举办的听证会,美国 4 家最大科技公司首席执行官以视频形式加入并对相干问题承受质询。包含 Facebook 的马克·扎克伯格、亚马逊的杰夫·贝佐斯、苹果的蒂姆·库克以及谷歌的桑德尔·皮查伊等 4 人与委员会成员就每家公司正在面临的反垄断问题开展集中探讨。 在会议中,蒂姆·库克示意苹果公司不是个垄断企业。激发和倒退了宏大的挪动软件市场,这是苹果公司的功绩。iPhone 通过硬件和软件的无缝集成、毫不费力的用户体验、简洁的设计和高质量的生态系统,从新定义了手机。但 iPhone 在智能手机中不占主导地位,智能手机市场竞争强烈,三星、LG、华为和谷歌等公司曾经建设了十分胜利的智能手机业务,提供了不同的办法。 库克示意,在事实上,谷歌领有占据寰球主导地位的操作系统,也就是 Android。所以在苹果看来,安卓才是寰球手机第一大操作系统,所以论垄断也基本跟 iOS 没关系。 但苹果公司的确在多个重要畛域中占据着主导地位。比方在高端的手机市场和利用商店畛域。近期一直有声音冒出,批评苹果“迫使”开发者恪守其公司的规定,并始终强占开发者的局部权利,对不同开发者采取不同的态度。 在众议院听证会上,库克否定苹果公司对其平台上的局部开发者采取了不同的态度,并示意对此不知情。对于苹果会从自家领取零碎中收集客户数据,要求所有在该平台上收款的开发者应用这一领取零碎这一指控,库克没有否定但也没有间接答复这个问题。库克还否定苹果会对开发者进行报复。

July 30, 2020 · 1 min · jiezi

关于ios:runtime-获取对象属性字典

#import "NSObject+object_runtime.h"#import <objc/runtime.h>@implementation NSObject (object_runtime)/** 获取对象的属性和属性值字典 */- (NSDictionary*)objectGetPropertyKeysValues{ NSMutableDictionary* dic = [NSMutableDictionary dictionary]; unsigned int count; objc_property_t * prop_list = class_copyPropertyList([self class], &count); for (int i=0; i<count; i++) { objc_property_t prop = prop_list[i]; const char * prop_name = property_getName(prop); NSString* propName = [NSString stringWithUTF8String:prop_name]; id propVal = [self valueForKey:propName]; if (propVal) { [dic setObject:propVal forKey:propName]; } else { [dic setObject:[NSNull null] forKey:propName]; } } free(prop_list); return dic;} /** 获取类的属性列表 */+ (NSArray*)classGetPropertyList{ unsigned int count; objc_property_t * prop_list = class_copyPropertyList([self class], &count); NSMutableArray * propsArr = [NSMutableArray arrayWithCapacity:count]; for (int i=0; i<count; i++) { objc_property_t prop = prop_list[i]; const char * prop_name = property_getName(prop); NSString* propName = [NSString stringWithUTF8String:prop_name]; [propsArr addObject:propName]; } free(prop_list); return propsArr;}/** 获取类的办法列表 */+ (NSArray*)classGetMethodList{ unsigned int count; Method * method_list = class_copyMethodList([self class], &count); NSMutableArray * array = [NSMutableArray arrayWithCapacity:count]; for (int i = 0; i<count; i++) { Method m = method_list[i]; const char * name = sel_getName(method_getName(m)); //IMP imp = method_getImplementation(m); //int args = method_getNumberOfArguments(m); //const char * encoding = method_getTypeEncoding(m); [array addObject:[NSString stringWithUTF8String:name]]; } free(method_list); return array;}@end

July 27, 2020 · 1 min · jiezi

关于ios:iOS深入理解RunLoop

转载阐明:本文为转载,这是一篇对于RunLoop的高质量文章,然而原文博客链接太慢,故而我搬迁到此处,原文是深刻了解RunLoop,作者是ibiremeRunLoop 是 iOS 和 OSX 开发中十分根底的一个概念,这篇文章将从 CFRunLoop 的源码动手,介绍 RunLoop 的概念以及底层实现原理。之后会介绍一下在 iOS 中,苹果是如何利用 RunLoop 实现主动开释池、提早回调、触摸事件、屏幕刷新等性能的。 RunLoop 的概念一般来讲,一个线程一次只能执行一个工作,执行实现后线程就会退出。如果咱们须要一个机制,让线程能随时处理事件但并不退出,通常的代码逻辑是这样的: function loop() { initialize(); do { var message = get_next_message(); process_message(message); } while (message != quit);}这种模型通常被称作 Event Loop。 Event Loop 在很多零碎和框架里都有实现,比方 Node.js 的事件处理,比方 Windows 程序的音讯循环,再比方 OSX/iOS 里的 RunLoop。实现这种模型的关键点在于:如何治理事件/音讯,如何让线程在没有解决音讯时休眠以防止资源占用、在有音讯到来时立即被唤醒。 所以,RunLoop 实际上就是一个对象,这个对象治理了其须要解决的事件和音讯,并提供了一个入口函数来执行下面 Event Loop 的逻辑。线程执行了这个函数后,就会始终处于这个函数外部 “承受音讯->期待->解决” 的循环中,直到这个循环完结(比方传入 quit 的音讯),函数返回。 OSX/iOS 零碎中,提供了两个这样的对象:NSRunLoop 和 CFRunLoopRef。CFRunLoopRef :在 CoreFoundation 框架内的,它提供了纯 C 函数的 API,所有这些 API 都是线程平安的。NSRunLoop :基于 CFRunLoopRef 的封装,提供了面向对象的 API,然而这些 API 不是线程平安的。 ...

July 27, 2020 · 10 min · jiezi

关于ios:iOS状态栏字体颜色设置

2019.12.04 17:26 info.plist 属性View controller-based status bar appearance, 也就是UIViewControllerBasedStatusBarAppearance, 官网文档阐明如下: A Boolean value indicating whether the status bar appearance is based on the style preferred for the current view controller.一个布尔值,批示状态栏外观是否基于以后视图控制器的首选款式。 状态栏字体色彩View controller-based status bar appearance设置为 YES 时, NO 状态对应设置有效; 反之亦然. 办法一: preferredStatusBarStyleView controller-based status bar appearance 设置为 YES, 应用 - [UIViewController preferredStatusBarStyle] 批改状态栏字体色. 实用于iOS7.0+, 举荐. // MyViewController.m- (UIStatusBarStyle)preferredStatusBarStyle { // 红色 //return UIStatusBarStyleLightContent; // 彩色 if (@available(iOS 13.0, *)) { return UIStatusBarStyleDarkContent; } else { return UIStatusBarStyleDefault; //彩色, 默认值 }}- (BOOL)prefersStatusBarHidden { return YES; //状态栏暗藏 //return NO; //状态栏显示, 默认值}留神: ...

July 27, 2020 · 2 min · jiezi

关于ios:iOS自定义返回按钮

2019/01/09 17:02 在父视图中批改1、应用 backBarButtonItem 实现,返回按钮紧贴屏幕右边,有返回手势。 这种办法须要将图片设置成 UIImageRenderingModeAlwaysOriginal 模式能力正确显示,否则图片会被渲染成蓝色。 - (void)viewDidLoad { [super viewDidLoad]; UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]; self.navigationController.navigationBar.backIndicatorImage = [[UIImage imageNamed:@"btn_back_black"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; self.navigationController.navigationBar.backIndicatorTransitionMaskImage = [[UIImage imageNamed:@"btn_back_black"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; self.navigationItem.backBarButtonItem = backItem;}2、应用 leftBarButtonItem 实现,返回按钮与屏幕左边缘有一小段距离(大略为8),有返回手势。 #import "BaseViewController.h"@interface BaseViewController ()@property (nonatomic, strong) UIBarButtonItem *backButtonItem;@end@implementation BaseViewController- (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.hidesBackButton = YES; if (self.navigationController.viewControllers.count > 1) { [self backButtonItemImageNamed:@"btn_back_black" target:self action:@selector(backButtonItemClicked:)]; }}- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; //解决根试图右边滑动手势页面卡死问题 if (self.navigationController.viewControllers.count == 1) { self.navigationController.interactivePopGestureRecognizer.enabled = NO; } else { self.navigationController.interactivePopGestureRecognizer.enabled = YES; }}- (void)backButtonItemImageNamed:(NSString*)imgName target:(id)target action:(SEL)selector { UIImage* backImg = [[UIImage imageNamed:imgName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; UIBarButtonItem* item = [[UIBarButtonItem alloc] initWithImage:backImg style:UIBarButtonItemStylePlain target:target action:selector]; self.backButtonItem = item; self.navigationItem.leftBarButtonItem = self.backButtonItem; //启用返回手势,须要解决卡死问题 self.navigationController.interactivePopGestureRecognizer.delegate = nil;}- (void)backButtonItemClicked:(UIButton *)sender { [self.navigationController popViewControllerAnimated:YES];}@end在本视图中批改1、批改成只有图片的: ...

July 27, 2020 · 1 min · jiezi

关于ios:iOS-自定义-NavigationController

2019/01/10 16:20 自定义导航栏,反对手势 #import "JINavigationController.h"@interface JINavigationController ()<UINavigationControllerDelegate,UIGestureRecognizerDelegate>@end@implementation JINavigationController+ (void)initialize { //appearance办法返回一个导航栏的外观对象 //批改了这个外观对象,相当于批改了整个我的项目中的外观 UINavigationBar *navigationBar = [UINavigationBar appearance]; //设置导航栏背景色彩 [navigationBar setBarTintColor:[UIColor whiteColor]]; //设置标题栏色彩 navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:[UIColor blackColor], NSFontAttributeName : [UIFont systemFontOfSize:18]}; //设置NavigationBarItem文字的色彩 //[navigationBar setTintColor:[UIColor blackColor]];}- (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wkself = self; self.delegate = wkself;}///MARK: override//全副批改返回按钮,然而会失去右滑返回的手势- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{ if (self.viewControllers.count > 0) { viewController.hidesBottomBarWhenPushed = YES; viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"btn_back_black"] style:UIBarButtonItemStyleDone target:self action:@selector(backClickedAction)]; } //在push一个新的VC时,禁用滑动返回手势 if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.interactivePopGestureRecognizer.enabled = NO; } [super pushViewController:viewController animated:animated];}-(void)backClickedAction { [self popViewControllerAnimated:YES];}///MARK: UINavigationControllerDelegate- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{ //齐全展现出VC时,启用滑动返回手势 if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.interactivePopGestureRecognizer.delegate = self; self.interactivePopGestureRecognizer.enabled = YES; } //解决根试图左滑页面卡死 if (navigationController.viewControllers.count == 1) { navigationController.interactivePopGestureRecognizer.enabled = NO; navigationController.interactivePopGestureRecognizer.delegate = nil; }}///MARK: UIGestureRecognizerDelegate//承受多手势- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{ return YES;}- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{ return [gestureRecognizer isKindOfClass:UIScreenEdgePanGestureRecognizer.class];}@end

July 27, 2020 · 1 min · jiezi