[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
}
-exportOptionsPlist
可以指向一個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>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>杰 周</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><none></string>
</dict>
</plist>
013
iOS 中的數組排序操作
NSLiteralSearch
區分 同一個字符(如日文的片假字)的半角與全角狀態[半角狀態 > 全角狀態]
NSWidthInsensitiveSearch
不區分 同一個字符(如日文的片假字)的半角與全角狀態[半角狀態 = 全角狀態]
同時指定兩個時,NSWidthInsensitiveSearch 比 NSLiteralSearch 的優先級高,綜合起來的結果: [半角狀態 = 全角狀態]
NSForcedOrderingSearch
NSForcedOrderingSearch 的優先級最高
012
工作線程中銷毀對象
對象的銷毀雖然消耗資源不多,但累積起來也是不容忽視的。通常當容器類持有大量對象時,其銷毀時的資源消耗就非常明顯。同樣的,如果對象可以放到后臺線程去釋放,那就挪到后臺線程去。這里有個小 Tip:把對象捕獲到 block 中,然后扔到后臺隊列去隨便發送個消息以避免編譯器警告,就可以讓對象在后臺線程銷毀了
NSArray *tmp = self.array;
self.array = nil;
dispatch_async(queue, ^{
[tmp class];
});
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:
開啟后進入后臺一段時間,app被殺掉,applicationWillTerminate就不一定被調用
010
UIScrollView的scrollRectToVisible: animated:方法應用
UIScrollView的scrollRectToVisible: animated:NO 可以使用UIScrollView立即停止滑動,而用設置contentOffset的方法,還會滑動一會兒。見圖:
代碼如下:
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
狀態欄樣式引起的神樣問題
問題描述:
- UINavigationController里的2個ViewController:XXPlayerViewController, XXDownloaderManagerViewController.
- XXPlayerViewController不顯示NavigationBar,preferredStatusBarStyle方法返回UIStatusBarStyleLightContent
- 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];
比如:完整的內容為:
或格式化顯示:
斷句后的結果: