iOS14適配

iOS14 的適配,很重要的一環(huán)就集中在\color{red}{用戶隱私}\color{red}{安全}方面。

在 iOS13 及以前,當(dāng)用戶首次訪問應(yīng)用程序時,會被要求開放大量權(quán)限,比如相冊、定位、聯(lián)系人等,實際上該應(yīng)用可能僅僅需要一個選擇圖片功能,卻被要求開放整個照片庫的權(quán)限,這確實是不合理的.

相冊

WWDC2020--What's new in PhotoKit

授權(quán)變更

iOS14 新增了Limited Photo Library Access模式,在授權(quán)彈窗中增加了 Select Photo 選項。用戶可以在 App 請求調(diào)用相冊時選擇部分照片讓 App 讀取。從 App 的視?來看,你的相冊里就只有這幾張照片,App 無法得知其它照片的存在。

public enum PHAuthorizationStatus : Int {
    ...
    @available(iOS 14, *)
    case limited = 4  //用戶已授權(quán)此應(yīng)用程序用于有限的照片庫訪問。 將PHPhotoLibraryPreventAutomaticLimitedAccessAlert = YES添加到應(yīng)用程序的Info.plist,以防止自動彈窗更新用戶受限的庫選擇。 使用PhotosUI / PHPhotoLibrary + PhotosUISupport.h中的-[PHPhotoLibrary(PhotosUISupport)presentLimitedLibraryPickerFromViewController:]手動顯示受限的庫選擇器。

}

相冊授權(quán)狀態(tài)新增PHAuthorizationStatus.limited,選擇此授權(quán)后,App有可能會在每次觸發(fā)相冊功能時都進行彈窗詢問用戶是否需要修改照片權(quán)限。

解決方案
在應(yīng)用程序的 info.plist 中添加
PHPhotoLibraryPreventAutomaticLimitedAccessAlert的值為 YES 來阻止該彈窗反復(fù)彈出,并且可通過下面這個 API 來手動顯示受限的庫選擇器進行照片選擇:

if #available(iOS 14, *) {
    PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: self)
}

注意PHAuthorizationStatus.limited僅在新API才有效,新API新增PHAccessLevel入?yún)?/p>

if #available(iOS 14, *) {
    PHPhotoLibrary.requestAuthorization(for: PHAccessLevel.readWrite) { authorizationStatus in
        switch authorizationStatus {
        case .limited: print("同意訪問部分相冊")
        case .authorized: print("同意訪問全部相冊")
        case .denied: print("拒絕訪問相冊")
        default: print("等待用戶確認(rèn)")
        }
    }
}

注意:
limit Photo 模式下,AssetsLibrary 訪問相冊會失敗;
在 writeOnly 模式下,AssetLibrary 也會有顯示問題。建議還在使用 AssetsLibrary 的同學(xué)盡快遷移到新 API。

相冊庫變更

iOS14 中官方推薦使用 PHPicker 來替代原 API 進行圖片選擇。PHPicker 為獨立進程,會在視圖最頂層進行展示,應(yīng)用內(nèi)無法對其進行截圖也無法直接訪問到其內(nèi)的數(shù)據(jù)。

UIImagePickerViewController 功能受限,每次只能選擇一張圖片,將逐漸被廢棄。

    public enum SourceType : Int {
        @available(iOS, introduced: 2, deprecated: 100000, message: "Will be removed in a future release, use PHPicker.")
        case photoLibrary = 0

        case camera = 1

        @available(iOS, introduced: 2, deprecated: 100000, message: "Will be removed in a future release, use PHPicker.")
        case savedPhotosAlbum = 2
    }

PHPicker 支持多選,支持搜索,支持按 image,video,livePhotos等進行選擇。

import UIKit
import PhotosUI

class ViewController: UITableViewController {

    var imageView = UIImageView()

    override func viewDidLoad() {
        super.viewDidLoad()

        if #available(iOS 14, *) {
            var pickerConfig = PHPickerConfiguration()
            pickerConfig.filter = .images
            pickerConfig.selectionLimit = 3 // 默認(rèn)為1,為0時表示可多選。
            
            let picker = PHPickerViewController(configuration: pickerConfig)
            picker.delegate = self
            present(picker, animated: true) {
                
            }
        }
    }
}

extension ViewController: PHPickerViewControllerDelegate {
    
    @available(iOS 14, *)
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        picker.dismiss(animated: true, completion: nil)
        
        if results.isEmpty { return }
        
        if let itemProvider = results.first?.itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self) {
            itemProvider.loadObject(ofClass: UIImage.self) { image, error in
                DispatchQueue.main.async {
                    if let image = image as? UIImage {
                        // Do something with image
                        self.imageView.image = image
                    }
                }
            }
        }
    }
}


IDFA隱私加強

IDFA 全稱為 Identity for Advertisers,即廣告標(biāo)識符。用來標(biāo)記用戶,廣泛的用于投放廣告、個性化推薦等

iOS13 及以前,系統(tǒng)會默認(rèn)為用戶開啟允許追蹤設(shè)置,我們可以簡單的通過代碼來獲取到用戶的 IDFA 標(biāo)識符。

if ASIdentifierManager.shared().isAdvertisingTrackingEnabled {
    let idfaString = ASIdentifierManager.shared().advertisingIdentifier.uuidString
}

iOS14之后,這個判斷用戶是否允許被追蹤的方法已經(jīng)廢棄:

@available(iOS, introduced: 6, deprecated: 14, message: "This has been replaced by functionality in AppTrackingTransparency's ATTrackingManager class.")
open var isAdvertisingTrackingEnabled: Bool { get }

IDFA默認(rèn)關(guān)閉,需要向用戶申請獲取權(quán)限,需要在info.plist中明示用戶申請權(quán)限:
key : NSUserTrackingUsageDescription
value: “需要獲取您的設(shè)備信息用以推送您喜歡的內(nèi)容”

不添加會產(chǎn)生以下crash

[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 NSUserTrackingUsageDescription key with a string value explaining to the user how the app uses this data.

引入系統(tǒng)庫 AppTrackingTransparency、AdSupport

import AppTrackingTransparency
import AdSupport

if #available(iOS 14, *) {
    ATTrackingManager.requestTrackingAuthorization { (status) in
        switch status {
        //已授權(quán)
        case .authorized: let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
        case .denied: print("用戶拒絕訪問設(shè)備信息")
        default: print("等待用戶確認(rèn)")
        }
    }
}

定位

WWDC2020--What's new in location
iOS14 定位授權(quán)彈窗新增 Precise 開關(guān),默認(rèn)開啟,顯示用戶精確位置。用戶通過這個開關(guān)可以進行更改。
On :地圖上會顯示精確位置;
Off:將顯示用戶的大致位置

一旦用戶關(guān)閉精準(zhǔn)定位,對于對用戶位置敏感度不高的 App 來說,這個似乎無影響,但是對于強依賴精確位置的 App 適配工作就顯得非常重要了。
一種辦法是:可以通過切換用戶到“隱私設(shè)置”中開啟精確定位,但是可能用戶寧可放棄使用這個應(yīng)用也不愿意授權(quán)app過多的訪問權(quán)限。

臨時精準(zhǔn)位置授權(quán)

iOS14 在 CLLocationManager 新增兩個方法可用于向用戶申請臨時開啟一次精確位置權(quán)限。

@available(iOS 14.0, *)
open func requestTemporaryFullAccuracyAuthorization(withPurposeKey purposeKey: String, completion: ((Error?) -> Void)? = nil)

@available(iOS 14.0, *)
open func requestTemporaryFullAccuracyAuthorization(withPurposeKey purposeKey: String)

在 Info.plist 中配置NSLocationTemporaryUsageDescriptionDictionary字典,字典中可以配置多個 purposeKey精準(zhǔn)位置用途

    <key>NSLocationTemporaryUsageDescriptionDictionary</key>
    <dict>
        <key>TacoFeature</key>
        <string>your precise location will be used to deliver tacos to you</string>
        <key>WantsToNavigate</key>
        <string>您的精確位置將用于計算路線,并允許您使用轉(zhuǎn)彎路線</string>
    </dict>

最終實現(xiàn)的時候,根據(jù)配置的 purposeKey ,授權(quán)框展示不同的內(nèi)容

func userWantsToNavigate() {
    //例如,app需要導(dǎo)航,但是用戶關(guān)閉了精準(zhǔn)定位
    if #available(iOS 14.0, *) {
        if locationManager.accuracyAuthorization == .reducedAccuracy {//定位精度受限,不精準(zhǔn)
            locationManager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: "WantsToNavigate") {_ in 
                if self.locationManager.accuracyAuthorization == .fullAccuracy {
                    self.beginNavigation()
                }
            }
        } else {
            self.beginNavigation()
        }
    } else {
        
    }
}

最終呈現(xiàn)給用戶的就是左圖,右圖為當(dāng)App主動關(guān)閉精確定位權(quán)限申請

主動設(shè)置定位精度

  • 可以直接通過API來根據(jù)不同的需求設(shè)置不同的定位精確度。
let locationMng = CLLocationManager()
locationMng.desiredAccuracy = kCLLocationAccuracyReduced
  • 對于地理位置不敏感的App 來說,iOS14 也可以通過直接在 info.plist 中添加 NSLocationDefaultAccuracyReduced 為 true 默認(rèn)請求大概位置。
    但是,這樣設(shè)置之后,即使用戶想要為該 App 開啟精確定位權(quán)限,也無法開啟。

注意,當(dāng) App 在 Background 模式下,如果并未獲得精確位置授權(quán),那么 Beacon 及其他位置敏感功能都將受到限制。


Local Network

iOS14 當(dāng) App 要使用 Bonjour 服務(wù)、訪問本地局域網(wǎng)、使用 mDNS 服務(wù)等,都需要授權(quán),開發(fā)者需要在 Info.plist 中詳細描述使用的為哪種服務(wù)以及用途:

下圖為需要無需申請權(quán)限與需要授權(quán)的服務(wù):

設(shè)置-> 隱私 中也可以查看和修改具體有哪些 App 正在使用 LocalNetwork:

對于使用了下列包含 Bonjour 的 framework,都需要更新描述:

Wi-Fi Address

iOS8 - iOS13 ,用戶在不同的網(wǎng)絡(luò)間切換和接入時mac 地址都不會改變,這也就使得網(wǎng)絡(luò)運營商還是可以通過 mac 地址對用戶進行匹配和用戶信息收集,生成完整的用戶信息。

iOS14 提供 Wifi 加密服務(wù),每次接入不同的 WiFi 使用的 mac 地址都不同。每過 24 小時,mac 地址還會更新一次。需要關(guān)注是否有使用用戶網(wǎng)絡(luò) mac 地址的服務(wù)。

用戶也可以自行選擇是否開啟 private Wi-Fi address:


剪切板

在 iOS14 中,讀取用戶剪切板的數(shù)據(jù)會彈出提示:


彈出提示的原因是使用 UIPasteboard 訪問用戶數(shù)據(jù),訪問以下數(shù)據(jù)都會彈出 toast 提示:

    open var string: String?
    open var strings: [String]?

    open var url: URL?
    open var urls: [URL]?

    @NSCopying open var image: UIImage?
    open var images: [UIImage]?

    @NSCopying open var color: UIColor?
    open var colors: [UIColor]?

如果應(yīng)用訪問剪切板僅僅用于判斷是否為URL格式,則 iOS14 新增了兩個 API 可以用于規(guī)避該提示,但只能用于判斷剪切板中是否有 URL,無法訪問甚至獲取剪貼板數(shù)據(jù):

extension UIPasteboard.DetectionPattern {

    /// NSString value, suitable for implementing "Paste and Go"
    @available(iOS 14.0, *)
    public static let probableWebURL: UIPasteboard.DetectionPattern

    /// NSString value, suitable for implementing "Paste and Search"
    @available(iOS 14.0, *)
    public static let probableWebSearch: UIPasteboard.DetectionPattern
}

如果應(yīng)用想直接訪問剪切板的數(shù)據(jù),暫時可能無法做到規(guī)避該提示。


相機和麥克風(fēng)

iOS14 中 App 使用相機麥克風(fēng)時會有圖標(biāo)提示以及綠點和黃點提示,并且會顯示當(dāng)前是哪個 App 在使用此功能。我們無法控制是否顯示該提示。


會觸發(fā)錄音小黃點的代碼示例:

let recorder = try? AVAudioRecorder(url: fileURL, settings: [:])
recorder?.record()

觸發(fā)相機小綠點的代碼示例:

guard let device = AVCaptureDevice.default(for: AVMediaType.video) else {
    return
}
let input = try? AVCaptureDeviceInput(device: device)
let session = AVCaptureSession()
guard let input2 = input, session.canAddInput(input2) else { return }
session.canAddInput(input2)
session.startRunning()

UITableView

UITableViewHeaderFooterView

tableView在plain模式下,UITableViewHeaderFooterView默認(rèn)為淺灰色背景,直接設(shè)置背景色或者子視圖背景色為UIColor.clear,親測無效

使用debug view hierarchy 看出來HeaderView 層級有所變化
old : ProbabilityCollegeHeaderView -> _UISystemBackgroundView -> _UITableViewHeaderFooterContentView
new : ProbabilityCollegeHeaderView -> _UISystemBackgroundView -> UIView -> _UITableViewHeaderFooterContentView

iOS14增加了backgroundConfiguration 配置方法,設(shè)置此圖層的背景樣式

if #available(iOS 14.0, *) {
    self.backgroundConfiguration = UIBackgroundConfiguration.clear()
}

UITableViewCell

在 iOS14 中,UITableViewCell 中如果有直接添加在 cell 上的控件,也就是使用self.addSubview(_)方式添加的控件,會顯示在 contentView 的下層,contentView 會阻擋事件交互,使所有事件都響應(yīng)tableView:didSelectRowAtIndexPath:方法如果 customView 存在交互事件將無法響應(yīng)。如果 contentView 設(shè)置了背景色,還會影響界面顯示.


UIDatePicker

iOS 14 中,UIDatePicker UI樣式更新了

@available(iOS 13.4, *)
open var preferredDatePickerStyle: UIDatePickerStyle

如果想使用原來的播輪樣式,需要設(shè)置:

datePicker.preferredDatePickerStyle = .wheels

Xcode12

xcode12默認(rèn)不支持模擬器架構(gòu),導(dǎo)致某些項目運行發(fā)生如下錯誤:

No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID...

或者:
ld: in /Users/vicentwyh/xxx, building for iOS Simulator, but linking in object file built for iOS, file '/Users/vicentwyhxxx for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

解決方法:(以下任選一種一種)

  • 在Build Setting中,刪除VALID_ARCHS這一欄
  • 或者在VALID_ARCHS添加x86_64

參考:
iOS14 隱私適配及部分解決方案

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容