iOS知识点

[TOC]

016

获取iOS设备uuid, 获取App bundleid

➜  ~ idevice_id -l
a82fecc1d3f1628f85e5055e238d8515f23624da

# 需要安装ideviceinstaller: brew install ideviceinstaller
➜  ~ ideviceinstaller -l
Total: 45 apps
com.tencent.xin - 微信 7.0.4.40
com.wmc-china.MemoryChampionshipsHD - 脑力大师 1.0.8
com.reederapp.iOS - Reeder 4000.39.01
com.xk72.Charles - Charles 95
is.workflow.my.app - 快捷指令 784
com.kapeli.dash.ios - Dash 400
com.sugarmo.ScrollClip - Picsew 2911
com.apple.TestFlight - TestFlight 6
com.netease.mailmasterpro - 网易邮箱大师 1429
com.baidu.map - 百度地图 10.15.0.7
com.moke.Annotable - Annotable 150

015


代码阅读target-action

(lldb) e id $view = (id) 0x7fbd71432590

(lldb) po [$view  allTargets]
{(
    <lldb.ViewController: 0x7feff2d67330>
)}

(lldb) po [$button actionsForTarget:(id)0x7feff2d67330 forControlEvent:0]

014


自动打包遇到的问题

当Team:Personal Team is not enrolled in the Apple Developer Program时,下面的命令导出ipa失败
失败原因${options_plist}所指定的文件中method字段写为了ad-hoc,修改为development就ok了

xcodebuild -exportArchive -archivePath ${archive_path} -exportPath ${ipa_path} -exportOptionsPlist ${options_plist}

上面命令的失败输出:
error: exportArchive: No signing certificate "iOS Distribution" found

Error Domain=IDECodesignResolverErrorDomain 
Code=1 "No signing certificate "iOS Distribution" found" 
UserInfo={
IDEProvisioningError_UserInfoKey_IDEProvisioningErrorPlatform=com.apple.platform.iphoneos, 
IDEProvisioningError_UserInfoKey_IDEProvisioningErrorAction=5, 
NSLocalizedRecoverySuggestion=No "iOS Distribution" signing certificate matching team ID "P9DNHPPVMB" with a private key was found.,
IDEProvisioningError_UserInfoKey_IDEProvisioningErrorSpecifier=iOS Distribution,
IDEProvisioningError_UserInfoKey_IDEProvisioningErrorTeam=<IDEProvisioningBasicTeam: 0x7f884413e0c0; teamID='P9DNHPPVMB', teamName='(null)'>,
NSLocalizedDescription=No signing certificate "iOS Distribution" found
}
Team:Personal Team is not enrolled in the Apple Developer Program.png

-exportOptionsPlist可以指向一个plist文件,文件内容大致如下:

plist文件.png

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>teamID</key>
    <string>P9DNHPPVMB</string>
    <key>method</key>
    <string>ad-hoc</string>
    <key>uploadSymbols</key>
    <true/>
    <key>provisioningProfiles</key>
    <dict>
        <key>com.jason.abcdefg</key>
        <string>6ce1bd8e-21b4-43c0-a00c-5aa86e131b45</string>
    </dict>
</dict>
</plist>

<key>provisioningProfiles</key> :
xxxx.mobileprovision[6ce1bd8e-21b4-43c0-a00c-5aa86e131b45.mobileprovision]
Xcode把Profiles下载到如下目录:
~/Library/MobileDevice/Provisioning Profiles

mobileprovision是二进制文件无法查看, 可以用如果下的命令查看文件内容

security cms -D -i 6ce1bd8e-21b4-43c0-a00c-5aa86e131b45.mobileprovision
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>AppIDName</key>
    <string>XC com jason abcdefg</string>
    <key>ApplicationIdentifierPrefix</key>
    <array>
    <string>P9DNHPPVMB</string>
    </array>
    <key>DeveloperCertificates</key>
    <array>
        <data>MIIFmjCCBIKgAwIBAgIISlCOHuhedtMwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgwNzIyMjM0NzMzWhcNMTkwNzIyMjM0NzMzWjCBjTEaMBgGCgmSJomT8ixkAQEMCk5OTDNENUg4MjIxOzA5BgNVBAMMMmlQaG9uZSBEZXZlbG9wZXI6IHpob3VqaWVfOTAzQDE2My5jb20gKFRDRExWRkVRSEopMRMwEQYDVQQLDApQOUROSFBQVk1CMRAwDgYDVQQKDAfmnbAg5ZGoMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPer0ggVn8D+jjuhHTxyFex3bk1Dp+Oxz7115mFwmwKwn0w7/RFFg87NpL3nGZA5FPpLdJfDPdZiVoNMcKA5Tl+KQRH9FYXENtli/Bn2/VEt9Cv8QQH71h26/U/mKtkBZCtxP4nR52v36naheUCS+2vB9UUy0Ndm2FnobegD8biJlJqtNFVYXTAQ+F/kJEnuLwWcr/uWmq4iteUvQxIOBkGlguw2g6Auw7/TjA1/6HGPaVsX3Tpz/M7A2I7nUB6QU54Z+sGnuMSJbelzwx8o1UyXTzgmuxaPMPUyARUETcDBKZLQ0QLNAkUCNpl1Ss6zv5trE06mbelquKBXp3BdUncCAwEAAaOCAfEwggHtMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUiCcXCam2GGCL7Ou69kdZxVJUo7cwPwYIKwYBBQUHAQEEMzAxMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDAzLXd3ZHIwMTCCAR0GA1UdIASCARQwggEQMIIBDAYJKoZIhvdjZAUBMIH+MIHDBggrBgEFBQcCAjCBtgyBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMDYGCCsGAQUFBwIBFipodHRwOi8vd3d3LmFwcGxlLmNvbS9jZXJ0aWZpY2F0ZWF1dGhvcml0eS8wFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwMwHQYDVR0OBBYEFHuh/bXHzpKtVf6EXpIIYrQ2j19hMA4GA1UdDwEB/wQEAwIHgDATBgoqhkiG92NkBgECAQH/BAIFADANBgkqhkiG9w0BAQsFAAOCAQEAo9AA9R9Lg6f77WY4n51KgP8MMHaEdDKmuji/sdHVhqCpMqfGdcVmweE2lp4M38g/SD2diOFL4YhXdlwG3e1jc68L8GIvfT+AeaAk3G2K7D6Ew6iR4vmAmWTUKbb8OIN7a5KGALKABfwAEDHynJnN+x2n7yCsQtlf1pF8vkYgmewDAeBPqc2ruq9WvxIcRDsAixEr0/f08zzohHSK0omAYSuKTd85UqRnZ1QUSbrDIG2U+H0qiS+0Qw4xyCHjlqtWRbMaoEppowcjgah8Llnp0Lel56mW0l4iMZdbHlRpsDbA+gX1tPeJN5ztvnNEjawDDQ8tT+U3RW7OcWrcIq43Cg==</data>
    </array>
    <key>Entitlements</key>
    <dict>
        <key>keychain-access-groups</key>
        <array>
            <string>P9DNHPPVMB.*</string>
        </array>
        <key>get-task-allow</key>
        <true/>
        <key>application-identifier</key>
        <string>P9DNHPPVMB.com.jason.abcdefg</string>
        <key>com.apple.developer.team-identifier</key>
        <string>P9DNHPPVMB</string>

    </dict>
    <key>ExpirationDate</key>
    <date>2018-11-01T11:22:49Z</date>
    <key>Name</key>
    <string>iOS Team Provisioning Profile: com.jason.abcdefg</string>
    <key>ProvisionedDevices</key>
    <array>
        <string>a82fecc1d3f1628f85e5055e238d8515f23624da</string>
    </array>
    <key>TeamIdentifier</key>
    <array>
        <string>P9DNHPPVMB</string>
    </array>
    <key>TeamName</key>
    <string>&#26480; &#21608;</string>
    <key>UUID</key>
    <string>6ce1bd8e-21b4-43c0-a00c-5aa86e131b45</string>
</dict>
</plist>

Xcode 10生成的ExportOptions.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>compileBitcode</key>
    <true/>
    <key>method</key>
    <string>development</string>
    <key>signingStyle</key>
    <string>automatic</string>
    <key>stripSwiftSymbols</key>
    <true/>
    <key>teamID</key>
    <string>P9DNHPPVMB</string>
    <key>thinning</key>
    <string>&lt;none&gt;</string>
</dict>
</plist>
ipa目录结构.png

013


iOS 中的数组排序操作

NSLiteralSearch
区分 同一个字符(如日文的片假字)的半角与全角状态[半角状态 > 全角状态]

NSWidthInsensitiveSearch
不区分 同一个字符(如日文的片假字)的半角与全角状态[半角状态 = 全角状态]
同时指定两个时,NSWidthInsensitiveSearch 比 NSLiteralSearch 的优先级高,综合起来的结果: [半角状态 = 全角状态]

NSForcedOrderingSearch
NSForcedOrderingSearch 的优先级最高

参考iOS 中的数组排序操作

012


工作线程中销毁对象

对象的销毁虽然消耗资源不多,但累积起来也是不容忽视的。通常当容器类持有大量对象时,其销毁时的资源消耗就非常明显。同样的,如果对象可以放到后台线程去释放,那就挪到后台线程去。这里有个小 Tip:把对象捕获到 block 中,然后扔到后台队列去随便发送个消息以避免编译器警告,就可以让对象在后台线程销毁了

NSArray *tmp = self.array;
self.array = nil;
dispatch_async(queue, ^{
    [tmp class];
});

引用自iOS 保持界面流畅的技巧

011


beginIgnoringInteractionEvents

UIApplication.shared.beginIgnoringInteractionEvents()
pvc.setViewControllers([vc], direction: dir, animated: true) { _ in 
  UIApplication.shared.endIgnoringInteractionEvents()         
}

In that code, I turn off user interaction when the page animation starts and turn it back on when the animation ends. The reason is that otherwise we can crash (or get into an incoherent state) if the user taps during the animation.

applicationWillTerminate:不一定被调用

For apps that do not support background execution or are linked against iOS 3.x or earlier, this method is always called when the user quits the app.
For apps that support background execution, this method is generally not called when the user quits the app because the app simply moves to the background in that case. However, this method may be called in situations where the app is running in the background (not suspended) and the system needs to terminate it for some reason

像阅读类应用如:咪咕阅读、掌阅、QQ阅读有朗读功能,开启了Background Modes:


朗读功能开启Background Modes.png

开启后进入后台一段时间,app被杀掉,applicationWillTerminate就不一定被调用

010


UIScrollView的scrollRectToVisible: animated:方法应用

UIScrollView的scrollRectToVisible: animated:NO 可以使用UIScrollView立即停止滑动,而用设置contentOffset的方法,还会滑动一会儿。见图:


2种方法日志比较

代码如下:


日志代码

009


iphone5 iOS7上UIScrollView的contentSize不能设置为CGFLOAT_MAX

最近在做阅读的上下滑动翻页功能,自然想到了UIScrollView
为了能无限翻页,把UIScrollView.contentSize = CGSizeMake(width, CGFLOAT_MAX)
测试发现在iphone5 iOS7崩溃


崩溃截图

解决方法:
UIScrollView.contentSize = CGSizeMake(width, 2^31);
可能原因是iphone5 iOS7是32位,不能大于2^32

008


JSQMessages的问题在iOS11上崩溃的问题

JSQMessagesComposerTextView(@interface JSQMessagesComposerTextView : UITextView)有个属性:
@property (weak, nonatomic, nullable) id<JSQMessagesComposerTextViewPasteDelegate> pasteDelegate;

在iOS11上崩溃,原因:

@protocol UITextPasteConfigurationSupporting <UIPasteConfigurationSupporting>
@property (nonatomic, weak, nullable) id<UITextPasteDelegate> pasteDelegate;
@end

@interface UITextView () <UITextPasteConfigurationSupporting>
@end

UITextView实现了UITextPasteConfigurationSupporting协议,而UITextPasteConfigurationSupporting定义了pasteDelegate,JSQMessagesComposerTextView定义的pasteDelegate与系统的冲突了

解决方法:
修改JSQMessagesComposerTextView的pasteDelegate为jsq_pasteDelegate

007

NSKeyedUnarchiver在iOS8下读取plist的问题

v7.3.0前用:
[NSArray writeToFile:savedFileName atomically:YES]来保存搜索记录;是一个plist文件
v7.3.1后用:
[NSKeyedArchiver archiveRootObject:array toFile:savedFileName]来保存搜索记录;是一个二进制文件

savedFileName都是同一个文件,在v7.3.1上覆写了v7.3.0的plist文件为二进制文件

在iOS8.4下的系统用如下代码读取文件时,崩溃;但iOS10以上正常

    NSMutableArray *recordArray;
    recordArray = [NSKeyedUnarchiver unarchiveObjectWithFile:savedFileName];
    if (recordArray == nil) {
        //旧数据提取
        recordArray = [NSMutableArray arrayWithContentsOfFile:savedFileName];
    }

为了让全部iOS版本都正常,修改代码如下:

    NSMutableArray *recordArray;
    @try {
        recordArray = [NSKeyedUnarchiver unarchiveObjectWithFile:savedFileName];
        if (recordArray == nil) {
            //旧数据提取
            recordArray = [NSMutableArray arrayWithContentsOfFile:savedFileName];
        }
    }
    @catch (NSException* e) {
        recordArray = [NSMutableArray arrayWithContentsOfFile:savedFileName];
    }

006


状态栏样式引起的神样问题

问题描述:

  1. UINavigationController里的2个ViewController:XXPlayerViewController, XXDownloaderManagerViewController.
  2. XXPlayerViewController不显示NavigationBar,preferredStatusBarStyle方法返回UIStatusBarStyleLightContent
  3. XXDownloaderManagerViewController显示NavigationBar,没有重写preferredStatusBarStyle方法,默认返回UIStatusBarStyleDefault
ViewController NavigationBar preferredStatusBarStyle
XXPlayer Hide UIStatusBarStyleLightContent
XXDownloaderManager Show UIStatusBarStyleDefault

步骤:XXDownloaderManagerViewController侧滑显示XXPlayerViewController,侧滑取消,并马上点击NavigationBar的“返回”按键

问题:XXPlayerViewController显示了XXDownloaderManagerViewController的UINavigationItem

解决方法:自定义的UINavigationController实现如下方法

- (UIViewController *)childViewControllerForStatusBarStyle {
    return self.topViewController;
}

参考:Bug when swiping from view with uinavigationbar to one without

005


AVAudioSessionRouteChangeNotification一般不在主线程通知

AVAudioSessionRouteChangeNotification一般不在主线程通知,需要注意多线程问题

004


iOS7上的问题02

speedSlider已创建,并在视图层次中,创建时minimumTrackTintColor,maximumTrackTintColor不为代码中的颜色,这时候调整值(比如应用设置成夜间模式),在iOS7上不生效

    //UISlider *speedSlider
    self.speedSlider.minimumTrackTintColor = RGB_COLOR(200, 100, 100);
    self.speedSlider.maximumTrackTintColor = RGB_COLOR(195, 206, 217);

iOS7上的问题01

有这么个函数:

- (void)showMainViewController:(NSInteger)pageIndex
{
}

它有一个参数:(NSInteger)pageIndex,在iOS7上,如下调用会有问题:

//targetVC实现了showMainViewController:方法
[targetVC performSelector:@selector(showMainViewController:) withObject:@0];
//或
[targetVC performSelector:@selector(showMainViewController:) withObject:[NSNumber numberWithInteger:0]];    

问题:pageIndex的值不为0,更像一个内存地址
解决方法:

((void(*)(id, SEL, NSInteger))objc_msgSend)(targetVC, @selector(showMainViewController:), 0);

003


Locale改变 NSCurrentLocaleDidChangeNotification

  • 通用-日期与时间-24小时制,收到通知
  • 通用-日期与时间-时区,不会收到通知
  • 通用-语言与地区-日历,不会收到通知
  • 通用-语言与地区-地区,杀死应用程序
  • 通用-语言与地区-iPhone语言,杀死应用程序
  • 通用-语言与地区-温度单位,收到通知

002


让特定UICollectionViewCell滚到可见范围内

问题:调用UICollectionView scrollToItemAtIndexPath: atScrollPosition: animated:不能让Cell滚到可见范围内
方法:可以这么调用:

[UICollectionView performBatchUpdates:^{
    [UICollectionView scrollToItemAtIndexPath: atScrollPosition: animated:];
} completion:nil];

001


不要在applicationDidEnterBackground做长时间操作

1. 按Home键进入后台
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    sleep(10);//模拟长时间操作
}
2. 1秒后点击应用进入前台,应用能显示
3. 这时点击界面是没有响应的
4. 10秒后applicationWillEnterForeground,applicationDidBecomeActive才被调用

NSLiteralSearch
区分 同一个字符(如日文的片假字)的半角与全角状态[半角状态 > 全角状态]

NSWidthInsensitiveSearch
不区分 同一个字符(如日文的片假字)的半角与全角状态[半角状态 = 全角状态]
同时指定两个时,NSWidthInsensitiveSearch 比 NSLiteralSearch 的优先级高,综合起来的结果: [半角状态 = 全角状态]

NSForcedOrderingSearch
NSForcedOrderingSearch 的优先级最高

000


NSString enumerateSubstringsInRange: options: usingBlock:可以断句

应用场景:咪咕阅读,掌阅等朗读时分句子高亮

[string enumerateSubstringsInRange:NSMakeRange(0, string.length)
                           options:NSStringEnumerationBySentences | NSStringEnumerationLocalized
                        usingBlock:block];

比如:完整的内容为:


或格式化显示:


格式化内容

断句后的结果:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 229,406评论 6 538
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,034评论 3 423
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 177,413评论 0 382
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,449评论 1 316
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,165评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,559评论 1 325
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,606评论 3 444
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,781评论 0 289
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,327评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,084评论 3 356
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,278评论 1 371
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,849评论 5 362
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,495评论 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,927评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,172评论 1 291
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,010评论 3 396
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,241评论 2 375