需求场景:通过 WKWebView 加载第三方网页,其中有一个录制人脸视频的功能,为了用户体验需要默认调用前摄像头,然而第三方的网页我们无法调整,只能通过注入 JS 来修改 input 标签,将 capture 属性改成 user 即可调用前摄像头。
网页内容是动态生成的,并不是写死的模板,所以需要监听 body 子节点发生改变的事件,每当 body 内容发生变更时,就去找出调用摄像头的 input 标签,找到之后动态修改它的属性。
当服务器返回的JSON字符串中包含
回车符
等特殊字符时,ajax的解析会报错,导致程序执行异常。
为了解决这个问题,在不侵入任何代码的情况下,只能替换 jQuery ajax 的方法实现了。
将下面的代码复制到公共js的顶部,确保在发送网络请求之前就已经执行了替换操作,这样我们就能自定义解析服务器返回的JSON数据了。
当前环境:macOS 10.14.1 + Charles 4.2.7 + iPhone 7 iOS 12.1
前往 https://www.charlesproxy.com/download/ 下载对应平台的 Charles 软件。
今天产品部的突然说 iOS 版 App 播放不了 GIF,一接到这个反馈信息,我一开始是不相信的,因为之前的旧版也是用的 SDWebImage
这个库且未做任何代码适配就能够播放 GIF,所以我内心是极不愿相信这是我的锅。
新版 App 重构后也上线了两个多月了,这期间由于 App 未涉及到 GIF 的播放,所以一直未发现该问题(
是我工作的疏忽)。
在小程序就要上线之际,突然接到一个需求:只有登录的用户才能转发小程序。
在一接到这个需求的时候,我内心是很拒绝的,一时间也是一脸懵逼态,无从下手。在我痛定思痛之后,发现了一对API wx.showShareMenu
、wx.hideShareMenu
,这对API能够显示/隐藏 当前
页面的转发按钮。
对于 iOS 开发者来说,如果需要对一个类进行扩展,第一反应就是
runtime
+category
,有了这组合,我们简直可以为所欲为,为类添加属性、方法、重写某个方法都不在话下。
我们都知道 UITabBar 只能添加 UITabBarItem,而 UITabBarItem 是继承自 NSObject 的,但是我们可以发现 UITabBarItem 内部有一个 _view
属性与私有类 UITabBarButton
关联着,而这个 UITabBarButton 正是我们在 UITabBar 上看到的一个个按钮对象。
当我们需要用户输入数字时,我们会将键盘类型设置为 UIKeyboardTypeNumberPad
、 UIKeyboardTypePhonePad
或 UIKeyboardTypeDecimalPad
等数字类型的键盘。但是如果用户使用了第三方输入法(比如搜狗),那就无法达到强制输入数字的目的了,因为搜狗输入法在这些 UIKeyboardType 枚举类型中,除了常规的 0~9 数字键外,还额外带了其他符号键,用户可以输入一些特殊字符,此时如果想要达到效果,就只能通过重写遵守 UITextFieldDelegate
并实现 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
方法,在这里通过正则判断用户输入的是否为数字。
今年苹果发布了三款 iPhone,分别为 iPhone XS、iPhone XS Max 以及 iPhone XR,尽管大家都在吐槽刘海屏,但是苹果今年已经是 iPhone 系列标配刘海屏了。
虽然苹果为我们带来了更大屏幕尺寸的 iPhone XS Max 和 iPhone XR,尽管一个是6.5英寸一个是6.1英寸,并且 iPhone XS Max 的分辨率更是达到了 1242px × 2688px,但是对于我们开发者来说,这两者的物理尺寸都一个样,都是 414×896pt
,而 6/7/8 Plus 系列的宽度也是 414pt,所以你可以把他们看作是 plus 系列的加长版。
当点击按钮后,可能会执行一个比较耗时的操作,但是又不方便在整个页面进行提示时,此时如果我们仅仅只是把按钮禁用了以防用户重复点击,但是用户并不知道操作是否还在继续,用户体验不够友好;但是如果我们在按钮被禁用时,自动显示一个转圈圈的小菊花进行提示,那用户体验就会好很多,用户一看就知道当前操作正在进行中。
注意点:
contentView
或 backgroundView
的背景色实现,修改 UITableViewHeaderFooterView 自身背景色无效果tableView:willDisplayHeaderView:forSection:
代理方法中进行设置,在 tableView:didEndDisplayingHeaderView:forSection:
设置无效项目需要对JSON返回的换行符进行解析,系统提供了解析JSON的方法[NSJSONSerialization JSONObjectWithData:options:error:]
,
AFNetworking 内部也是采用该方法来解析服务器返回的内容。所以,我只需要 hook 该系统方法,当解析失败的时候进行处理就行了,这样就可以一劳永逸,也无需修改其他地方的代码。
作为一名 iOS 开发者,肯定知道 NSArray/NSDictionary 不能存储 nil
值,如果你试图往数组/字典中存储 nil,那么 App 也将毫不客气的为你闪退。
尽管在日常的编码中,我们都会小心翼翼的处理 nil,但是总会有纰漏,毕竟大部分数据都是从服务器下发的,我们很难彻底把控。作为一名码农,肯定是想着怎么偷懒的,既能自动规避 nil,又能够不影响现有代码,最好不用引入第三方方法。得益于 Objective-C 的 runtime 机制,我们可以很优雅地通过 Method Swizlling
来解决上述问题。
最近项目重构,所以采用了 WKWebView 来展示网页内容,但是发现在 iOS9 上程序会出现 crash,以前也用过 WKWebView 但是都没遇到这么坑的情况啊。
具体操作:通过 push 网页控制器,然后在 pop 之后,程序就崩了。
打断点也定位不到 crash 代码行,打开 Xcode 的僵尸模式之后,控制台也仅输出以下信息:
相信没有哪款App是没有使用到滚动视图(UIScrollView、UITableView、UICollectionView)的吧,我相信大家用的最多的就是UITableView了,当需要展示列表数据时,我想大家第一次时间想到的就是UITableView。
如果数据不为空的时候还好,可谁也不能保证一定会有数据展示吧,如果没数据的时候,就会给客户呈现一个空白页面(白板),此时我们可以给用户一点提示信息(图片、文字),这不仅可以提升用户体验,也不至于让用户一脸懵逼。
我们经常会遇到这样一种需求,在控制器上有一个关闭按钮,点击来关闭当前页面。而我们通常的做法都是在 Storyboard 上拖一个 UIButton 出来,然后将 UIButton 拖线到控制器上,新建一个 IBAction 方法,并在该方法中通过代码来关闭当前控制器。
其实,我们可以不需要这么麻烦,可以通过 Unwind Segue
在 Storyboard 上拖拖线即可达到关闭控制器的效果。
越来越多人采用Markdown进行写作,而表格作为一种比较常见的需求,Markdown也支持快速创建表格。
语法:
| Name | Score |
| :- | :-: |
| zhangsan | 90 |
在Swift中截取子串,一直是个头疼的问题,毕竟牵涉到String.Index
这个鬼东西,而且API还不好用。现在连substring(to:)
、substring(from:)
、substring(width:)
这几个方法也被废弃了。
相信大家在日常开发中,都离不开web吧,部分页面还是得用网页进行展示。在iOS7和之前我们可以用UIWebView来加载网页,在iOS8 Apple为我们带来了WKWebView(WebKit框架),而在iOS9 Apple为我们提供了进一步的封装库SafariServices。
SafariServices的可定制性很差,可以说毫无定制性可言,我们只能控制一下导航栏和底部工具栏的颜色,以及通过SFSafariViewControllerDelegate可以添加自定的分享功能(UIActivity)。
苹果在iOS10.3系统中为我们带来了更改App图标的功能, 主要接口定义如下:
// Pass `nil` to use the primary application icon. The completion handler will be invoked asynchronously on an arbitrary background queue; be sure to dispatch back to the main queue before doing any further UI work.
前提条件:接收临时会话的QQ号码必须开通QQ推广功能,否则不能打开临时会话窗口。
公司项目在商品详情页面中,有一个客服按钮,点击后需要打开客服MM的QQ聊天窗口,在此可以向客服MM咨询商品相关的问题。这里就记录下iOS如何跳转到QQ的聊天窗口。
最近项目有个需求,需要在UITextView中禁止用户输入回车符,因为后台不会过滤回车符号,所以当AFNetworking请求数据时,如果返回的数据中包含了回车符,那么JSON解析将会失败。既然后台不处理,那没办法,只能在UITextView上禁用回车符了。
我们需要解决以下问题:
最近升级了Xcode9之后,发现Xcode经常性卡顿,菊花常现,已经严重影响到代码的编写了,一开始还以为是Xcode9的问题,后来在网上搜索了下,原来老版本的Xcode就存在这个问题,而且是由于IB_DESIGNABLE
这个系统宏导致的。
当我们在自定义视图的定义前面用了IB_DESIGNABLE
这个宏来修饰,就表明了我们这个视图是可以在SB/XIB中实时预览的,本来这是一个很好用的功能,我们直接修改了视图代码就可以在SB上直接渲染出来,这真是所见即所得,简直棒到没朋友。但是这功能确实也坑了我们一把,当我们在编写代码时,只要修改了源码,哪怕只敲了一个字符,Xcode也会自动重新编译SB文件,这就很尴尬了,当我们不断敲代码的时候,Xcode就不断地重新编译SB文件,最后导致Xcode异常卡顿。
运营推广人员向我们反馈说需要一个能方便拷贝会员手机号码的功能,方便进行其他操作。由于会员信息是采用UITableView来进行展示的,而系统已经为我们准备好了UITableViewCell长按功能菜单的API,我们只需实现对应的代理方法即可。
今天产品经理向我反馈在iOS11上点击保存图片后App闪退了,通过调试发现控制台输出了如下错误信息:
[access] This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryAddUsageDescription key with a string value explaining to the user how the app uses this data.
由于iOS的沙盒机制,导致应用不能访问沙盒目录以外的文件目录。所以如果我们需要将音视频文件拷贝到App上,只能拷贝到App的Documents
目录
如果我们的App需要支持从PC将文件拷贝到App的Documents目录并展示出来,则需要在Info.plist中添加UIFileSharingEnabled
(Application supports iTunes file sharing)键,并将键值设置为YES
。
有时候我们会用表格的头部视图来做一些简单的UI展示,如果遇到高度固定的情况还好,并无任何问题。但是如果遇到高度需要动态调整的时候,那就有点蛋疼了,因为你不能通过直接修改tableHeaderView的frame属性来达到效果。直接修改frame会导致UI有时候正常有时候又不正常,完全把控不了。
如果有多层嵌套的情况下,有时候我们需要在某处直接退出多层循环,在Objective-C下并没有比较好的方式实现;而在Swfit中可以通过标签语句来比较优雅地实现,首先需要使用标签标识不同的循环体,形式如下:
LabelName: while condition {
最近在把玩支付宝
和小米商城
App时发现了个好玩的东西,在支付宝首页中截屏,则会在屏幕右侧弹出一个小窗口来展示首页截屏图片,点击图片就会进入求助反馈页面,再点击意见反馈,截屏的图片就会自动被选上作为反馈图片使用;而小米商城的做法则更好玩,在任意页面中进行截屏,则会在屏幕右下角中弹出一个分享截图给好友
的提示框,点击则会弹出分享页面,在此可以看到我们刚才截取的屏幕图片,接下来你就可以把截屏图片分享给你的微信朋友、QQ好友、发到朋友圈、发微博等等,任君选择。
如果你只想知道代码的正确使用姿势,请直接看文章底部的示例代码。
有时候我们需要在UICollectionView执行了reloadData方法后,监听reloadData的完成状态以便执行某些回调操作。如果我们紧跟着reloadData代码,在其后面继续编写我们的回调操作,这个时候你会发现程序的运行结果与我们的预期有出入,并非是我们所期望的结果。
我们需要在UIScrollView滚动时根据滚动偏移量实时计算当前滚动到第几页,需要实现scrollViewDidScroll(_:)
这个代理方法,记得开启分页功能scrollView.isPagingEnabled = true
func scrollViewDidScroll(_ scrollView: UIScrollView) {
在iOS11中,苹果对UIScrollView新增了
contentInsetAdjustmentBehavior
属性来取代之前的UIViewController的automaticallyAdjustsScrollViewInsets
属性。
调整窗口大小或居中显示,必须将NSWindow的
restorable
属性设置为NO,否则无效果。
应用在关闭时会记住window当前的位置以及frame,在下次启动应用时,系统会将window显示在上次关闭时的位置,并恢复关闭时的frame。有时候我们希望在每次打开应用时,应用都能居中显示,或者是我们需要在应用启动时,指定窗口的frame,则可以在NSWindowController的windowDidLoad方法进行设置:
新建一个macOS应用项目,编译运行后默认出现的界面是如下图所示的样子:
有时候我们需要去掉titleBar,类似QQ登录界面那种,此时我们可以在继承自NSWindowController的自定义类的-windowDidLoad方法中通过下面的代码实现效果:
我们都知道在Playground上能够一边写代码一边预览代码运行效果(所见即所得),如果我们需要在Playground上调试UI,就得借助于PlaygroundSupport系统库了。
1、导入PlaygroundSupport库
import PlaygroundSupport
UITableView在iOS9后新增了一个属性cellLayoutMarginsFollowReadableWidth
,该属性会影响UITableViewCell在iPad下的显示,且该属性默认为YES
。
当你发现在iPad下UITableViewCell不能占满整个UITableView的宽度时,只需将该属性设置为NO即可。
UISwitch大小是不能修改的,iOS7开始,系统将UISwitch大小固定为51x31。
尽管UISwitch不能通过修改frame
的方式修改大小,但是可以通过transform
来进行缩放,变相达到我们想要的效果。
你可以直接将下面的代码粘贴到viewDidLoad
里面。如果你的场景比较复杂,从A控制器push到B控制器时B控制器需要设置导航栏透明,然后从B控制器pop回A控制器时恢复导航栏原有样式,则建议在B控制器中的viewWillAppear:
方法中将导航栏设置成透明,在viewWillDisappear:
中恢复导航栏样式。
虽然说是获取一年后的时间,但是可以通过设置不同的数值,达到获取N年前或N年后的时间的效果。
当数值>0
时,获取之后的时间,如果数值<0
则为获取之前的时间。
NSDate *date = [NSDate date];
最近项目有这么个需求,后台返回一个图片URL,Android通过该URL加载网络图片,同时需要做到点击图片的不同区域,跳转到不同的Activity页面。此时就需要监听View的点击坐标点以及该坐标点所处的区域。
需要注意的是,Android中的
Rect
和iOS中的CGRect
的概念有点不一样,iOS中的CGRect通过CGRectMake(x, y, width, height)
方法进行创建,而Android中的Rect通过public Rect(int left, int top, int right, int bottom)
初始化。iOS中的是x
、y
、width
、height
,对应的是视图的x坐标点
、y坐标点
、视图的宽度值
、视图的高度值
;而Android中的是left
、top
、right
、bottom
对应的是视图的视图左边距坐标点
、视图顶部边距的坐标点
、视图右边距的坐标点
、视图底部边距的坐标点
。Android中的Rect更类似于iOS中的UIEdgeInsets的概念。
最近在自学Python,感谢廖雪峰前辈的Python教程。看了这教程,算是对Python语法有了一点基础,越发地迷上Python,想继续深入学习Python,在网上找了下资料,发现鱼C网站有Python视频教程,更难能可贵的是居然有百度网盘的分享地址,鱼C的教程我并不陌生,之前就看过鱼C出品的汇编语言教程,觉得挺不错的。所以就想着保存一份到自己的网盘上,但是10页数据一共97个视频,难道你还要一个一个点击进入,再点击查看百度网盘的下载地址吗?想想我都觉得要疯了,所以用Python写了这个小脚本,负责抓取所有的百度网盘链接和提取密码,然后调用Mac平台的open命令打开Safari,剩下的事情就简单多了,直接copy提取密码,Command+V然后回车,进去后再保存到自己的网盘。