I was trying to deep dive into how the UITableView works internally. I've already read multiple posts regarding that like,
https://www.mikeash.com/pyblog/friday-qa-2013-02-22-lets-build-uitableview.html
I want to know if there is any way we can look into the content of the reusable pool, i.e. how many and what all UITableViewCell types are available inside it at a moment.
I already know that we'll have the cells as per the screen size and the cell height. But I'm trying to figure out what happens if the tableView accepts different types of cells at different indexPaths.
Well, you can dig down into the objects in debug...
I set a breakpoint in didSelectRowAt and looked into the Variables View pane:
I had one row (index path [0,3] that used TestCellB and 90 rows that used TestCell, and the table was scrolled to row 21 (so row [0,3] was well off-screen.
As you can see, there is an internal Dictionary named _reusableTableCells which, in my example, currently contains 1 TestCellB and 2 TestCells.
EDIT
I just gave this a try - might give you some additional info:
var reusableCells = tableView.value(forKey: "_reusableTableCells")
print(reusableCells)
Output:
Optional({
TestCellB = (
"<TranslateTest.TestCellB: 0x7f87b206aa00; baseClass = UITableViewCell; frame = (0 1612; 414 37); clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003a66380>>"
);
TestCellC = (
"<TranslateTest.TestCellC: 0x7f87b2894800; baseClass = UITableViewCell; frame = (0 205; 414 93); clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003a586e0>>",
"<TranslateTest.TestCellC: 0x7f87b3000e00; baseClass = UITableViewCell; frame = (0 298; 414 93); clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x600003a5fe40>>"
);
})
Related
I have implement inline style date picker in iOS 14. I want to disable to open keyboard when focus on time picker.
inline style date picker:
Please help me as soon as possible.
If you show both of date and time but don't let the user change it, why you don't only show the date (and then add the custom date as another view).
If you still keep the datePickerMode is dateAndTime, I can only help you disable the time view (the date view can be select normally). You can do something like this (code in Swift)
datePicker.subviews[0].subviews[0].subviews[2].isUserInteractionEnabled = false
But don't forget to check each subviews exit or not.
Below is information of the subview
// datePicker.subviews[0]
datePicker.subviews[0].subviews[0].subviews[2].isUserInteractionEnabled = false
// datePicker.subviews[0].subviews[0]
<_UIDatePickerCalendarContentStackView: 0x7fb9af50c3e0; frame = (2 52; 316 295.667); clipsToBounds = YES; layer = <CALayer: 0x60000052bfe0>>
// datePicker.subviews[0].subviews[0].subviews
3 elements
- 0 : <_UIDatePickerCalendarHeaderView: 0x7fb9af50cd70; frame = (0 0; 316 0); layer = <CALayer: 0x6000005483c0>>
- 1 : <_UIDatePickerCalendarDateView: 0x7fb9b1815370; frame = (0 0; 316 283.667); layer = <CALayer: 0x60000054ea00>>
- 2 : <_UIDatePickerCalendarTimeView: 0x7fb9b181c800; frame = (0 283.667; 316 12); userInteractionEnabled = NO; layer = <CALayer: 0x600000540660>>
You could remove the tap gesture recognizer that is making the keyboard appear. It worked for me. Here is how to do it for a view that contains a property datePicker: UIDatePicker
override func didMoveToWindow() {
super.didMoveToWindow()
guard let stackView = datePicker?.subviews.first?.subviews.first as? UIStackView,
let bottomCalendarView = stackView.arrangedSubviews.last,
let timeLabel = bottomCalendarView.subviews.first,
let tapGesture = timeLabel.gestureRecognizers?.first else { return }
timeLabel.removeGestureRecognizer(tapGesture)
}
I found this good link how to get selected images.
I am trying to set image that I get from extension context to image view that I placed in storyboard.
this my print out code po self.theImageView:
<UIImageView: 0x7b8a1c90; frame = (240 89; 52 41); opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x7b887fa0>> - (null)
and this is po self.theImageView.image
<UIImage: 0x7a6977f0>
So I even can see image using eye tool when debug it:
But on the screen of my simulator there is no visible image.
I get this when using the Xcode debugging console with this line:
po [[UIWindow keyWindow] recursiveDescription]
Then I get back lines with the recursive description like this
<UILabel: 0xb0b8170; frame = (138 106; 200 15); text = 'Distance'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0xb0b8220>>
What does "autoresize = RM+BM" and is there a place I can lookup the meaning of the letters? I also saw something like this "autoresize = LM+W+RM+TM+H+BM".
autoresize indicates which bits have been set in the autoresizingMask:
RM = UIAutoresizingFlexibleRightMargin
BM = UIAutoresizingFlexibleBottomMargin
The others follow a similar abbreviation syntax.
If you give all the constraints, then you can easily see all of them. These all indicates the UIAutoResizing.
RM means Right margin
BM means Bottom margin
W means Width
H means Height
LM means Left margin
TM means Top margin
<SIGMAPOINT_MPAdView: 0x10db888a0; frame = (0 0; 320 50); clipsToBounds = YES; autoresize = LM+RM; layer = <CALayer: 0x282b704c0>>
recently, I am making a custom UITableViewCell with animatable UIImageView to play animated GIF. During making it, I found that an animation is not shown after the cell was reused.
It seems that UIImageView is affected by [self prepareForReuse]. When I did debugging it, I could get the following information.
** before calling [super prepareForReuse] **
(lldb) po self.testImageView
<UIImageView: 0x1ab681c0; frame = (39 0; 78 61); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; animations = { UIImageAnimation=<CAKeyframeAnimation: 0x1ab77870>; }; layer = <CALayer: 0x1ab68b60>> - (null)
** after calling [super prepareForReuse] **
(lldb) n
(lldb) po self.testImageView
<UIImageView: 0x1ab681c0; frame = (39 0; 78 61); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x1ab68b60>> - (null)
As it show, "animations = { UIImageAnimation=; };" is removed.
Fortunately, I could work around that problem by making a new instance of UIImage and setting it to UIImageView again as a workaround. For doing this workaround, it's important to re-create an instance of UIImage not to reuse an instance which is already set to UIImageView.
Anyway, what I really want to know is why prepareForReuse method removes the information about an animation.
Please let me know an internal reuse logic of the method which is hidden.
Upon calling [super prepareForReuse], stopAnimation is called on self.testImageView. I think this is the right logic being used so that the cell can be reused. You just need to call the [self.testImageView startAnimation] method once the cell is prepared for reuse. You need not resort to the "workaround" method that you have mentioned.
Found a solution. I had to set the UIImageView's image property to nil in prepareForReuse(), before setting a new (or even the same) animated UIImage.
I am building a TTTableViewController subclass based on Three20 TTCatalog sample. In there they have defined a subclass of TTTableViewController which has search functionality, called SearchTextController, and it has a search bar appear in the table view header.
Here's what their loadView method looks like:
- (void)loadView {
[super loadView];
TTTableViewController* searchController = [[[TTTableViewController alloc] init] autorelease];
searchController.dataSource = [[[MockSearchDataSource alloc] initWithDuration:1.5] autorelease];
self.searchViewController = searchController;
self.tableView.tableHeaderView = _searchController.searchBar;
}
I tried to re implement the same kind of functionality in my own subclass of TTTableView. The problem is that I cannot get the search bar to appear.
Running these in loadView of TTCatalog SearchTestController (after the last line)
NSLog(#"_searchController.searchBar address %#",_searchController.searchBar.description);
NSLog(#"self.tableView.tableHeaderView address %#",self.tableView.tableHeaderView.description);
yields the same memory address for the layer (meaning the view got set correctly)
2012-07-03 12:00:02.326 TTCatalog[53493:f803] _searchController.searchBar address <UISearchBar: 0x6a5c940; frame = (0 0; 320 44); layer = <CALayer: 0x6a5ca40>>
2012-07-03 12:00:02.327 TTCatalog[53493:f803] self.tableView.tableHeaderView address <UISearchBar: 0x6a5c940; frame = (0 0; 320 44); layer = <CALayer: 0x6a5ca40>>
When I run the same NSLogs in my app, I get this:
2012-07-03 11:41:54.900 myApp[51991:f803] _searchController.searchBar address <UISearchBar: 0x6a43c20; frame = (0 0; 320 44); layer = <CALayer: 0x6a43ce0>>
2012-07-03 11:41:54.901 myApp[51991:f803] self.tableView.tableHeaderView address <UISearchBar: 0x6a43c20; frame = (0 0; 320 44); layer = <CALayer: 0x6a43ce0>>
The layers have the same memory address in my app as well, but the search bar is not visible in the table view header. Is there something else I am missing here?