I think it's easy to use UITableView itself once you get used to it, I think it's a little difficult to create a custom Cell.
This time, I will implement the timeline from 1 in the project I just created.
Also, because I am not good at explaining, the article has become quite long. Therefore, it is divided into 3 articles in total.
It would be helpful if you could let it flow with a light feeling.
The GitHub repository will be ** here **.
The first thing to do **-Define a simple TableView -Create a custom cell -Link TableView and custom cells ** I would like to go.
First, instantiate the UITableView class. Select the size is the full width of the view and the style is plain.
ViewController.swift
let tableView = UITableView(frame: self.view.bounds, style: .plain)
Next, add two protocols.
The protocols to add are UITableViewDelegate
and UITableViewDataSource
.
ViewController.swift
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {・ ・ ・}
If you comply with the two protocols, an error will occur, so fix it. Then the following method will be defined.
ViewController.swift
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
<#code#>
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
<#code#>
}
The first method specifies how many cells to place in the ** section **. The return type is Int type and returns the number of cells.
This time, I tentatively declared an array called item
.
The return value is the number of elements in the array item.
ViewController.swift
let item = ["Cell 1", "Cell 2", "Cell 3", "Cell 4", "Cell 5"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return item.count
}
The second method defines the information when constructing the cell.
Now I want to temporarily add the element of the array item to the textLabel of the cell.
ViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = item[indexPath.row]
return cell
}
I wrote the process in the requested method, The data cannot be reflected as it is.
In viewDidLoad with tableView.delegate = self
Write tableView.dataSource = self
.
By describing this You can delegate the processing of the first compliant protocol to yourself.
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
let tableView = UITableView(frame: self.view.bounds, style: .plain)
tableView.delegate = self
tableView.dataSource = self
}
Finally, write view.addSubview because it needs to be reflected in the view.
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
・ ・ ・
view.addSubview(tableView)
}
At this point, try starting the simulator once.
Then you can see that the items in the array are stored in the cell in order.
This time it's a Twitter timeline, so you need to create a custom cell.
How to make a custom cell You can either ** write it directly in the view controller ** or use ** .xib **.
This time, we will create a custom cell by using the latter .xib method.
I create the file as usual,
Set Subclass to UITableViewCell
and check Also create XIB file.
Then two files will be created.
Place the object in a file with the extension .xib on the left side of the screen, Describe the process in a file with the extension .swift on the right side of the screen.
It's a little rough, but we'll implement the UI. Implemented the icon, name, how many minutes ago the tweet time, the content of the tweet, and the four buttons below.
The processing when pressing the four buttons below is not implemented this time, I would like to implement other parts.
However, I will make it a specification to output with print ()
later so that you can see that it was pressed.
Defined in the newly created class,
awakeFromNib ()
is
Called immediately after being loaded from a Storyboard or nib file.
setSelected (_ selected: Bool, animated: Bool)
is
Performs the state animation processing of the selected state and the normal state.
A method that creates a cell for ViewController.swift
Specifies to generate cells based on this custom cell.
First, set the Identifier
so that you can reference the custom cell.
Select the cell in CustomTableViewCell.xib and the Identifier will be displayed in the editor on the right.
Set any name for this Identifier.
After setting the identifier, write the following in viewDidLoad of ViewController.swift. (It does not have to be described in the absolute viewDidLoad.) Describe the identifier set earlier in forCellReuseIdentifier.
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "customCell")
}
Then modify inside cellForRowAt.
I used to instantiate the UItableViewCell class, Change to refer to customCell.
After as!
, Please use the file name of your custom cell.
ViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomTableViewCell
cell.content.text = self.item[indexPath.row]
return cell
}
So far, the simulator looks like this: You can see that the contents of the custom cell are reflected.
However, if it is left as it is, even if there are many tweets as shown in the image below, all will not be displayed. If it is Twitter, I think that the vertical width will increase according to the content of the tweet.
Next, the height is automatically adjusted. Constraint each object.
Since the height of the label is automatically adjusted, restrictions are placed on the top, bottom, left, and right.
Then change the number of lines in the Label from the default of 1 to 0.
By doing so, the height is automatically adjusted according to the number of characters.
It's getting pretty Twitter-like!
For the rest, I would like to add the following functions. ** ・ Show how many minutes ago you tweeted ・ When each button is pressed, the fact that it was pressed is output to the log. -Added the function to open the details screen of a tweet when you tap it **
First, I would like to implement "** Show how many minutes ago was tweeted **". As an implementation method, I would like to subtract the tweeted time from the current time and put out a few minutes ago.
This time, I will play with the array item a little and explicitly define the time when it was tweeted. Also, I made it possible to store the name as well.
ViewController.swift
var item = [
["content": "2020\n is\n It's over.\n this year too\n good\n one year\It was n.", "date": Date().timeIntervalSince1970 - 313123123, "name": "Saito"],
["content": "Have a nice year.", "date": Date().timeIntervalSince1970 - 123212312, "name": "Honda"],
["content": "Happy New Year.", "date": Date().timeIntervalSince1970 - 20000000, "name": "Suzuki"],
["content": "I will give you 10,000 yen for New Year's gifts.", "date": Date().timeIntervalSince1970 - 2323232, "name": "Kawasaki"],
["content": "I will study harder in 2021.", "date": Date().timeIntervalSince1970 - 13213, "name": "Mitsubishi"],
["content": "This year is a real nuisance, so I'll tighten my mind.", "date": Date().timeIntervalSince1970 - 3333, "name": "Toyota"],
["content": "I look forward to working with you again this year.", "date": Date().timeIntervalSince1970 - 10, "name": "Takeda"]
]
Next, I modified the method for forming cells.
I am getting the current time with let now = Date (). TimeIntervalSince1970
.
let past = item [indexPath.row] ["date "] as! TimeInterval
is
Getting the value of the key value:" date "
of the array at the same number as the row in the cell of the array item.
The part of cell. ***. Text =
is
You are assigning a value to a custom cell property.
In addition, the following is defined in viewDidLoad.
The sequence is reversed in the array with item = item.reversed ()
.
Since the latest contents are added to the end, the order is reversed so that the beginning is the latest.
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
item = item.reversed()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomTableViewCell
let now = Date().timeIntervalSince1970
let past = item[indexPath.row]["date"] as! TimeInterval
cell.time.text = timeCheck(now: now, past: past)
cell.content.text = (item[indexPath.row]["content"] as! String)
cell.name.text = (item[indexPath.row]["name"] as! String)
return cell
}
The timeCheck (now :, past :)
method that appeared in the code above,
It will be the original method I created.
This method specifies the time at the time of posting and the current time as arguments. Calculate how long ago from the difference obtained by subtracting the past time from the current time.
Twitter is expressed abstractly as before. So I made it possible to return with an expression suitable for it.
ViewController.swift
func timeCheck(now: TimeInterval, past: TimeInterval) -> String {
let timeDiff = Int(now - past)
let year = timeDiff / 31104000
let month = timeDiff / 2592000
let day = timeDiff / 86400
let hour = timeDiff / 3600
let minute = timeDiff / 60
let second = timeDiff
if year != 0 {
return "\(year)year ago"
} else if month != 0 {
return "\(month)Months ago"
} else if day != 0 {
return "\(day)A day ago"
} else if hour != 0 {
return "\(hour)by the time"
} else if minute != 0 {
return "\(minute)Minutes ago"
} else {
return "\(second)Seconds ago"
}
}
The simulator looks like this: The height is automatically adjusted, and the time is displayed as ○ hours ago.
Next, we will implement "** When each button is pressed, the fact that it was pressed is output to the log **".
Specify a value for the tag of each button, and make a conditional branch with the tag of which button was pressed.
CustomTableViewController.swift
@IBAction func actionButton(_ sender: Any) {
guard let button = sender as? UIButton else {
return
}
switch button.tag {
case 1:
print("The reply button has been pressed.")
case 2:
print("The retweet button was pressed.")
case 3:
print("The like button has been pressed.")
case 4:
print("The share button has been pressed.")
default:
print("Error:I don't know which button was pressed.")
}
}
The execution result is as follows.
When you press each button, the appropriate log will be output. Now you can implement the process when you press the button!
Next, implement "** Add a function to open the detail screen of the tweet when you tap it **".
The method that detects which cell was tapped when the cell was tapped Do this with didSelectRowAt.
ViewController.swift
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
<#code#>
}
This time I would like to make a screen transition and display the details on a separate screen. First, describe the process to perform screen processing on a separate screen.
Add an object from +
at the top right of the screen.
You can add a new view by searching for ViewController and dragging and dropping.
Next, create a new file.
Select File> New> File> Cocoa Touch Class.
This time, I named it DetailViewController.swift
.
Associate DetailViewController.swift with ViewController. Enter the file name to be linked to the Class part on the upper right of the screen.
Associate NavigationController with ViewController. Select View Controller> Editor> Embed in> Click Navigation Controller
Then the Navigation Controller will be added to the left of the view controller.
Next, link the view controller and Detail view controller. Drag and drop the mark on the left of the view controller while holding down the ** control key **.
Then a menu will appear, so select show
.
It's OK if the two views are connected by an arrow!
Next, when the screen transitions from the view controller, the screen transitions with reference to the identifier, so We will define the identifier of DetailViewController.
Now, let's describe the screen transition in the didSelectRowAt introduced earlier.
The processing of let detailVC = ・ ・ ・
is
It is a process to get DetailViewController from the instance of Storyboard.
I don't know which view controller is the detail view controller, so
The DetailViewController is identified by the (identifier:" detailView ")
part.
navigationController? .PushViewController (detailVC, animated: true)
is
It is a process to perform screen transition. Specify the screen transition destination with the first argument.
tableView.deselectRow (at: indexPath, animated: true)
is
When I tap a cell, the color of that cell changes.
The color is restored after the screen transition.
You can see the difference by trying with and without writing!
ViewController
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let detailVC = storyboard?.instantiateViewController(identifier: "detailView") as! DetailViewController
navigationController?.pushViewController(detailVC, animated: true)
tableView.deselectRow(at: indexPath, animated: true)
}
If you execute the processing up to this point, you can confirm that the screen transition has been completed.
I would like to finish the first one so far.
Since the minimum Twitter implementation is done at this point Please try to make corrections personally from here!
Also, if you have any better code, please point it out.
Thank you for watching until the end.
Click here for more -> [Swift] I implemented a Twitter timeline in UITableView (Part 2)
Recommended Posts