如何使用 Swift 关闭打开的文件?
How do you close open files using Swift?
我正在下载约 1300 张图片。这些都是小图片,总大小约为 500KB。但是,在下载并将它们放入 userDefault 后,出现如下错误:
libsystem_network.dylib: nw_route_get_ifindex :: socket(PF_ROUTE, SOCK_RAW, PF_ROUTE) 失败:[24] 太多打开文件
假设,下载的 png 图像没有被关闭。
我已经通过以下方式扩展了缓存大小:
// Configuring max network request cache size
let memoryCapacity = 30 * 1024 * 1024 // 30MB
let diskCapacity = 30 * 1024 * 1024 // 30MB
let urlCache = URLCache(memoryCapacity: memoryCapacity, diskCapacity: diskCapacity, diskPath: "myDiscPath")
URLCache.shared = urlCache
这是我存储图像的方法:
func storeImages (){
for i in stride(from: 0, to: Cur.count, by: 1) {
// Saving into userDefault
saveIconsToDefault(row: i)
}
}
将它们全部添加到 userDefault 后出现错误。所以,我知道他们在那里。
编辑:
函数:
func getImageFromWeb(_ urlString: String, closure: @escaping (UIImage?) -> ()) {
guard let url = URL(string: urlString) else {
return closure(nil)
}
let task = URLSession(configuration: .default).dataTask(with: url) { (data, response, error) in
guard error == nil else {
print("error: \(String(describing: error))")
return closure(nil)
}
guard response != nil else {
print("no response")
return closure(nil)
}
guard data != nil else {
print("no data")
return closure(nil)
}
DispatchQueue.main.async {
closure(UIImage(data: data!))
}
}; task.resume()
}
func getIcon (id: String, completion: @escaping (UIImage) -> Void) {
var icon = UIImage()
let imageUrl = "https://files/static/img/\(id).png"
getImageFromWeb(imageUrl) { (image) in
if verifyUrl(urlString: imageUrl) == true {
if let image = image {
icon = image
completion(icon)
}
} else {
if let image = UIImage(named: "no_image_icon") {
icon = image
completion(icon)
}
}
}
}
用法:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "CurrencyCell", for: indexPath) as? CurrencyCell else { return UITableViewCell() }
if currencies.count > 0 {
let noVal = currencies[indexPath.row].rank ?? "N/A"
let nameVal = currencies[indexPath.row].name ?? "N/A"
let priceVal = currencies[indexPath.row].price_usd ?? "N/A"
getIcon(id: currencies[indexPath.row].id!, completion: { (retImg) in
cell.configureCell(no: noVal, name: nameVal, price: priceVal, img: retImg)
})
}
return cell
}
URLSession(configuration: .default)
语法正在为每个请求创建一个新的 URLSession
。创建一个 URLSession
(将其保存在一些 属性 中),然后将其重新用于所有请求。或者,如果您真的没有对 URLSession
进行任何自定义配置,只需使用 URLSession.shared
:
let task = URLSession.shared.dataTask(with: url) { data, response, error in
...
}
task.resume()
您提到要在 UserDefaults
中保存 1300 张图像。那不是存储该类型数据或该数量文件的正确位置。我建议您使用 File System Programming Guide: The Library Directory Stores App-Specific Files 中概述的 "Caches" 文件夹。
let cacheURL = try! FileManager.default
.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("images")
// create your subdirectory before you try to save files into it
try? FileManager.default.createDirectory(at: cacheURL, withIntermediateDirectories: true)
也不要试图将它们存储在 "Documents" 文件夹中。有关详细信息,请参阅 iOS Storage Best Practices。
我正在下载约 1300 张图片。这些都是小图片,总大小约为 500KB。但是,在下载并将它们放入 userDefault 后,出现如下错误:
libsystem_network.dylib: nw_route_get_ifindex :: socket(PF_ROUTE, SOCK_RAW, PF_ROUTE) 失败:[24] 太多打开文件
假设,下载的 png 图像没有被关闭。
我已经通过以下方式扩展了缓存大小:
// Configuring max network request cache size
let memoryCapacity = 30 * 1024 * 1024 // 30MB
let diskCapacity = 30 * 1024 * 1024 // 30MB
let urlCache = URLCache(memoryCapacity: memoryCapacity, diskCapacity: diskCapacity, diskPath: "myDiscPath")
URLCache.shared = urlCache
这是我存储图像的方法:
func storeImages (){
for i in stride(from: 0, to: Cur.count, by: 1) {
// Saving into userDefault
saveIconsToDefault(row: i)
}
}
将它们全部添加到 userDefault 后出现错误。所以,我知道他们在那里。
编辑:
函数:
func getImageFromWeb(_ urlString: String, closure: @escaping (UIImage?) -> ()) {
guard let url = URL(string: urlString) else {
return closure(nil)
}
let task = URLSession(configuration: .default).dataTask(with: url) { (data, response, error) in
guard error == nil else {
print("error: \(String(describing: error))")
return closure(nil)
}
guard response != nil else {
print("no response")
return closure(nil)
}
guard data != nil else {
print("no data")
return closure(nil)
}
DispatchQueue.main.async {
closure(UIImage(data: data!))
}
}; task.resume()
}
func getIcon (id: String, completion: @escaping (UIImage) -> Void) {
var icon = UIImage()
let imageUrl = "https://files/static/img/\(id).png"
getImageFromWeb(imageUrl) { (image) in
if verifyUrl(urlString: imageUrl) == true {
if let image = image {
icon = image
completion(icon)
}
} else {
if let image = UIImage(named: "no_image_icon") {
icon = image
completion(icon)
}
}
}
}
用法:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "CurrencyCell", for: indexPath) as? CurrencyCell else { return UITableViewCell() }
if currencies.count > 0 {
let noVal = currencies[indexPath.row].rank ?? "N/A"
let nameVal = currencies[indexPath.row].name ?? "N/A"
let priceVal = currencies[indexPath.row].price_usd ?? "N/A"
getIcon(id: currencies[indexPath.row].id!, completion: { (retImg) in
cell.configureCell(no: noVal, name: nameVal, price: priceVal, img: retImg)
})
}
return cell
}
URLSession(configuration: .default)
语法正在为每个请求创建一个新的 URLSession
。创建一个 URLSession
(将其保存在一些 属性 中),然后将其重新用于所有请求。或者,如果您真的没有对 URLSession
进行任何自定义配置,只需使用 URLSession.shared
:
let task = URLSession.shared.dataTask(with: url) { data, response, error in
...
}
task.resume()
您提到要在 UserDefaults
中保存 1300 张图像。那不是存储该类型数据或该数量文件的正确位置。我建议您使用 File System Programming Guide: The Library Directory Stores App-Specific Files 中概述的 "Caches" 文件夹。
let cacheURL = try! FileManager.default
.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("images")
// create your subdirectory before you try to save files into it
try? FileManager.default.createDirectory(at: cacheURL, withIntermediateDirectories: true)
也不要试图将它们存储在 "Documents" 文件夹中。有关详细信息,请参阅 iOS Storage Best Practices。