Xcode 10.3
ios 12.4
swift5
ios 12.4
swift5
完成品
UI

コード
WorldClockVC
- import UIKit
- class WorldClockVC: UIViewController ,UITableViewDelegate,UITableViewDataSource{
- var selectTimezones = [String]()
- var userDefaults = UserDefaults.standard
- var timer = Timer()
- @IBOutlet weak var tableView: UITableView!
- override func viewDidLoad() {
- super.viewDidLoad()
- loadTimeZones()
- tableView.register(UINib(nibName: "WorldClockCell", bundle: nil), forCellReuseIdentifier: "WorldClockCell")
- self.navigationItem.setLeftBarButton(self.editButtonItem, animated: true)
- }
- func loadTimeZones(){
- if let getTimeZones = userDefaults.object(forKey: "TimeZones") as? [String]{
- selectTimezones = getTimeZones
- }
- }
- func saveTimeZones(){
- userDefaults.set(selectTimezones, forKey: "TimeZones")
- userDefaults.synchronize()
- }
- override func setEditing(_ editing: Bool, animated: Bool) {
- super.setEditing(editing, animated: animated)
- tableView.setEditing(editing, animated: animated)
- }
- func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
- return true
- }
- func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
- return true
- }
- func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
- let sourceCellItem = selectTimezones[sourceIndexPath.row]
- guard let indexPath = selectTimezones.firstIndex(of: sourceCellItem) else { return }
- selectTimezones.remove(at: indexPath)
- selectTimezones.insert(sourceCellItem, at: destinationIndexPath.row)
- saveTimeZones()
- }
- func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- return selectTimezones.count
- }
- func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
- return 60
- }
- func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- let cell = tableView.dequeueReusableCell(withIdentifier: "WorldClockCell") as! WorldClockCell
- cell.setCity(name: selectTimezones[indexPath.row])
- return cell
- }
- func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
- if editingStyle == .delete {
- selectTimezones.remove(at: indexPath.row)
- tableView.deleteRows(at: [indexPath], with: .fade)
- saveTimeZones()
- }
- }
- func timeZone(city:String) -> String{
- let formatter = DateFormatter()
- formatter.dateFormat = "HH:mm"
- let timeZoneIdentifiers = TimeZone.knownTimeZoneIdentifiers
- for identifier in timeZoneIdentifiers {
- if identifier.contains(city){
- formatter.timeZone = TimeZone(identifier: identifier)
- }
- }
- return formatter.string(from: Date())
- }
- override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
- guard let nvc = segue.destination as? UINavigationController else {return}
- guard let vc = nvc.topViewController as? WorldClockSelectVC else {return}
- vc.delegate = self
- }
- }
- extension WorldClockVC:WorldClockSelectVCDelegte{
- func worldClockSelect(cancel: WorldClockSelectVC) {
- self.setEditing(false, animated: false)
- }
- func worldClockSelect(selectedWorldClock: WorldClockSelectVC, selected: String) {
- if !selectTimezones.contains(selected){
- selectTimezones.append(selected)
- }
- tableView.reloadData()
- saveTimeZones()
- }
- }
WorldClockCell
- import UIKit
- class WorldClockCell: UITableViewCell {
- @IBOutlet weak var timeLabel: UILabel!
- @IBOutlet weak var cityLabel: UILabel!
- @IBOutlet weak var hrsLabel: UILabel!
- var timer = Timer()
- var cityName:String!
- override func awakeFromNib() {
- super.awakeFromNib()
- self.accessoryView = timeLabel
- }
- func setCity(name:String){
- cityLabel.text = name
- timeLabel.text = timeZone(city: name)
- hrsLabel.text = "Today,+0HRS"
- cityName = name
- timer = Timer.scheduledTimer(
- timeInterval: 1.0, // 時間間隔
- target: self, // タイマーの実際の処理の場所
- selector: #selector(WorldClockCell.tickTimer(_:)), // メソッド タイマーの実際の処理
- userInfo: nil,
- repeats: true)
- RunLoop.main.add(timer, forMode: RunLoop.Mode.common)
- }
- @objc func tickTimer(_ timer: Timer) {
- timeLabel.text = timeZone(city: cityName)
- }
- func timeZone(city:String) -> String{
- let formatter = DateFormatter()
- formatter.dateFormat = "HH:mm"
- formatter.timeStyle = .short
- formatter.locale = Locale(identifier: "ja_JP")
- let timeZoneIdentifiers = TimeZone.knownTimeZoneIdentifiers
- for identifier in timeZoneIdentifiers {
- if identifier.contains(city){
- formatter.timeZone = TimeZone(identifier: identifier)
- }
- }
- let timeDiff = formatter.timeZone.secondsFromGMT()
- hrsLabel.text = timeDiff.timeString()
- return formatter.string(from: Date())
- }
- }
- extension Int {
- func timeString() -> String {
- let adjustSecondsForJapan : TimeInterval = 9 * 60 * 60
- let formatter = DateComponentsFormatter()
- formatter.allowedUnits = [.day,.hour, .minute]
- formatter.unitsStyle = .positional
- let formattedString = formatter.string(from: TimeInterval(self) - adjustSecondsForJapan) ?? "0"
- let df = DateFormatter()
- df.dateStyle = .short
- df.doesRelativeDateFormatting = true
- let day = df.string(from: Date(timeIntervalSinceNow: TimeInterval(self) - adjustSecondsForJapan))
- if formattedString == "0" {
- return day + ", +0HRS"
- } else {
- if formattedString.hasPrefix("-") {
- return day + ", \(formattedString)HRS"
- } else {
- return day + "+\(formattedString)HRS"
- }
- }
- }
- }
WorldClockSelectVC
githubはこちら
- import UIKit
- protocol WorldClockSelectVCDelegte {
- func worldClockSelect(selectedWorldClock:WorldClockSelectVC,selected:String)
- func worldClockSelect(cancel:WorldClockSelectVC)
- }
- class WorldClockSelectVC: UIViewController {
- @IBOutlet weak var tableView: UITableView!
- @IBOutlet weak var nav: UINavigationBar!
- var delegate:WorldClockSelectVCDelegte!
- private var searchController: UISearchController!
- var filteredTitles = [[String]]()
- var timeZoneIdentifiers = [String]()
- var allCities: [String] = []
- var sortedFirstLetters: [String] = []
- var sections: [[String]] = [[]]
- var searchString:String = ""
- override func viewDidLoad() {
- super.viewDidLoad()
- searchController = UISearchController(searchResultsController: nil)
- searchController.searchResultsUpdater = self
- searchController.obscuresBackgroundDuringPresentation = false
- searchController.dimsBackgroundDuringPresentation = false
- searchController.searchBar.sizeToFit()
- searchController.searchBar.showsCancelButton = true
- searchController.searchBar.delegate = self
- // UISearchControllerをUINavigationItemのsearchControllerプロパティにセットする。
- navigationItem.searchController = searchController
- // trueだとスクロールした時にSearchBarを隠す(デフォルトはtrue)
- // falseだとスクロール位置に関係なく常にSearchBarが表示される
- navigationItem.hidesSearchBarWhenScrolling = false
- NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
- timeZoneIdentifiers = TimeZone.knownTimeZoneIdentifiers.sorted()
- for identifier in timeZoneIdentifiers {
- if let cityName = identifier.split(separator: "/").last {
- allCities.append("\(cityName)")
- }
- }
- let firstLetters = allCities.map { $0[$0.startIndex].uppercased() }
- let uniqueFirstLetters = Array(Set(firstLetters))
- sortedFirstLetters = uniqueFirstLetters.sorted()
- sections = sortedFirstLetters.map({firstLetter in return allCities.filter({ $0[$0.startIndex].uppercased() == firstLetter }).sorted(by: {$0 < $1})
- })
- filteredTitles = sections
- }
- @objc private func keyboardWillShow(notification: NSNotification) {
- if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
- tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
- }
- }
- @objc private func keyboardWillHide(notification: NSNotification) {
- tableView.contentInset = .zero
- }
- }
- // MARK: - UISearchResultsUpdating
- extension WorldClockSelectVC: UISearchResultsUpdating ,UISearchBarDelegate{
- func updateSearchResults(for searchController: UISearchController) {
- // SearchBarに入力したテキストを使って表示データをフィルタリングする。
- searchString = searchController.searchBar.text ?? ""
- if searchString.isEmpty {
- filteredTitles = sections
- } else {
- filteredTitles = sections.map({
- filter in return filter.filter({$0.contains(searchString)})
- }
- )
- }
- tableView.reloadData()
- }
- func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
- delegate.worldClockSelect(cancel: self)
- dismiss(animated: true, completion: nil)
- }
- }
- // MARK: - UITableViewDataSource UITableViewDelegate
- extension WorldClockSelectVC: UITableViewDataSource,UITableViewDelegate {
- func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- return filteredTitles[section].count
- }
- func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
- cell.textLabel?.text = filteredTitles[indexPath.section][indexPath.row]
- return cell
- }
- public func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
- return searchString != "" ? nil : sortedFirstLetters[section]
- }
- func numberOfSections(in tableView: UITableView) -> Int {
- return filteredTitles.count
- }
- public func sectionIndexTitles(for tableView: UITableView) -> [String]? {
- return searchString != "" ? nil : sortedFirstLetters
- }
- public func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
- return UILocalizedIndexedCollation.current().section(forSectionIndexTitle: index)
- }
- func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- searchController.searchBar.resignFirstResponder()
- searchController.dismiss(animated: false)
- delegate.worldClockSelect(selectedWorldClock: self, selected: filteredTitles[indexPath.section][indexPath.row])
- dismiss(animated: true, completion: nil)
- }
- }
参考
UISearchControllerの使い方。主に結果画面からNavigationControllerでPushswift – カスタムモデルクラスを使用して、tableView内のデータをセクションごとにアルファベット順にソートする方法
Replacement of date object with “today” and “yesterday” strings in iphone
0 件のコメント:
コメントを投稿