Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
iOS 上 self-sizing cell 的過去、現在、與未來
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Jeff Lin
November 08, 2016
Programming
49
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
iOS 上 self-sizing cell 的過去、現在、與未來
2016 mopcon session
Jeff Lin
November 08, 2016
Other Decks in Programming
See All in Programming
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
970
パーソナライズPodcastを作った話
repunit11
0
140
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
1
2.3k
Everything will be SERVERLESS — 信じて運用した10年の経験値 / Everything Will be Serverless — Lessons Learned from 10 Years of Operational Experience
seike460
PRO
1
990
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
380
設計次第でAIコードの読む量は減らせる / designing-for-code-reading
minodriven
34
16k
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
490
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
370
HTML-in-Canvasで作る未来のWeb UI表現
clockmaker
4
4.7k
JRuby: Past, Present, and Future
headius
0
230
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
210
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
150
Featured
See All Featured
KATA
mclloyd
PRO
35
16k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
2
360
Skip the Path - Find Your Career Trail
mkilby
1
250
Fantastic passwords and where to find them - at NoRuKo
philnash
53
4k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
120
120k
Prompt Engineering for Job Search
mfonobong
0
500
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
930
Technical Leadership for Architectural Decision Making
baasie
3
600
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Mind Mapping
helmedeiros
1
400
Music & Morning Musume
bryan
48
7.4k
How to Think Like a Performance Engineer
csswizardry
28
2.9k
Transcript
iOS Ӥ self-sizing cell ጱ螂݄牏 匍ࣁ牏膏๚㬵 ฏਡ(Jeff Lin)
ፘ橕捍纷 • Yahoo 樄რ樄咳ॺկ AppDevKit - 樄咳ᑃ蜢膏 ۑ胼獤Ձ-ਟப痷(Anistar) • https://github.com/yahoo/AppDevKit
• ᤈᘏ – iOS BDD ᛔ㵕介手礍-磷ܮᄪ(qcl) • https://github.com/qcl/zizhi
About me • YAHOO App Engineer • 㷢膏珶उ牏ೌ搚iOS App樄咳牧ፓ獮揗揣搳ᇔӾஞ •
AppDevKit 樄რ懯向
Agenda • Ջ讕ฎSelf-sizing牫 • ݱ圵Self-sizing薹ဩ膏穉斃 • Xcode 8盅蝽کጱ㺔氂
Self-sizingአࣁߺ牫
ྯ㳷獉裾ଶ犋嘦ਧ
ྯ㳷獉裾ଶ犋嘦ਧ
獉ݢ胼氥纈/褲萢
獉ݢ胼氥纈/褲萢
Expandable cell
㵕眲ਁ羷 • iOS dynamic type • UIFont.preferredFontForTex tStyle:
㵕眲ਁ羷
向ᶎزկ䯤౮ • ਁ牏瑽粙物 • UIImageView, UILabel, UITextView… • Container物 •
UITableView, UICollectionView • 䋿֢物 • storyboard, xib, 纷ୗ嘨䌃constraint
Layout 㻌奈ਁ 瑽ṛ犋段ਁ 瑽ṛ段ਁ
Self-sizingெ讕狶?
ᓒ! • 磧ፗ矑牧֕磪碻玱ᘒݢ犥薹究auto self-sizing蒂ቘ犋㬵ጱ 㺔氂
ெ讕ᓒ牫 • NSString • sizeWithAttributes • boundingRectWithSize:options:attributes:context: • UILabel •
sizeToFit: • UIScrollView/UITextView • contentSize
Ӟ犚ᥝੜஞጱ瑿ො • کጱsizeݢ胼ࢩ傶ੜ碍讨磪藮癩牧አceil()狕ྋ • sizeToFit:䨝ፗ矑硬虋frame牧磪ݢ胼Ꮘ瓥 constraint牧碚蟳ֵአ
UITextView contentSize • sizeForItemAtIndexPath: • ࢧ㯽textView.ContentSize
櫞螇iOS䷱蒂ቘ蝡կԪ?
UITableview self sizing • 磪ݢ胼矦ᤈጱUILabel戔ਧnumberOfLines = 0 • 獵ӥ疰ฎAutoLayoutጱԪԧ self.tableView?.rowHeight
= UITableViewAutomaticDimension self.tableView?.estimatedRowHeight = 100
That’s all!
UITableview self sizing • ฃ䋿֢ • 螕አࢴਧڜ蔭ୗጱlayout
UICollectionView • Grid view, ፘ罏 • ੜܜ粙/य़ܜ粙牧ֵአᘏ ݢ螡䢔layout • 犖ݢ犥螕አෝ礿ڜୗ獉
UICollectionView self-sizing
ෝฎ۱౮ԧAppDevKit • UICollectionViewCell • subclass ADKTableViewDynamicSizeCell/ ADKCollectionViewDynamicSizeCell • 戔অಅ磪嘦ਧጱ璎ፗ constraint
• collectionView:layout:sizeForItemAtIndexPath: • ℂADKNibCacheManager೭ڊcell虻碘ऴ蝱݄ • 㯽獈cell懯ጱय़ੜ牧ᓒڊṛ
AppDevKit Solution
AppDevKit Solution collectionView:layout:sizeForItemAtIndexPath: 1. 叨ኞcellአ㬵ऴ獈虻碘 let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName")
as! String? let cell = ADKSWNibCacheManager.sharedInstance().instance( className: appName?.appending(".\ (SSSmallCardCollectionViewCell.self)")) as! SSSmallCardCollectionViewCell
AppDevKit Solution 2.妔ਧ疝ଶ现ڡྍጱṛଶ牧伛猋盅媲懯ᓒ let preferSize = CGSize.init(width: collectionView.frame.size.width / 2.0
- 10, height: 100.0) cell.frame = CGRect.init(origin: .zero, size: preferSize) 3.ݞlayoutIfNeeded虏constraint咳䠁֢አ cell.contentView.layoutIfNeeded()
AppDevKit Solution 4.秇硈ऴ獈虻碘 func setup(cell: SSSmallCardCollectionViewCell, indexPath: IndexPath) { let
productInfo = self.products[indexPath.row] cell.contentView.layoutIfNeeded() cell.titleLabel?.text = productInfo.productTitle ... }
AppDevKit Solution 5.ᓒڊṛ牦 let size = ADKCellDynamicSizeCalculator.sharedInstance().size (forDynamicHeightCellInstance: cell, preferredSize:
preferSize) return size
Sample Code @objc(collectionView:layout:sizeForItemAtIndexPath:) func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize { // 1. 叨ኞcellአ㬵ऴ獈虻碘 let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String? let cell = ADKSWNibCacheManager.sharedInstance().instance(className: appName?.appending(".\(SSSmallCardCollectionViewCell.self)")) as! SSSmallCardCollectionViewCell // 2. 妔ਧ疝ଶ现ڡྍጱṛଶ牧伛猋盅媲懯ᓒ let preferSize = CGSize.init(width: collectionView.frame.size.width / 2.0 - 10, height: 100.0) cell.frame = CGRect.init(origin: .zero, size: preferSize) // 3.ڥአlayoutIfNeeded虏constraint咳䠁֢አ cell.contentView.layoutIfNeeded() // 4.秇硈ऴ獈虻碘 setup(cell: cell, indexPath: indexPath) // 5.ᓒڊṛ牦 let size = ADKCellDynamicSizeCalculator.sharedInstance().size(forDynamicHeightCellInstance: cell, preferredSize: CGSize.init(width: collectionView.frame.size.width / 2.0 - 10, height: 0.0)) return size }
Recap 1. 叨ኞcellአ㬵ऴ獈虻碘 2. 妔ਧ疝ଶ现ڡྍጱṛଶ牧 伛猋盅媲懯ᓒ 3. ڥአlayoutIfNeeded虏 constraint咳䠁֢አ 4.
秇硈ऴ獈虻碘 5. ᓒڊṛ牦 ImageView Title Description Price
Recap 1. 叨ኞcellአ㬵ऴ獈虻碘 2. 妔ਧ疝ଶ现ڡྍጱṛଶ牧 伛猋盅媲懯ᓒ 3. ڥአlayoutIfNeeded虏 constraint咳䠁֢አ 4.
秇硈ऴ獈虻碘 5. ᓒڊṛ牦 ImageView Title Description Price
Recap 1. 叨ኞcellአ㬵ऴ獈虻碘 2. 妔ਧ疝ଶ现ڡྍጱṛଶ牧 伛猋盅媲懯ᓒ 3. ڥአlayoutIfNeeded虏 constraint咳䠁֢አ 4.
秇硈ऴ獈虻碘 5. ᓒڊṛ牦 ImageView Title Description Price
Recap 1. 叨ኞcellአ㬵ऴ獈虻碘 2. 妔ਧ疝ଶ现ڡྍጱṛଶ牧 伛猋盅媲懯ᓒ 3. ڥአlayoutIfNeeded虏 constraint咳䠁֢አ 4.
秇硈ऴ獈虻碘 5. ᓒڊṛ牦 ImageView Title Description Price ImageView SO NICE᮷䨝 ᮷䨝菠妟೪矑朼 $ 790
ImageView SO NICE᮷䨝 ᮷䨝菠妟೪矑朼 790 Recap 1. 叨ኞcellአ㬵ऴ獈虻碘 2. 妔ਧ疝ଶ现ڡྍጱṛଶ牧
伛猋盅媲懯ᓒ 3. ڥአlayoutIfNeeded虏 constraint咳䠁֢አ 4. 秇硈ऴ獈虻碘 5. ᓒڊṛ牦 ImageView SO NICE᮷䨝 ᮷䨝菠妟೪矑朼 $ 790 SO NICE᮷䨝 菠妟೪矑朼而Ӥ 蔬 ᮷䨝菠妟೪矑朼 而Ӥ蔬 蝚憙櫕 䍅翕菥奋,吖 搡೪矑朼而Ӥ 蔬牐 狐讀ူ讨 玢臺牏缏誢菠妟 蕕觽ᤥ,猻褷碻 牐
AppDevKit Solution ADKCellDynamicSizeCalculator.sharedInsta nce().size(forDynamicHeightCellInstance: cell, preferredSize: CGSize.init(width: collectionView.frame.size.width / 2.0
- 10, height: 0.0)) 磭Ӟ皰ੜܜฎ蓦癷疝ጱӞ牧樌蚣傶10px
How AppDevKit works? • ᛔ㵕懯ᓒ CGSize resultSize = [contentView systemLayoutSizeFittingSize:UILayoutFittingCompr
essedSize]; resultSize.width = preferredSize.width; resultSize.height = MAX(resultSize.height, preferredSize.height); 疝ݢ胼ॡय़ ṛݢ胼襑ᥝ婘ੜ
systemLayoutSizeFittingSize • UILayoutFittingCompressedSize • 礬硁viewጱconstraints礿կᓒڊ螕ݳጱ磧ੜsize • UILayoutFittingExpandedSize • 礬硁viewጱconstraints礿կᓒڊ螕ݳጱ磧य़size
layoutIfNeeds • layoutIfNeeds • 獮کreloadDataਠ౮ጱcontentSize • Animate autoLayout
獮کcontentSize // contentSize: {0, 0} collectionView.dataSource = self.delegator // contentSize:
{0, 0} collectionView.reloadData() // contentSize: {0, 0} collectionView.layoutIfNeeded // contentSize: {375, 2557.5}
layoutIfNeeds-Animation viewForAnimate.someConstraint.constanst = 0.0 UIView.animate(withDuration: 0.3) { viewForAnimate.layoutIfNeeded() } UIView.animate(withDuration:
0.3) { viewForAnimate.frame = CGRect.init(origin: .zero, size: CGSize.init(width: 100, height: 100)) } Frame base layout Constraint Autolayout
櫞螇iOS䷱蒂ቘ蝡կԪ?
ᛔᤈ妔ਧྯ㮆cellጱ疝ṛ • collectionView:layout:sizeForItemAtIndexPath: • Customized UICollectionViewLayout
estimatedItemSize
estimatedItemSize • iOS 8 above • UICollectionViewFlowLayout • estimatedItemSize •
UICollectionViewCell • preferredLayoutAttributesFittingAttributes
estimatedItemSize • 觊犲UITableViewጱestimatedRowHeight • UICollectionViewFlowLayout flowLayout.estimatedItemSize = CGSize.init(width: UIScreen.main.bounds.size.width /
2 - 20, height: 100)
Sample Code func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { self.contentView.layoutIfNeeded()
layoutAttributes.frame.size.height = systemLayoutSizeFitting(UILayoutFittingCompressedSi ze).height layoutAttributes.frame.size.width = self.bounds.size.width return layoutAttributes }
蝽کጱ獋㮆㺔氂 • ᆙclass referenceୌ捍ݞ super.preferredLayoutAttributesFitting(layoutAttributes) • newLayoutAttributes೭کsize 1000x1000 • iOS
10 self.contentView.layoutIfNeeded()
Ӟ犚ݢ犥ኸጱԪ • 戔ਧԧestimatedItemSize疰䨝藉咳cellጱ preferredLayoutAttributesFitting • estimatedItemSize䨝ኼ螂sizeForItemAtIndexPath ጱ奾ຎ
preferredLayoutAttributesFittingA ttributes
preferredLayoutAttributesFittingA ttributes • ݝ磪ਁ᮷অঅጱ • 磪瑽戔ਧṛ犖অঅጱ • 磪瑽+穉ֺ...
ெ讕旰牫 • 毆ض戔অӞ礿瑽粙ṛ constraint • ݢࣁwillDisplayCell֢皨 蝱ᤈ藲碉 • ADKSetConstraintConsta nt:forAttribute:
can help!
螭䷱薹究ጱ㺔氂 • ग़圵cell窾ݳ珌牫֕ estimatedItemSize䌘虡ฎ碉 㮆flowLayout • 螭ฎࢧکአ collectionView:layout:sizeFo rItemAtIndexPath:薹究މ
Expandable cell • 獋圵䋿֢ොୗ • estimatedItemSize+invalidLayout +UIViewAnimation • sizeForCellAtIndexPath+performBatchUpdate:
ੜ奾 • TableView • estimatedRowHeightܨݢ薹究य़蟂獤ጱ制丆 • CollectionView • 㻌Ӟ圵ጱcellአestimatedItemSize螭䄪አ牧݈犋櫞䌃 •
斃֯薹物sizeForItemAtIndexPath牧֕ᥝ臺讨ێ穥 • 螭篷ဩ笕᪃牫ݝ磪Custom flowLayoutԧ • AppDevKit might help for nib!
Xcode 8 & iOS 10
self-sizing in iOS 10 • WWDC 216 What's New in
UICollectionView in iOS 10 • ፓ獮螭手犋ڊྋ嘦ጱֵአොୗ flowLayout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
xib in Xcode 8
xib in Xcode 8 • xibӾزկ磪constraint疰䷱磪frameፘ橕ጱ戔ਧ • init褩ྦྷݢ胼玲ک梊ጱframeጱ独 • Update:Xcode
8.1ےࢧ㬵ԧ
Frame size1000!
xib in Xcode 8 NSLayoutConstraint(item: star, attribute: .height, relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute, multiplier: 0.0, constant: self.frame.height).isActive = true; ᘉ౮ጮ扖物̣ጱṛଶ戔ਧӤ䍅 ጱṛ”独”Ӟ䰬
1000x1000 star!
Solution • ̣ ṛଶፘ缛oṛ䌘Ӥӥ螲ኴ傶0 NSLayoutConstraint(item: star, attribute: .height, relatedBy: .equal,
toItem: self, attribute: .height, multiplier: 1.0, constant: 0.0).isActive = true;
xib戔獋ᤈጱṛଶᤩ㳫ധԧ Xcode 7 Xcode 8
ԧ獋ᤈṛඪ砤 ݈ԧӞ礿constraint...
ྋ嘦ጱ薹究ොဩ • 愆᪃扗磪ጱauto layout constraint戔ਧ • ᓒṛ獮嘦狒contentViewय़ੜྋ嘦ٚ layoutIfNeeded • 螕吚戔ਧpreferredMaxLayoutWidth藉咳矦ᤈ
অৼ犋ᥝ䋊
Ӟ犚狕ྋୌ捍 • 疰吚֢xibӤጱ፡کጱṛጱ犋ਂࣁ • sizeӞፗᓒ梊ጱ扖牧䲒礚ฎ犋ฎԧconstraint • constraint螨عֵአself.frame.sizeጱ独
ԧconstraintࡂ...
Self-sizing checklist • estimatedItemSize • 懿䋿֢cellӾጱ preferredLayoutAttributesFittingAttributes • 嘦ਧ覍self-sizingጱconstraint䷱磪笙ധ
Self-sizing checklist • sizeForItemAtIndexPath: ᓒṛ獮 • 蝚螂虻碘ऴ獈cache cell • 纷ୗ嘨䌃constraintᥝኸframe戔౮毆懯य़ੜ
• 嘦ਧ覍self-sizingጱconstraint䷱磪笙ധ • ADKNibSizeCalculator & ADKCellDynamicSizeCalculator can help!
犥现… • 嘦ਧ覍self-sizingጱconstraint䷱磪笙ധ • 瑽粙ೲ穉ֺ戔ݢ胼蝨౮ጱ㺔氂(ੜܜ) • 螕吚戔ਧpreferredMaxLayoutWidth
Thank you!