import MySwiftIperf
) и начинаете измерять.URLSession
некий большой файл. У URLSession
есть отличный делегат, в котором можно глянуть текущую порцию скаченных данных. Этого достаточно для измерения скорости. Начальное время, текущее время, текущее кол-во скаченных байт, всё это делим на нужное измерение в кб/мб/...import Foundation
let json = """
[{
"idSite": 204233,
"status": 0,
"Name": "",
"timeOfStatus": null
},
{
"idSite": 204234,
"status": 0,
"Name": "",
"timeOfStatus": null
},
{
"idSite": 204235,
"status": 0,
"Name": "",
"timeOfStatus": null
},
{
"idSite": 204236,
"status": 1,
"Name": "OK",
"timeOfStatus": "2019-06-26 12:58:16"
}]
"""
struct SomeStruct: Decodable {
let idSite: Int
let status: Bool
let name: String
let timeOfStatus: Date?
// Преобразуем Name -> name
private enum CodingKeys: String, CodingKey {
case idSite
case status
case name = "Name"
case timeOfStatus
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.idSite = try container.decode(Int.self, forKey: .idSite)
// Выбрасываем ошибку, если статус не равен 1. Не выделяем зря память.
let status = try container.decode(Int.self, forKey: .status)
if status == 1 {
self.status = true
} else {
throw DecodingError.dataCorruptedError(forKey: .status, in: container, debugDescription: "Status mast be `1`")
}
self.name = try container.decode(String.self, forKey: .name)
// Преобразуем строку с датой в объект для работы с датами Date
let date = try? container.decode(String.self, forKey: .timeOfStatus)
let dateFormatter: DateFormatter = {
$0.dateFormat = "yyyy-MM-dd HH:mm:ss"
$0.calendar = Calendar(identifier: .iso8601)
$0.timeZone = TimeZone(secondsFromGMT: 0)
$0.locale = Locale(identifier: "en_US_POSIX")
return $0
}(DateFormatter())
self.timeOfStatus = date != nil ? dateFormatter.date(from: date!) : nil
}
}
// Тип обёртка, которая даст легко отфильтровать данные, от тех, которые не прошли из-за статуса.
enum Throwable<T: Decodable>: Decodable {
case success(T), failure(Error)
init(from decoder: Decoder) throws {
do {
let decoded = try T(from: decoder)
self = .success(decoded)
} catch let error {
self = .failure(error)
}
}
var value: T? {
switch self {
case .failure(_):
return nil
case .success(let value):
return value
}
}
}
let decoder = JSONDecoder()
let arrayOfSomeStructs = try! decoder.decode([Throwable<SomeStruct>].self, from: json.data(using: .utf8)!)
let filteredArrayOfSomeStructs = arrayOfSomeStructs.compactMap{ $0.value }
print(filteredArrayOfSomeStructs.count)
func playVideo(filename: String) {
let path = Bundle.main.path(forResource: filename, ofType:"mp4")!
player = AVPlayer(url: NSURL(fileURLWithPath: path) as URL)
playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = CGRect(x: 880, y: 270, width: 960, height: 540)
scene!.view!.layer.addSublayer(playerLayer)
player.actionAtItemEnd = .none
player.play()
DispatchQueue.main.async {
NotificationCenter.default.addObserver(self,
selector: #selector(playerItemDidReachEnd),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime ,
object: self.player.currentItem)
}
}
@objc func playerItemDidReachEnd(notification: NSNotification) {
print("repeating...")
let seconds : Int64 = 0
let preferredTimeScale : Int32 = 1
let seekTime : CMTime = CMTimeMake(value: seconds, timescale: preferredTimeScale)
player.seek(to: seekTime)
player.play()
}
let json = """
[{
"invoiceNumber": "FV/MON/X/369",
"date": "2019-06-01 00:00:00",
"dueDate": "2019-06-01 00:00:00",
"overdue": true,
"valueNoTax": 100,
"valueWithTax": 123,
"valueToPay": 123
},
{
"invoiceNumber": "FV/MON/X/368",
"date": "2019-06-01 00:00:00",
"dueDate": "2019-06-01 00:00:00",
"overdue": true,
"valueNoTax": 100,
"valueWithTax": 123,
"valueToPay": 123
},
{
"invoiceNumber": "FV/MON/X/367",
"date": "2019-06-01 00:00:00",
"dueDate": "2019-06-01 00:00:00",
"overdue": true,
"valueNoTax": 100,
"valueWithTax": 123,
"valueToPay": 123
},
{
"invoiceNumber": "FV/MON/X/366",
"date": "2019-06-01 00:00:00",
"dueDate": "2019-06-01 00:00:00",
"overdue": true,
"valueNoTax": 100,
"valueWithTax": 123,
"valueToPay": 123
},
{
"invoiceNumber": "FV/MON/X/363",
"date": "2019-05-04 00:00:00",
"dueDate": "2019-05-04 00:00:00",
"overdue": true,
"valueNoTax": 100,
"valueWithTax": 123,
"valueToPay": 123
},
{
"invoiceNumber": "FV/MON/X/362",
"date": "2019-05-04 00:00:00",
"dueDate": "2019-05-04 00:00:00",
"overdue": true,
"valueNoTax": 100,
"valueWithTax": 123,
"valueToPay": 123
},
{
"invoiceNumber": "FV/MON/X/361",
"date": "2019-05-04 00:00:00",
"dueDate": "2019-05-04 00:00:00",
"overdue": true,
"valueNoTax": 100,
"valueWithTax": 123,
"valueToPay": 123
},
{
"invoiceNumber": "FV/MON/X/360",
"date": "2019-05-04 00:00:00",
"dueDate": "2019-05-04 00:00:00",
"overdue": true,
"valueNoTax": 100,
"valueWithTax": 123,
"valueToPay": 123
}]
"""
struct FakturyObject: Decodable {
let date: String
let dueDate: String
let invoiceNumber: String
let overdue: Bool // <---- ОШИБКА БЫЛА ТУТ!
let valueNoTax: Int
let valueToPay: Int
let valueWithTax: Int
}
let data = json.data(using: .utf8)
let decoder = JSONDecoder()
let parsedData = try! decoder.decode([FakturyObject].self, from: data!)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "chat") as! ChatsTableViewCell;
cell.imageUser.image = UIImage.convertBase64ToImage(imageString: (data?.list[indexPath.row].imageUser)!)
cell.imageUser.layer.cornerRadius = cell.frame.size.height / 2;
cell.imageUser.clipsToBounds = true;
return cell;
}
awakeFromNib
)printf
. Посмотрите, сколько раз вызывается эта функция и сравните с тем, сколько раз будет вызываться ваш код в tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
import UIKit
final class Cell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
imageView?.clipsToBounds = true
imageView?.contentMode = .scaleAspectFit
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var frame: CGRect {
didSet {
guard frame.height != oldValue.height else { return }
imageView?.layer.cornerRadius = frame.height / 2.0
print(#function)
}
}
}
final class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(Cell.self, forCellReuseIdentifier: "Cell")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 21;
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.imageView?.image = UIImage(named: "c-1-8")!
cell.textLabel?.text = "Ooops";
return cell;
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return tableView.frame.width * 0.25;
}
}
Слушай, я вижу что такой метод есть, но почему-то у тебя отличаются названия агрументов. Может глянешь?
⌘ + Shift + 0
. Если ввести название этого метода и глянуть на аргументы, то становится ясно, что presses
нужно заменить _ presses
, а withEvent
нужно заменить на with
Тоже самое сделать и со вторым методом.func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?)
let
не просто так. Опустим очевидное, исходящее из определения - неизменяемость. Но что стоит за этим на уровне компилятора? А стоят за этим нужные вещи. let
можно ведь пометить не только, скажем переменную содержащую число, а коллекцию или структуру или объект. mutable
В свою очередь это делает тоже не просто так. Any
и AnyObject
являются так называемыми Nonspecific types. Неспецифичные типы служат указателем компилятору о возможности хранения любого типа. НО за такую возможность нужно платить и Вы платите: String
, даже зная, что присвоенная переменная на самом деле является типом String
. У вас просто не будет такой информации ровно до тех пор, пока вы не преобразуете этот тип обратно. Any
, но это только во время выполнения кода, на момент компиляции информация об этом отсутсвует. print(_:separator:terminator:)
получает информацию о том, что вывести в консоль, исходя из того, что все стандартные типы реализуют протоколы CustomStringConvertible
, CustomDebugStringConvertible,
CustomReflectable
в реализации которых содержится информация о типе(текстовая). Если у типа нет реализации этих протоколов, print(_:separator:terminator:)
выводит просто название типа. dump(_:name:indent:maxDepth:maxItems:)
.T
подставит конкретный тип, скажем String
. Что в свою очередь приводит к тому, что у дженериков отсутствуют проблемы указанные выше. (Даже моё "во-первых" у дженериков отсутствуют, если вы накладываете на них ограничения. )public enum HTTPMethod: String {
case options = "OPTIONS"
case get = "GET"
case head = "HEAD"
case post = "POST"
case put = "PUT"
case patch = "PATCH"
case delete = "DELETE"
case trace = "TRACE"
case connect = "CONNECT"
}
completion
вашей анимации надо все же сказать системе, что анимация завершена. transitionContext.completeTransition(true)
// ...
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
layout.itemSize = UICollectionViewFlowLayout.automaticSize
contentView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
contentView.leftAnchor.constraint(equalTo: leftAnchor),
contentView.rightAnchor.constraint(equalTo: rightAnchor),
contentView.topAnchor.constraint(equalTo: topAnchor),
contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
let v = UIView(frame: .zero)
let l1 = UILabel(frame: .zero)
l1.translatesAutoresizingMaskIntoConstraints = false
l1.font = .systemFont(ofSize: 27.0)
l1.text = "asdlas"
v.addSubview(l1)
NSLayoutConstraint.activate([
l1.topAnchor.constraint(equalTo: v.topAnchor),
l1.leadingAnchor.constraint(equalTo: v.leadingAnchor),
])
l1.setContentHuggingPriority(.required, for: .vertical)
l1.setContentCompressionResistancePriority(.required, for: .vertical)
let trailing = l1.trailingAnchor.constraint(equalTo: v.trailingAnchor)
trailing.priority = .defaultHigh
NSLayoutConstraint.activate([
trailing
])
let l2 = UILabel(frame: .zero)
l2.translatesAutoresizingMaskIntoConstraints = false
l2.font = .systemFont(ofSize: 17.0)
l2.text = ""
v.addSubview(l2)
NSLayoutConstraint.activate([
l2.topAnchor.constraint(equalTo: l1.bottomAnchor),
l2.leadingAnchor.constraint(equalTo: v.leadingAnchor),
])
l2.setContentHuggingPriority(.required, for: .vertical)
l2.setContentCompressionResistancePriority(.required, for: .vertical)
let trailing_ = l2.trailingAnchor.constraint(equalTo: v.trailingAnchor)
trailing_.priority = .defaultHigh
let bottom = l2.bottomAnchor.constraint(equalTo: v.bottomAnchor)
bottom.priority = .defaultHigh
NSLayoutConstraint.activate([
trailing_,
bottom
])
let s = v.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
view.addSubview(v)
v.frame.size = s
v.center = view.center
v.layer.borderColor = UIColor.red.cgColor
v.layer.borderWidth = 1.0
func preferredLayoutAttributesFitting(
_ layoutAttributes: UICollectionViewLayoutAttributes
) -> UICollectionViewLayoutAttributes
{
let layoutAttributes = super.preferredLayoutAttributesFitting(layoutAttributes)
let fittingSize = UIView.layoutFittingCompressedSize
layoutAttributes.frame.size = systemLayoutSizeFitting(
fittingSize,
withHorizontalFittingPriority: .fittingSizeLevel,
verticalFittingPriority: .fittingSizeLevel
)
return layoutAttributes
}
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
// ...
}