Today, I’m going to share a problem we encountered recently. When we use WKWebView in the App to enter the web version of the Facebook page, we will not be able to log in. We got an error message as follows:
For your account security logging into Facebook from an embedded browser is disabled.
However, all the information on the Internet only mentions Android. Why can’t I log in to iOS?But I found that some of my projects are able to log in. After researching for a while, I discovered that you must add microphone permissions or camera permissions into info.plist and then you can log in facebook like magic!
struct OnboardingData: Hashable, Identifiable {
let id: Int
let mainImage: String
let titleText: String
let subtitleText: String
static let list: [OnboardingData] = [
OnboardingData(id: 0, mainImage: "plan", titleText: "Select your destination", subtitleText: "Choose your destination and plan your trip"),
OnboardingData(id: 1, mainImage: "money", titleText: "Book your ticket", subtitleText: "Use the price comparison system to book tickets and restaurants with the lowest prices"),
OnboardingData(id: 2, mainImage: "enjoy", titleText: "Enjoy the trip", subtitleText: "Please start and enjoy your journey!")
]
}
在這裡的 PassthroughSubject 可以直接從字面意思去理解,它沒有初始值,當它一被指定值時,它會通知訂閱者對此作出相對應的改變。此處的使用方式就是當 data 一被設定時,didChange 會利用 .send 指令,通知他的訂閱者作出改動。在 Apple 文件的定義如下:
As a concrete implementation of Subject, the PassthroughSubject provides a convenient way to adapt existing imperative code to the Combine model.Unlike CurrentValueSubject, a PassthroughSubject doesn’t have an initial value or a buffer of the most recently-published element. A PassthroughSubject drops values if there are no subscribers, or its current demand is zero. (參考 Apple 文件)
在初始化部分,我們利用 URLSession 指令從遠端讀取並下載物件:
class RemoteImageLoader: ObservableObject {
var didChange = PassthroughSubject<Data, Never>()
var data = Data() {
didSet {
didChange.send(data)
}
}
init(imageUrlString: String) {
guard let url = URL(string: imageUrlString) else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
DispatchQueue.main.async {
self.data = data
}
}
task.resume()
}
}
完成 RemoteImageLoader 之後,我們宣告一個訂閱此 RemoteImageLoader 的 RemoteImageView。可以看到 .onReceive 那行程式碼,當 RemoteImageView 收到 RemoteImageLoader 已經取得圖片 Date 資料的通知時,我們再利用 UIImage 去讀取 data 資料,轉而存進 Image 裡。
struct RemoteImageView: View {
@ObservedObject var imageLoader:RemoteImageLoader
@State var image: UIImage = UIImage()
init(withImageURL url:String) {
imageLoader = RemoteImageLoader(imageUrlString: url)
}
var body: some View {
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 200, height: 200)
.onReceive(imageLoader.didChange) { data in
self.image = UIImage(data: data) ?? UIImage()
}
}
}