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) 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=,
NSLocalizedDescription=No signing certificate "iOS Distribution" found
}
iOS知识点_第1张图片
Team:Personal Team is not enrolled in the Apple Developer Program.png

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

iOS知识点_第2张图片
plist文件.png





    teamID
    P9DNHPPVMB
    method
    ad-hoc
    uploadSymbols
    
    provisioningProfiles
    
        com.jason.abcdefg
        6ce1bd8e-21b4-43c0-a00c-5aa86e131b45
    


provisioningProfiles :
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




    AppIDName
    XC com jason abcdefg
    ApplicationIdentifierPrefix
    
    P9DNHPPVMB
    
    DeveloperCertificates
    
        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==
    
    Entitlements
    
        keychain-access-groups
        
            P9DNHPPVMB.*
        
        get-task-allow
        
        application-identifier
        P9DNHPPVMB.com.jason.abcdefg
        com.apple.developer.team-identifier
        P9DNHPPVMB

    
    ExpirationDate
    2018-11-01T11:22:49Z
    Name
    iOS Team Provisioning Profile: com.jason.abcdefg
    ProvisionedDevices
    
        a82fecc1d3f1628f85e5055e238d8515f23624da
    
    TeamIdentifier
    
        P9DNHPPVMB
    
    TeamName
    杰 周
    UUID
    6ce1bd8e-21b4-43c0-a00c-5aa86e131b45


Xcode 10生成的ExportOptions.plist





    compileBitcode
    
    method
    development
    signingStyle
    automatic
    stripSwiftSymbols
    
    teamID
    P9DNHPPVMB
    thinning
    <none>


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:


iOS知识点_第3张图片
朗读功能开启Background Modes.png

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

010


UIScrollView的scrollRectToVisible: animated:方法应用

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


iOS知识点_第4张图片
2种方法日志比较

代码如下:


iOS知识点_第5张图片
日志代码

009


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

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


iOS知识点_第6张图片
崩溃截图

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

008


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

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

在iOS11上崩溃,原因:

@protocol UITextPasteConfigurationSupporting 
@property (nonatomic, weak, nullable) id pasteDelegate;
@end

@interface UITextView () 
@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
iOS知识点_第7张图片
ViewController NavigationBar preferredStatusBarStyle
XXPlayer Hide UIStatusBarStyleLightContent
XXDownloaderManager Show UIStatusBarStyleDefault

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

问题:XXPlayerViewController显示了XXDownloaderManagerViewController的UINavigationItem

iOS知识点_第8张图片

解决方法:自定义的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];

比如:完整的内容为:


或格式化显示:


iOS知识点_第9张图片
格式化内容

断句后的结果:


iOS知识点_第10张图片

你可能感兴趣的:(iOS知识点)