implementing UIScrollViewDelegate in a UICollectionView subclass
up vote
1
down vote
favorite
I have a UICollectionView
subclass.
I want to add a default implementation for scrollViewDidScroll
from UIScrollViewDelegate
Is there a way to access the scrollView delegate methods from the UICollectionView
subclass?
Thanks
ios swift uiscrollview uicollectionview
add a comment |
up vote
1
down vote
favorite
I have a UICollectionView
subclass.
I want to add a default implementation for scrollViewDidScroll
from UIScrollViewDelegate
Is there a way to access the scrollView delegate methods from the UICollectionView
subclass?
Thanks
ios swift uiscrollview uicollectionview
I would also like to know
– RX9
Nov 11 at 0:32
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have a UICollectionView
subclass.
I want to add a default implementation for scrollViewDidScroll
from UIScrollViewDelegate
Is there a way to access the scrollView delegate methods from the UICollectionView
subclass?
Thanks
ios swift uiscrollview uicollectionview
I have a UICollectionView
subclass.
I want to add a default implementation for scrollViewDidScroll
from UIScrollViewDelegate
Is there a way to access the scrollView delegate methods from the UICollectionView
subclass?
Thanks
ios swift uiscrollview uicollectionview
ios swift uiscrollview uicollectionview
asked Nov 10 at 23:22
ilan
1,75422151
1,75422151
I would also like to know
– RX9
Nov 11 at 0:32
add a comment |
I would also like to know
– RX9
Nov 11 at 0:32
I would also like to know
– RX9
Nov 11 at 0:32
I would also like to know
– RX9
Nov 11 at 0:32
add a comment |
2 Answers
2
active
oldest
votes
up vote
1
down vote
accepted
You can add a function that implement the default code you need, for example:
class YourCollectionView: UICollectionView {
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: layout)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateUIOnScrollViewDidScroll(_ scrollView: UIScrollView) {
//...
}
}
Then when you implement the delegate functions in your view controller, add:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
yourCollectionView.updateUIOnScrollViewDidScroll(scrollView)
}
EDIT
If you want to use your collection like an external library and you don’t want to call the updated function every time, you can implement a custom class that only conform to the UICollectionViewDelegate (if you want you can have a separated CustomDataSource class too that implement data source and delegate), for example:
class YourCollectionViewDelegate: NSObject, UICollectionViewDelegate {
// implement a callback for every function you need to manage in the view controller
var onSelectedItemAt: ((IndexPath) -> Void)?
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath)
onSelectedItemAt?(indexPath)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard let collectionView = scrollView as? YourCollectionViewClass else { fatalError(“your message”) }
// implement your ui update
}
Then in your view controller you just have to bind the delegate with your view controller:
class MyViewController: UIViewController {
//...
let customDelegate = YourCollectionViewDelegate()
override func viewDidLoad() {
super.viewDidLoad()
//...
myCollection.delegate = customDelegate
setupBindings()
}
private func setupBindings() {
customDelegate.onSelectedItemAt = { [weak self] indexPath in
//...
}
}
Thanks, i have a CollectionView with some functionality that is the same across all the app. I want this to work like an external library.
– ilan
Nov 11 at 0:29
dont want to call the the update function in every viewcontroller that has this collectionview
– ilan
Nov 11 at 0:30
I edited my answer ;) let me know if this can work for you.
– Francesco Deliro
Nov 11 at 10:24
add a comment |
up vote
0
down vote
We can use delegation
concept to get access from CustomCollectionView
whenever user scrolls it.
This is the implementation of CustomCollectionView
also note that the delegate
method is optional
which are available in Objective C
.
So that, if your ViewController
confirms to the CustomCollectionViewDelegate
protocol
then it needs to implement the delegate methods else it have not to.
Note:
However, CustomCollectionView
is a subclass of UICollectionView
means its simple generic UI element. In fact, it is a View
in Model-View-Controller (MVC)
. As per MVC
, View
can not be directly talk to the Controller
, the communication between View
and Controller
is blind & structured
. The good examples of such kind of communication are Target & Action
and delegate
pattern.
The delegate is a simple variable which is contained by the generic UI components like UIScrollView, UITableView, UICollectionView
, etc. The Controller
has to confirms the protocol by setting up the delegate
of the UI element to self
to implement the delegate methods inside it.
The conclusion is the subclass of generic UI element can't implement the delegate methods inside it.
However, we can achieve that by making a customized UIView
with XIB
and add the collectionView
to it.
Code:
CustomCollectionView:
import UIKit
@objc protocol CustomCollectionViewDelegate {
@objc optional func collectionViewDidScroll(_ scrollView: UIScrollView)
}
class CustomCollectionView: UIView {
//MARK: - Outlets
@IBOutlet weak var collection: UICollectionView!
//MARK: - Variables
weak var vc: UIViewController!
weak var view: UIView!
weak var customDelegate: CustomCollectionViewDelegate?
let titles = ["HorizontalCollectionView", "VerticalCollectionView"]
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
init(frame: CGRect, in vc: UIViewController, setCustomDelegate set: Bool) {
super.init(frame: frame)
xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
self.vc = vc
self.customDelegate = set ? vc as? CustomCollectionViewDelegate : nil
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
}
private func xibSetup(frame: CGRect) {
view = loadViewFromNib()
view.frame = frame
addSubview(view)
collection.register(UINib(nibName: "CustomCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CustomCollectionViewCell")
collection.delegate = self
collection.dataSource = self
}
private func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "CustomCollectionView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
extension CustomCollectionView: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if customDelegate != nil {
customDelegate!.collectionViewDidScroll!(scrollView)
}
}
}
extension CustomCollectionView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return titles.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10 // Adjust the inter item space based on the requirement.
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 300, height: collectionView.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCollectionViewCell", for: indexPath) as! CustomCollectionViewCell
cell.titleLabel.text = titles[indexPath.row]
return cell
}
}
CustomCollectionView XIB:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CustomCollectionView" customModule="SampleDemoApp" customModuleProvider="target">
<connections>
<outlet property="collection" destination="loF-CI-n5C" id="EZi-It-39z"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="CustomCollectionView" customModule="SampleDemoApp" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="loF-CI-n5C">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="HQB-uW-7CY">
<size key="itemSize" width="50" height="50"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
</collectionView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="loF-CI-n5C" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Khs-Aw-6b7"/>
<constraint firstItem="loF-CI-n5C" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="cEr-al-Pib"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="loF-CI-n5C" secondAttribute="bottom" id="ftp-QG-OGJ"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="loF-CI-n5C" secondAttribute="trailing" id="num-9n-spN"/>
</constraints>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<point key="canvasLocation" x="138.40000000000001" y="153.37331334332833"/>
</view>
</objects>
</document>
ViewController:
override func viewDidLoad() {
super.viewDidLoad()
let collectionView = CustomCollectionView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 200), in: self, setCustomDelegate: true)
view.addSubview(collectionView)
}
Delegate Implementation:
extension ViewController: CustomCollectionViewDelegate {
func collectionViewDidScroll(_ scrollView: UIScrollView) {
//do something...
}
}
You dont set the UIScrolllViewDelegate so scrollViewDidScroll wont be called
– ilan
Nov 11 at 9:07
Thats my bad. I'm sorry..!! After hitting my head so many times, I came to know that it is impossible to add delegate methods to generic UI elements as per MVC. But can be possible with customizing a UIView. I've updated my answer, please have a look.
– Sateesh
Nov 11 at 13:20
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
You can add a function that implement the default code you need, for example:
class YourCollectionView: UICollectionView {
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: layout)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateUIOnScrollViewDidScroll(_ scrollView: UIScrollView) {
//...
}
}
Then when you implement the delegate functions in your view controller, add:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
yourCollectionView.updateUIOnScrollViewDidScroll(scrollView)
}
EDIT
If you want to use your collection like an external library and you don’t want to call the updated function every time, you can implement a custom class that only conform to the UICollectionViewDelegate (if you want you can have a separated CustomDataSource class too that implement data source and delegate), for example:
class YourCollectionViewDelegate: NSObject, UICollectionViewDelegate {
// implement a callback for every function you need to manage in the view controller
var onSelectedItemAt: ((IndexPath) -> Void)?
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath)
onSelectedItemAt?(indexPath)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard let collectionView = scrollView as? YourCollectionViewClass else { fatalError(“your message”) }
// implement your ui update
}
Then in your view controller you just have to bind the delegate with your view controller:
class MyViewController: UIViewController {
//...
let customDelegate = YourCollectionViewDelegate()
override func viewDidLoad() {
super.viewDidLoad()
//...
myCollection.delegate = customDelegate
setupBindings()
}
private func setupBindings() {
customDelegate.onSelectedItemAt = { [weak self] indexPath in
//...
}
}
Thanks, i have a CollectionView with some functionality that is the same across all the app. I want this to work like an external library.
– ilan
Nov 11 at 0:29
dont want to call the the update function in every viewcontroller that has this collectionview
– ilan
Nov 11 at 0:30
I edited my answer ;) let me know if this can work for you.
– Francesco Deliro
Nov 11 at 10:24
add a comment |
up vote
1
down vote
accepted
You can add a function that implement the default code you need, for example:
class YourCollectionView: UICollectionView {
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: layout)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateUIOnScrollViewDidScroll(_ scrollView: UIScrollView) {
//...
}
}
Then when you implement the delegate functions in your view controller, add:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
yourCollectionView.updateUIOnScrollViewDidScroll(scrollView)
}
EDIT
If you want to use your collection like an external library and you don’t want to call the updated function every time, you can implement a custom class that only conform to the UICollectionViewDelegate (if you want you can have a separated CustomDataSource class too that implement data source and delegate), for example:
class YourCollectionViewDelegate: NSObject, UICollectionViewDelegate {
// implement a callback for every function you need to manage in the view controller
var onSelectedItemAt: ((IndexPath) -> Void)?
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath)
onSelectedItemAt?(indexPath)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard let collectionView = scrollView as? YourCollectionViewClass else { fatalError(“your message”) }
// implement your ui update
}
Then in your view controller you just have to bind the delegate with your view controller:
class MyViewController: UIViewController {
//...
let customDelegate = YourCollectionViewDelegate()
override func viewDidLoad() {
super.viewDidLoad()
//...
myCollection.delegate = customDelegate
setupBindings()
}
private func setupBindings() {
customDelegate.onSelectedItemAt = { [weak self] indexPath in
//...
}
}
Thanks, i have a CollectionView with some functionality that is the same across all the app. I want this to work like an external library.
– ilan
Nov 11 at 0:29
dont want to call the the update function in every viewcontroller that has this collectionview
– ilan
Nov 11 at 0:30
I edited my answer ;) let me know if this can work for you.
– Francesco Deliro
Nov 11 at 10:24
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
You can add a function that implement the default code you need, for example:
class YourCollectionView: UICollectionView {
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: layout)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateUIOnScrollViewDidScroll(_ scrollView: UIScrollView) {
//...
}
}
Then when you implement the delegate functions in your view controller, add:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
yourCollectionView.updateUIOnScrollViewDidScroll(scrollView)
}
EDIT
If you want to use your collection like an external library and you don’t want to call the updated function every time, you can implement a custom class that only conform to the UICollectionViewDelegate (if you want you can have a separated CustomDataSource class too that implement data source and delegate), for example:
class YourCollectionViewDelegate: NSObject, UICollectionViewDelegate {
// implement a callback for every function you need to manage in the view controller
var onSelectedItemAt: ((IndexPath) -> Void)?
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath)
onSelectedItemAt?(indexPath)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard let collectionView = scrollView as? YourCollectionViewClass else { fatalError(“your message”) }
// implement your ui update
}
Then in your view controller you just have to bind the delegate with your view controller:
class MyViewController: UIViewController {
//...
let customDelegate = YourCollectionViewDelegate()
override func viewDidLoad() {
super.viewDidLoad()
//...
myCollection.delegate = customDelegate
setupBindings()
}
private func setupBindings() {
customDelegate.onSelectedItemAt = { [weak self] indexPath in
//...
}
}
You can add a function that implement the default code you need, for example:
class YourCollectionView: UICollectionView {
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: layout)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateUIOnScrollViewDidScroll(_ scrollView: UIScrollView) {
//...
}
}
Then when you implement the delegate functions in your view controller, add:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
yourCollectionView.updateUIOnScrollViewDidScroll(scrollView)
}
EDIT
If you want to use your collection like an external library and you don’t want to call the updated function every time, you can implement a custom class that only conform to the UICollectionViewDelegate (if you want you can have a separated CustomDataSource class too that implement data source and delegate), for example:
class YourCollectionViewDelegate: NSObject, UICollectionViewDelegate {
// implement a callback for every function you need to manage in the view controller
var onSelectedItemAt: ((IndexPath) -> Void)?
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath)
onSelectedItemAt?(indexPath)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard let collectionView = scrollView as? YourCollectionViewClass else { fatalError(“your message”) }
// implement your ui update
}
Then in your view controller you just have to bind the delegate with your view controller:
class MyViewController: UIViewController {
//...
let customDelegate = YourCollectionViewDelegate()
override func viewDidLoad() {
super.viewDidLoad()
//...
myCollection.delegate = customDelegate
setupBindings()
}
private func setupBindings() {
customDelegate.onSelectedItemAt = { [weak self] indexPath in
//...
}
}
edited Nov 11 at 12:29
answered Nov 11 at 0:15
Francesco Deliro
2,3992716
2,3992716
Thanks, i have a CollectionView with some functionality that is the same across all the app. I want this to work like an external library.
– ilan
Nov 11 at 0:29
dont want to call the the update function in every viewcontroller that has this collectionview
– ilan
Nov 11 at 0:30
I edited my answer ;) let me know if this can work for you.
– Francesco Deliro
Nov 11 at 10:24
add a comment |
Thanks, i have a CollectionView with some functionality that is the same across all the app. I want this to work like an external library.
– ilan
Nov 11 at 0:29
dont want to call the the update function in every viewcontroller that has this collectionview
– ilan
Nov 11 at 0:30
I edited my answer ;) let me know if this can work for you.
– Francesco Deliro
Nov 11 at 10:24
Thanks, i have a CollectionView with some functionality that is the same across all the app. I want this to work like an external library.
– ilan
Nov 11 at 0:29
Thanks, i have a CollectionView with some functionality that is the same across all the app. I want this to work like an external library.
– ilan
Nov 11 at 0:29
dont want to call the the update function in every viewcontroller that has this collectionview
– ilan
Nov 11 at 0:30
dont want to call the the update function in every viewcontroller that has this collectionview
– ilan
Nov 11 at 0:30
I edited my answer ;) let me know if this can work for you.
– Francesco Deliro
Nov 11 at 10:24
I edited my answer ;) let me know if this can work for you.
– Francesco Deliro
Nov 11 at 10:24
add a comment |
up vote
0
down vote
We can use delegation
concept to get access from CustomCollectionView
whenever user scrolls it.
This is the implementation of CustomCollectionView
also note that the delegate
method is optional
which are available in Objective C
.
So that, if your ViewController
confirms to the CustomCollectionViewDelegate
protocol
then it needs to implement the delegate methods else it have not to.
Note:
However, CustomCollectionView
is a subclass of UICollectionView
means its simple generic UI element. In fact, it is a View
in Model-View-Controller (MVC)
. As per MVC
, View
can not be directly talk to the Controller
, the communication between View
and Controller
is blind & structured
. The good examples of such kind of communication are Target & Action
and delegate
pattern.
The delegate is a simple variable which is contained by the generic UI components like UIScrollView, UITableView, UICollectionView
, etc. The Controller
has to confirms the protocol by setting up the delegate
of the UI element to self
to implement the delegate methods inside it.
The conclusion is the subclass of generic UI element can't implement the delegate methods inside it.
However, we can achieve that by making a customized UIView
with XIB
and add the collectionView
to it.
Code:
CustomCollectionView:
import UIKit
@objc protocol CustomCollectionViewDelegate {
@objc optional func collectionViewDidScroll(_ scrollView: UIScrollView)
}
class CustomCollectionView: UIView {
//MARK: - Outlets
@IBOutlet weak var collection: UICollectionView!
//MARK: - Variables
weak var vc: UIViewController!
weak var view: UIView!
weak var customDelegate: CustomCollectionViewDelegate?
let titles = ["HorizontalCollectionView", "VerticalCollectionView"]
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
init(frame: CGRect, in vc: UIViewController, setCustomDelegate set: Bool) {
super.init(frame: frame)
xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
self.vc = vc
self.customDelegate = set ? vc as? CustomCollectionViewDelegate : nil
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
}
private func xibSetup(frame: CGRect) {
view = loadViewFromNib()
view.frame = frame
addSubview(view)
collection.register(UINib(nibName: "CustomCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CustomCollectionViewCell")
collection.delegate = self
collection.dataSource = self
}
private func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "CustomCollectionView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
extension CustomCollectionView: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if customDelegate != nil {
customDelegate!.collectionViewDidScroll!(scrollView)
}
}
}
extension CustomCollectionView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return titles.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10 // Adjust the inter item space based on the requirement.
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 300, height: collectionView.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCollectionViewCell", for: indexPath) as! CustomCollectionViewCell
cell.titleLabel.text = titles[indexPath.row]
return cell
}
}
CustomCollectionView XIB:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CustomCollectionView" customModule="SampleDemoApp" customModuleProvider="target">
<connections>
<outlet property="collection" destination="loF-CI-n5C" id="EZi-It-39z"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="CustomCollectionView" customModule="SampleDemoApp" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="loF-CI-n5C">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="HQB-uW-7CY">
<size key="itemSize" width="50" height="50"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
</collectionView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="loF-CI-n5C" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Khs-Aw-6b7"/>
<constraint firstItem="loF-CI-n5C" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="cEr-al-Pib"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="loF-CI-n5C" secondAttribute="bottom" id="ftp-QG-OGJ"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="loF-CI-n5C" secondAttribute="trailing" id="num-9n-spN"/>
</constraints>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<point key="canvasLocation" x="138.40000000000001" y="153.37331334332833"/>
</view>
</objects>
</document>
ViewController:
override func viewDidLoad() {
super.viewDidLoad()
let collectionView = CustomCollectionView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 200), in: self, setCustomDelegate: true)
view.addSubview(collectionView)
}
Delegate Implementation:
extension ViewController: CustomCollectionViewDelegate {
func collectionViewDidScroll(_ scrollView: UIScrollView) {
//do something...
}
}
You dont set the UIScrolllViewDelegate so scrollViewDidScroll wont be called
– ilan
Nov 11 at 9:07
Thats my bad. I'm sorry..!! After hitting my head so many times, I came to know that it is impossible to add delegate methods to generic UI elements as per MVC. But can be possible with customizing a UIView. I've updated my answer, please have a look.
– Sateesh
Nov 11 at 13:20
add a comment |
up vote
0
down vote
We can use delegation
concept to get access from CustomCollectionView
whenever user scrolls it.
This is the implementation of CustomCollectionView
also note that the delegate
method is optional
which are available in Objective C
.
So that, if your ViewController
confirms to the CustomCollectionViewDelegate
protocol
then it needs to implement the delegate methods else it have not to.
Note:
However, CustomCollectionView
is a subclass of UICollectionView
means its simple generic UI element. In fact, it is a View
in Model-View-Controller (MVC)
. As per MVC
, View
can not be directly talk to the Controller
, the communication between View
and Controller
is blind & structured
. The good examples of such kind of communication are Target & Action
and delegate
pattern.
The delegate is a simple variable which is contained by the generic UI components like UIScrollView, UITableView, UICollectionView
, etc. The Controller
has to confirms the protocol by setting up the delegate
of the UI element to self
to implement the delegate methods inside it.
The conclusion is the subclass of generic UI element can't implement the delegate methods inside it.
However, we can achieve that by making a customized UIView
with XIB
and add the collectionView
to it.
Code:
CustomCollectionView:
import UIKit
@objc protocol CustomCollectionViewDelegate {
@objc optional func collectionViewDidScroll(_ scrollView: UIScrollView)
}
class CustomCollectionView: UIView {
//MARK: - Outlets
@IBOutlet weak var collection: UICollectionView!
//MARK: - Variables
weak var vc: UIViewController!
weak var view: UIView!
weak var customDelegate: CustomCollectionViewDelegate?
let titles = ["HorizontalCollectionView", "VerticalCollectionView"]
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
init(frame: CGRect, in vc: UIViewController, setCustomDelegate set: Bool) {
super.init(frame: frame)
xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
self.vc = vc
self.customDelegate = set ? vc as? CustomCollectionViewDelegate : nil
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
}
private func xibSetup(frame: CGRect) {
view = loadViewFromNib()
view.frame = frame
addSubview(view)
collection.register(UINib(nibName: "CustomCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CustomCollectionViewCell")
collection.delegate = self
collection.dataSource = self
}
private func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "CustomCollectionView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
extension CustomCollectionView: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if customDelegate != nil {
customDelegate!.collectionViewDidScroll!(scrollView)
}
}
}
extension CustomCollectionView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return titles.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10 // Adjust the inter item space based on the requirement.
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 300, height: collectionView.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCollectionViewCell", for: indexPath) as! CustomCollectionViewCell
cell.titleLabel.text = titles[indexPath.row]
return cell
}
}
CustomCollectionView XIB:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CustomCollectionView" customModule="SampleDemoApp" customModuleProvider="target">
<connections>
<outlet property="collection" destination="loF-CI-n5C" id="EZi-It-39z"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="CustomCollectionView" customModule="SampleDemoApp" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="loF-CI-n5C">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="HQB-uW-7CY">
<size key="itemSize" width="50" height="50"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
</collectionView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="loF-CI-n5C" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Khs-Aw-6b7"/>
<constraint firstItem="loF-CI-n5C" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="cEr-al-Pib"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="loF-CI-n5C" secondAttribute="bottom" id="ftp-QG-OGJ"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="loF-CI-n5C" secondAttribute="trailing" id="num-9n-spN"/>
</constraints>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<point key="canvasLocation" x="138.40000000000001" y="153.37331334332833"/>
</view>
</objects>
</document>
ViewController:
override func viewDidLoad() {
super.viewDidLoad()
let collectionView = CustomCollectionView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 200), in: self, setCustomDelegate: true)
view.addSubview(collectionView)
}
Delegate Implementation:
extension ViewController: CustomCollectionViewDelegate {
func collectionViewDidScroll(_ scrollView: UIScrollView) {
//do something...
}
}
You dont set the UIScrolllViewDelegate so scrollViewDidScroll wont be called
– ilan
Nov 11 at 9:07
Thats my bad. I'm sorry..!! After hitting my head so many times, I came to know that it is impossible to add delegate methods to generic UI elements as per MVC. But can be possible with customizing a UIView. I've updated my answer, please have a look.
– Sateesh
Nov 11 at 13:20
add a comment |
up vote
0
down vote
up vote
0
down vote
We can use delegation
concept to get access from CustomCollectionView
whenever user scrolls it.
This is the implementation of CustomCollectionView
also note that the delegate
method is optional
which are available in Objective C
.
So that, if your ViewController
confirms to the CustomCollectionViewDelegate
protocol
then it needs to implement the delegate methods else it have not to.
Note:
However, CustomCollectionView
is a subclass of UICollectionView
means its simple generic UI element. In fact, it is a View
in Model-View-Controller (MVC)
. As per MVC
, View
can not be directly talk to the Controller
, the communication between View
and Controller
is blind & structured
. The good examples of such kind of communication are Target & Action
and delegate
pattern.
The delegate is a simple variable which is contained by the generic UI components like UIScrollView, UITableView, UICollectionView
, etc. The Controller
has to confirms the protocol by setting up the delegate
of the UI element to self
to implement the delegate methods inside it.
The conclusion is the subclass of generic UI element can't implement the delegate methods inside it.
However, we can achieve that by making a customized UIView
with XIB
and add the collectionView
to it.
Code:
CustomCollectionView:
import UIKit
@objc protocol CustomCollectionViewDelegate {
@objc optional func collectionViewDidScroll(_ scrollView: UIScrollView)
}
class CustomCollectionView: UIView {
//MARK: - Outlets
@IBOutlet weak var collection: UICollectionView!
//MARK: - Variables
weak var vc: UIViewController!
weak var view: UIView!
weak var customDelegate: CustomCollectionViewDelegate?
let titles = ["HorizontalCollectionView", "VerticalCollectionView"]
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
init(frame: CGRect, in vc: UIViewController, setCustomDelegate set: Bool) {
super.init(frame: frame)
xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
self.vc = vc
self.customDelegate = set ? vc as? CustomCollectionViewDelegate : nil
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
}
private func xibSetup(frame: CGRect) {
view = loadViewFromNib()
view.frame = frame
addSubview(view)
collection.register(UINib(nibName: "CustomCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CustomCollectionViewCell")
collection.delegate = self
collection.dataSource = self
}
private func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "CustomCollectionView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
extension CustomCollectionView: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if customDelegate != nil {
customDelegate!.collectionViewDidScroll!(scrollView)
}
}
}
extension CustomCollectionView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return titles.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10 // Adjust the inter item space based on the requirement.
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 300, height: collectionView.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCollectionViewCell", for: indexPath) as! CustomCollectionViewCell
cell.titleLabel.text = titles[indexPath.row]
return cell
}
}
CustomCollectionView XIB:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CustomCollectionView" customModule="SampleDemoApp" customModuleProvider="target">
<connections>
<outlet property="collection" destination="loF-CI-n5C" id="EZi-It-39z"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="CustomCollectionView" customModule="SampleDemoApp" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="loF-CI-n5C">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="HQB-uW-7CY">
<size key="itemSize" width="50" height="50"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
</collectionView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="loF-CI-n5C" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Khs-Aw-6b7"/>
<constraint firstItem="loF-CI-n5C" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="cEr-al-Pib"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="loF-CI-n5C" secondAttribute="bottom" id="ftp-QG-OGJ"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="loF-CI-n5C" secondAttribute="trailing" id="num-9n-spN"/>
</constraints>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<point key="canvasLocation" x="138.40000000000001" y="153.37331334332833"/>
</view>
</objects>
</document>
ViewController:
override func viewDidLoad() {
super.viewDidLoad()
let collectionView = CustomCollectionView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 200), in: self, setCustomDelegate: true)
view.addSubview(collectionView)
}
Delegate Implementation:
extension ViewController: CustomCollectionViewDelegate {
func collectionViewDidScroll(_ scrollView: UIScrollView) {
//do something...
}
}
We can use delegation
concept to get access from CustomCollectionView
whenever user scrolls it.
This is the implementation of CustomCollectionView
also note that the delegate
method is optional
which are available in Objective C
.
So that, if your ViewController
confirms to the CustomCollectionViewDelegate
protocol
then it needs to implement the delegate methods else it have not to.
Note:
However, CustomCollectionView
is a subclass of UICollectionView
means its simple generic UI element. In fact, it is a View
in Model-View-Controller (MVC)
. As per MVC
, View
can not be directly talk to the Controller
, the communication between View
and Controller
is blind & structured
. The good examples of such kind of communication are Target & Action
and delegate
pattern.
The delegate is a simple variable which is contained by the generic UI components like UIScrollView, UITableView, UICollectionView
, etc. The Controller
has to confirms the protocol by setting up the delegate
of the UI element to self
to implement the delegate methods inside it.
The conclusion is the subclass of generic UI element can't implement the delegate methods inside it.
However, we can achieve that by making a customized UIView
with XIB
and add the collectionView
to it.
Code:
CustomCollectionView:
import UIKit
@objc protocol CustomCollectionViewDelegate {
@objc optional func collectionViewDidScroll(_ scrollView: UIScrollView)
}
class CustomCollectionView: UIView {
//MARK: - Outlets
@IBOutlet weak var collection: UICollectionView!
//MARK: - Variables
weak var vc: UIViewController!
weak var view: UIView!
weak var customDelegate: CustomCollectionViewDelegate?
let titles = ["HorizontalCollectionView", "VerticalCollectionView"]
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
init(frame: CGRect, in vc: UIViewController, setCustomDelegate set: Bool) {
super.init(frame: frame)
xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
self.vc = vc
self.customDelegate = set ? vc as? CustomCollectionViewDelegate : nil
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
}
private func xibSetup(frame: CGRect) {
view = loadViewFromNib()
view.frame = frame
addSubview(view)
collection.register(UINib(nibName: "CustomCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CustomCollectionViewCell")
collection.delegate = self
collection.dataSource = self
}
private func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "CustomCollectionView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
extension CustomCollectionView: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if customDelegate != nil {
customDelegate!.collectionViewDidScroll!(scrollView)
}
}
}
extension CustomCollectionView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return titles.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10 // Adjust the inter item space based on the requirement.
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 300, height: collectionView.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCollectionViewCell", for: indexPath) as! CustomCollectionViewCell
cell.titleLabel.text = titles[indexPath.row]
return cell
}
}
CustomCollectionView XIB:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CustomCollectionView" customModule="SampleDemoApp" customModuleProvider="target">
<connections>
<outlet property="collection" destination="loF-CI-n5C" id="EZi-It-39z"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="CustomCollectionView" customModule="SampleDemoApp" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="loF-CI-n5C">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="HQB-uW-7CY">
<size key="itemSize" width="50" height="50"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
</collectionView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="loF-CI-n5C" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Khs-Aw-6b7"/>
<constraint firstItem="loF-CI-n5C" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="cEr-al-Pib"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="loF-CI-n5C" secondAttribute="bottom" id="ftp-QG-OGJ"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="loF-CI-n5C" secondAttribute="trailing" id="num-9n-spN"/>
</constraints>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<point key="canvasLocation" x="138.40000000000001" y="153.37331334332833"/>
</view>
</objects>
</document>
ViewController:
override func viewDidLoad() {
super.viewDidLoad()
let collectionView = CustomCollectionView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 200), in: self, setCustomDelegate: true)
view.addSubview(collectionView)
}
Delegate Implementation:
extension ViewController: CustomCollectionViewDelegate {
func collectionViewDidScroll(_ scrollView: UIScrollView) {
//do something...
}
}
edited Nov 11 at 13:16
answered Nov 11 at 8:25
Sateesh
1,354615
1,354615
You dont set the UIScrolllViewDelegate so scrollViewDidScroll wont be called
– ilan
Nov 11 at 9:07
Thats my bad. I'm sorry..!! After hitting my head so many times, I came to know that it is impossible to add delegate methods to generic UI elements as per MVC. But can be possible with customizing a UIView. I've updated my answer, please have a look.
– Sateesh
Nov 11 at 13:20
add a comment |
You dont set the UIScrolllViewDelegate so scrollViewDidScroll wont be called
– ilan
Nov 11 at 9:07
Thats my bad. I'm sorry..!! After hitting my head so many times, I came to know that it is impossible to add delegate methods to generic UI elements as per MVC. But can be possible with customizing a UIView. I've updated my answer, please have a look.
– Sateesh
Nov 11 at 13:20
You dont set the UIScrolllViewDelegate so scrollViewDidScroll wont be called
– ilan
Nov 11 at 9:07
You dont set the UIScrolllViewDelegate so scrollViewDidScroll wont be called
– ilan
Nov 11 at 9:07
Thats my bad. I'm sorry..!! After hitting my head so many times, I came to know that it is impossible to add delegate methods to generic UI elements as per MVC. But can be possible with customizing a UIView. I've updated my answer, please have a look.
– Sateesh
Nov 11 at 13:20
Thats my bad. I'm sorry..!! After hitting my head so many times, I came to know that it is impossible to add delegate methods to generic UI elements as per MVC. But can be possible with customizing a UIView. I've updated my answer, please have a look.
– Sateesh
Nov 11 at 13:20
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244392%2fimplementing-uiscrollviewdelegate-in-a-uicollectionview-subclass%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I would also like to know
– RX9
Nov 11 at 0:32