├── DynamicCell.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcuserdata
│ └── mohannad.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
├── DynamicCell.xcworkspace
├── contents.xcworkspacedata
├── xcshareddata
│ └── IDEWorkspaceChecks.plist
└── xcuserdata
│ └── mohannad.xcuserdatad
│ └── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
├── DynamicCell
├── Controllers
│ ├── CommentsController.swift
│ ├── FeedsController.swift
│ └── MainController.swift
├── Info.plist
├── Models
│ ├── Comment.swift
│ └── Photo.swift
├── Others
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── 90.imageset
│ │ │ ├── 90.jpeg
│ │ │ └── Contents.json
│ │ ├── 91.imageset
│ │ │ ├── 91.jpeg
│ │ │ └── Contents.json
│ │ ├── 92.imageset
│ │ │ ├── 92.jpeg
│ │ │ └── Contents.json
│ │ ├── 93.imageset
│ │ │ ├── 99.jpeg
│ │ │ └── Contents.json
│ │ ├── 94.imageset
│ │ │ ├── 94.jpeg
│ │ │ └── Contents.json
│ │ ├── 95.imageset
│ │ │ ├── 95.jpeg
│ │ │ └── Contents.json
│ │ ├── 96.imageset
│ │ │ ├── 96.jpeg
│ │ │ └── Contents.json
│ │ ├── 97.imageset
│ │ │ ├── 97.jpeg
│ │ │ └── Contents.json
│ │ ├── 98.imageset
│ │ │ ├── 98.jpeg
│ │ │ └── Contents.json
│ │ ├── 99.imageset
│ │ │ ├── 93.jpeg
│ │ │ └── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ └── SceneDelegate.swift
├── Utilities
│ ├── ApiService.swift
│ ├── CommentFlowLayout.swift
│ ├── Constants.swift
│ ├── Extentions.swift
│ └── PinterestLayout.swift
└── Views
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Comments.storyboard
│ ├── CustomCells
│ ├── CommentCell.swift
│ └── FeedCell.swift
│ └── Feeds.storyboard
├── DynamicCellTests
├── DynamicCellTests.swift
└── Info.plist
├── DynamicCellUITests
├── DynamicCellUITests.swift
└── Info.plist
├── Podfile
├── Podfile.lock
├── Pods
├── Fakery
│ ├── LICENSE.md
│ ├── README.md
│ ├── README.md.orig
│ └── Sources
│ │ └── Fakery
│ │ ├── Config.swift
│ │ ├── Data
│ │ ├── Parser.swift
│ │ └── Provider.swift
│ │ ├── Extensions
│ │ ├── ArrayExtension.swift
│ │ └── StringExtensions.swift
│ │ ├── Faker.swift
│ │ ├── Generators
│ │ ├── Address.swift
│ │ ├── App.swift
│ │ ├── Bank.swift
│ │ ├── Business.swift
│ │ ├── Car.swift
│ │ ├── Cat.swift
│ │ ├── Commerce.swift
│ │ ├── Company.swift
│ │ ├── Date.swift
│ │ ├── Gender.swift
│ │ ├── Generator.swift
│ │ ├── Ham.swift
│ │ ├── Hobbit.swift
│ │ ├── House.swift
│ │ ├── Internet.swift
│ │ ├── Lorem.swift
│ │ ├── Name.swift
│ │ ├── Number.swift
│ │ ├── PhoneNumber.swift
│ │ ├── ProgrammingLanguage.swift
│ │ ├── Team.swift
│ │ ├── Vehicle.swift
│ │ └── Zelda.swift
│ │ └── Resources
│ │ └── Locales
│ │ ├── de-AT.json
│ │ ├── de-CH.json
│ │ ├── de.json
│ │ ├── en-AU.json
│ │ ├── en-CA.json
│ │ ├── en-GB.json
│ │ ├── en-IND.json
│ │ ├── en-TEST.json
│ │ ├── en-US.json
│ │ ├── en.json
│ │ ├── es.json
│ │ ├── fa.json
│ │ ├── fr.json
│ │ ├── it.json
│ │ ├── ja.json
│ │ ├── ko.json
│ │ ├── nb-NO.json
│ │ ├── nl.json
│ │ ├── pl.json
│ │ ├── pt-BR.json
│ │ ├── ru.json
│ │ ├── sk.json
│ │ ├── sv.json
│ │ ├── tr-TR.json
│ │ ├── uk.json
│ │ ├── zh-CN.json
│ │ └── zh-TW.json
├── Kingfisher
│ ├── LICENSE
│ ├── README.md
│ └── Sources
│ │ ├── Cache
│ │ ├── CacheSerializer.swift
│ │ ├── DiskStorage.swift
│ │ ├── FormatIndicatedCacheSerializer.swift
│ │ ├── ImageCache.swift
│ │ ├── MemoryStorage.swift
│ │ └── Storage.swift
│ │ ├── Extensions
│ │ ├── ImageView+Kingfisher.swift
│ │ ├── NSButton+Kingfisher.swift
│ │ ├── NSTextAttachment+Kingfisher.swift
│ │ ├── TVMonogramView+Kingfisher.swift
│ │ ├── UIButton+Kingfisher.swift
│ │ └── WKInterfaceImage+Kingfisher.swift
│ │ ├── General
│ │ ├── ImageSource
│ │ │ ├── AVAssetImageDataProvider.swift
│ │ │ ├── ImageDataProvider.swift
│ │ │ ├── Resource.swift
│ │ │ └── Source.swift
│ │ ├── KF.swift
│ │ ├── KFOptionsSetter.swift
│ │ ├── Kingfisher.swift
│ │ ├── KingfisherError.swift
│ │ ├── KingfisherManager.swift
│ │ └── KingfisherOptionsInfo.swift
│ │ ├── Image
│ │ ├── Filter.swift
│ │ ├── GIFAnimatedImage.swift
│ │ ├── Image.swift
│ │ ├── ImageDrawing.swift
│ │ ├── ImageFormat.swift
│ │ ├── ImageProcessor.swift
│ │ ├── ImageProgressive.swift
│ │ ├── ImageTransition.swift
│ │ └── Placeholder.swift
│ │ ├── Kingfisher.h
│ │ ├── Networking
│ │ ├── AuthenticationChallengeResponsable.swift
│ │ ├── ImageDataProcessor.swift
│ │ ├── ImageDownloader.swift
│ │ ├── ImageDownloaderDelegate.swift
│ │ ├── ImageModifier.swift
│ │ ├── ImagePrefetcher.swift
│ │ ├── RedirectHandler.swift
│ │ ├── RequestModifier.swift
│ │ ├── RetryStrategy.swift
│ │ ├── SessionDataTask.swift
│ │ └── SessionDelegate.swift
│ │ ├── SwiftUI
│ │ ├── ImageBinder.swift
│ │ ├── KFImage.swift
│ │ └── KFImageOptions.swift
│ │ ├── Utility
│ │ ├── Box.swift
│ │ ├── CallbackQueue.swift
│ │ ├── Delegate.swift
│ │ ├── ExtensionHelpers.swift
│ │ ├── Result.swift
│ │ ├── Runtime.swift
│ │ ├── SizeExtensions.swift
│ │ └── String+MD5.swift
│ │ └── Views
│ │ ├── AnimatedImageView.swift
│ │ └── Indicator.swift
├── Manifest.lock
├── Pods.xcodeproj
│ ├── project.pbxproj
│ └── xcuserdata
│ │ └── mohannad.xcuserdatad
│ │ └── xcschemes
│ │ ├── Fakery-Faker.xcscheme
│ │ ├── Fakery.xcscheme
│ │ ├── Kingfisher.xcscheme
│ │ ├── Pods-DynamicCell-DynamicCellUITests.xcscheme
│ │ ├── Pods-DynamicCell.xcscheme
│ │ ├── Pods-DynamicCellTests.xcscheme
│ │ └── xcschememanagement.plist
└── Target Support Files
│ ├── Fakery
│ ├── Fakery-Info.plist
│ ├── Fakery-dummy.m
│ ├── Fakery-prefix.pch
│ ├── Fakery-umbrella.h
│ ├── Fakery.debug.xcconfig
│ ├── Fakery.modulemap
│ ├── Fakery.release.xcconfig
│ └── ResourceBundle-Faker-Fakery-Info.plist
│ ├── Kingfisher
│ ├── Kingfisher-Info.plist
│ ├── Kingfisher-dummy.m
│ ├── Kingfisher-prefix.pch
│ ├── Kingfisher-umbrella.h
│ ├── Kingfisher.debug.xcconfig
│ ├── Kingfisher.modulemap
│ └── Kingfisher.release.xcconfig
│ ├── Pods-DynamicCell-DynamicCellUITests
│ ├── Pods-DynamicCell-DynamicCellUITests-Info.plist
│ ├── Pods-DynamicCell-DynamicCellUITests-acknowledgements.markdown
│ ├── Pods-DynamicCell-DynamicCellUITests-acknowledgements.plist
│ ├── Pods-DynamicCell-DynamicCellUITests-dummy.m
│ ├── Pods-DynamicCell-DynamicCellUITests-frameworks-Debug-input-files.xcfilelist
│ ├── Pods-DynamicCell-DynamicCellUITests-frameworks-Debug-output-files.xcfilelist
│ ├── Pods-DynamicCell-DynamicCellUITests-frameworks-Release-input-files.xcfilelist
│ ├── Pods-DynamicCell-DynamicCellUITests-frameworks-Release-output-files.xcfilelist
│ ├── Pods-DynamicCell-DynamicCellUITests-frameworks.sh
│ ├── Pods-DynamicCell-DynamicCellUITests-umbrella.h
│ ├── Pods-DynamicCell-DynamicCellUITests.debug.xcconfig
│ ├── Pods-DynamicCell-DynamicCellUITests.modulemap
│ └── Pods-DynamicCell-DynamicCellUITests.release.xcconfig
│ ├── Pods-DynamicCell
│ ├── Pods-DynamicCell-Info.plist
│ ├── Pods-DynamicCell-acknowledgements.markdown
│ ├── Pods-DynamicCell-acknowledgements.plist
│ ├── Pods-DynamicCell-dummy.m
│ ├── Pods-DynamicCell-frameworks-Debug-input-files.xcfilelist
│ ├── Pods-DynamicCell-frameworks-Debug-output-files.xcfilelist
│ ├── Pods-DynamicCell-frameworks-Release-input-files.xcfilelist
│ ├── Pods-DynamicCell-frameworks-Release-output-files.xcfilelist
│ ├── Pods-DynamicCell-frameworks.sh
│ ├── Pods-DynamicCell-umbrella.h
│ ├── Pods-DynamicCell.debug.xcconfig
│ ├── Pods-DynamicCell.modulemap
│ └── Pods-DynamicCell.release.xcconfig
│ └── Pods-DynamicCellTests
│ ├── Pods-DynamicCellTests-Info.plist
│ ├── Pods-DynamicCellTests-acknowledgements.markdown
│ ├── Pods-DynamicCellTests-acknowledgements.plist
│ ├── Pods-DynamicCellTests-dummy.m
│ ├── Pods-DynamicCellTests-umbrella.h
│ ├── Pods-DynamicCellTests.debug.xcconfig
│ ├── Pods-DynamicCellTests.modulemap
│ └── Pods-DynamicCellTests.release.xcconfig
└── README.md
/DynamicCell.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/DynamicCell.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/DynamicCell.xcodeproj/xcuserdata/mohannad.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | DynamicCell.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 6
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/DynamicCell.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/DynamicCell.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/DynamicCell.xcworkspace/xcuserdata/mohannad.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/DynamicCell/Controllers/CommentsController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CommentsController.swift
3 | // DynamicCell
4 | //
5 | // Created by Mohannad on 29.03.2021.
6 | //
7 |
8 | import UIKit
9 | import Fakery
10 |
11 | class CommentsController: UIViewController {
12 |
13 |
14 | @IBOutlet weak var commentColllection: UICollectionView!
15 |
16 | let commentFlowLayout = CommentFlowLayout()
17 |
18 | private var comments = [Comment]()
19 |
20 | override func viewDidLoad() {
21 | super.viewDidLoad()
22 | buildComments()
23 | configure()
24 |
25 | }
26 |
27 |
28 |
29 | func configure () {
30 |
31 | commentColllection.dataSource = self
32 | commentColllection.register(CommentCell.self, forCellWithReuseIdentifier: "cell")
33 | commentFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
34 | commentFlowLayout.minimumInteritemSpacing = 10
35 | commentFlowLayout.minimumLineSpacing = 10
36 | commentColllection.collectionViewLayout = commentFlowLayout
37 | commentColllection.contentInsetAdjustmentBehavior = .always
38 | commentColllection.reloadData()
39 | }
40 |
41 |
42 | func buildComments(){
43 |
44 | let faker = Faker(locale: "nb-NO")
45 | for i in 0...9 {
46 | let randomInt = Int(arc4random_uniform(6) + 1)
47 | var info = Comment(owner: faker.name.name(), id: UUID().uuidString, message: faker.lorem.sentences(amount: 5), ownerPhoto: "9\(i)")
48 |
49 | comments.append(info)
50 |
51 | }
52 |
53 | }
54 | }
55 |
56 |
57 |
58 | extension CommentsController : UICollectionViewDataSource {
59 |
60 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
61 | return comments.count
62 | }
63 |
64 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
65 |
66 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CommentCell
67 |
68 | cell.comment = comments[indexPath.row]
69 |
70 | return cell
71 | }
72 |
73 |
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/DynamicCell/Controllers/FeedsController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FeedsController.swift
3 | // DynamicCell
4 | //
5 | // Created by Mohannad on 29.03.2021.
6 | //
7 |
8 | import UIKit
9 | import Fakery
10 |
11 | class FeedsController: UIViewController {
12 |
13 | @IBOutlet weak var feedCollection: UICollectionView!
14 |
15 | var photos = [Photo]()
16 |
17 | var headers = [String]()
18 |
19 | override func viewDidLoad() {
20 | super.viewDidLoad()
21 | buildHeaders()
22 | configure()
23 |
24 | }
25 |
26 |
27 | func configure(){
28 |
29 | let layout = PinterestLayout()
30 | layout.delegate = self
31 |
32 | feedCollection.register(FeedCell.self, forCellWithReuseIdentifier: "FeedCell")
33 | feedCollection.dataSource = self
34 | feedCollection.collectionViewLayout = layout
35 | feedCollection.toggleActivityIndicator()
36 |
37 | ApiService.shared.getPhotos { (res) in
38 |
39 | if let photos = res {
40 |
41 | DispatchQueue.main.async {
42 |
43 | self.feedCollection.toggleActivityIndicator()
44 |
45 | self.photos = photos
46 |
47 | self.feedCollection.reloadData()
48 | }
49 | }
50 | }
51 | }
52 |
53 | func buildHeaders(){
54 |
55 | let faker = Faker(locale: "nb-NO")
56 | for i in 0...50 {
57 | let randomInt = Int(arc4random_uniform(13) + 2)
58 | let text = faker.lorem.words(amount: randomInt)
59 | headers.append(text)
60 | }
61 | }
62 | }
63 |
64 | extension FeedsController : UICollectionViewDataSource , UICollectionViewDelegate {
65 |
66 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
67 | return photos.count
68 | }
69 |
70 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
71 |
72 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FeedCell", for: indexPath) as! FeedCell
73 |
74 | cell.info = photos[indexPath.row]
75 |
76 | cell.descLab.text = headers[indexPath.row]
77 |
78 | return cell
79 |
80 | }
81 |
82 | }
83 |
84 | extension FeedsController : PinterestLayoutDelegate {
85 |
86 | func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath, cellWidth: CGFloat) -> CGFloat {
87 |
88 | let imgHeight = calculateImageHeight(sourceImage: photos[indexPath.row] , scaledToWidth: cellWidth)
89 |
90 | let textHeight = requiredHeight(text: headers[indexPath.row], cellWidth: (cellWidth - 10))
91 |
92 | return (imgHeight + textHeight + 10)
93 |
94 | }
95 |
96 | func calculateImageHeight (sourceImage:Photo, scaledToWidth: CGFloat) -> CGFloat {
97 | let oldWidth = CGFloat( sourceImage.width)
98 | let scaleFactor = scaledToWidth / oldWidth
99 | let newHeight = CGFloat(sourceImage.height) * scaleFactor
100 | return newHeight
101 | }
102 |
103 | func requiredHeight(text:String , cellWidth : CGFloat) -> CGFloat {
104 |
105 | let font = UIFont(name: "Helvetica", size: 16.0)
106 | let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: cellWidth, height: .greatestFiniteMagnitude))
107 | label.numberOfLines = 0
108 | label.lineBreakMode = .byWordWrapping
109 | label.font = font
110 | label.text = text
111 | label.sizeToFit()
112 | return label.frame.height
113 |
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/DynamicCell/Controllers/MainController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // DynamicCell
4 | //
5 | // Created by Mohannad on 27.03.2021.
6 | //
7 |
8 | import UIKit
9 | import Fakery
10 |
11 | class MainController: UIViewController {
12 |
13 |
14 |
15 |
16 | override func viewDidLoad() {
17 | super.viewDidLoad()
18 |
19 |
20 |
21 | // Do any additional setup after loading the view.
22 | }
23 |
24 |
25 |
26 |
27 |
28 |
29 | }
30 |
31 |
32 |
--------------------------------------------------------------------------------
/DynamicCell/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 | UISceneStoryboardFile
37 | Main
38 |
39 |
40 |
41 |
42 | UIApplicationSupportsIndirectInputEvents
43 |
44 | UILaunchStoryboardName
45 | LaunchScreen
46 | UIMainStoryboardFile
47 | Main
48 | UIRequiredDeviceCapabilities
49 |
50 | armv7
51 |
52 | UISupportedInterfaceOrientations
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationLandscapeLeft
56 | UIInterfaceOrientationLandscapeRight
57 |
58 | UISupportedInterfaceOrientations~ipad
59 |
60 | UIInterfaceOrientationPortrait
61 | UIInterfaceOrientationPortraitUpsideDown
62 | UIInterfaceOrientationLandscapeLeft
63 | UIInterfaceOrientationLandscapeRight
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/DynamicCell/Models/Comment.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Comment.swift
3 | // DynamicCell
4 | //
5 | // Created by Mohannad on 29.03.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | struct Comment : Codable {
11 | var owner : String
12 | var id : String
13 | var message : String
14 | var ownerPhoto : String
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/DynamicCell/Models/Photo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Photo.swift
3 | // MVVMArchitecture
4 | //
5 | // Created by Mohannad on 26.03.2021.
6 | //
7 |
8 | import UIKit
9 |
10 |
11 | class Photo : Codable {
12 | var id : String
13 | var width : Int
14 | var height : Int
15 | var url : String
16 | var download_url : String
17 | }
18 |
--------------------------------------------------------------------------------
/DynamicCell/Others/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // DynamicCell
4 | //
5 | // Created by Mohannad on 27.03.2021.
6 | //
7 |
8 | import UIKit
9 |
10 | @main
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 |
13 |
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | return true
18 | }
19 |
20 | // MARK: UISceneSession Lifecycle
21 |
22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
23 | // Called when a new scene session is being created.
24 | // Use this method to select a configuration to create the new scene with.
25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
26 | }
27 |
28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
29 | // Called when the user discards a scene session.
30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
32 | }
33 |
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/90.imageset/90.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohannadBakbouk/DynamicCell/91ccccd6ca3dca6b02224a264020f89763f6d872/DynamicCell/Others/Assets.xcassets/90.imageset/90.jpeg
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/90.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "90.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/91.imageset/91.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohannadBakbouk/DynamicCell/91ccccd6ca3dca6b02224a264020f89763f6d872/DynamicCell/Others/Assets.xcassets/91.imageset/91.jpeg
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/91.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "91.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/92.imageset/92.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohannadBakbouk/DynamicCell/91ccccd6ca3dca6b02224a264020f89763f6d872/DynamicCell/Others/Assets.xcassets/92.imageset/92.jpeg
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/92.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "92.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/93.imageset/99.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohannadBakbouk/DynamicCell/91ccccd6ca3dca6b02224a264020f89763f6d872/DynamicCell/Others/Assets.xcassets/93.imageset/99.jpeg
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/93.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "99.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/94.imageset/94.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohannadBakbouk/DynamicCell/91ccccd6ca3dca6b02224a264020f89763f6d872/DynamicCell/Others/Assets.xcassets/94.imageset/94.jpeg
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/94.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "94.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/95.imageset/95.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohannadBakbouk/DynamicCell/91ccccd6ca3dca6b02224a264020f89763f6d872/DynamicCell/Others/Assets.xcassets/95.imageset/95.jpeg
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/95.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "95.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/96.imageset/96.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohannadBakbouk/DynamicCell/91ccccd6ca3dca6b02224a264020f89763f6d872/DynamicCell/Others/Assets.xcassets/96.imageset/96.jpeg
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/96.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "96.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/97.imageset/97.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohannadBakbouk/DynamicCell/91ccccd6ca3dca6b02224a264020f89763f6d872/DynamicCell/Others/Assets.xcassets/97.imageset/97.jpeg
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/97.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "97.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/98.imageset/98.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohannadBakbouk/DynamicCell/91ccccd6ca3dca6b02224a264020f89763f6d872/DynamicCell/Others/Assets.xcassets/98.imageset/98.jpeg
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/98.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "98.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/99.imageset/93.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MohannadBakbouk/DynamicCell/91ccccd6ca3dca6b02224a264020f89763f6d872/DynamicCell/Others/Assets.xcassets/99.imageset/93.jpeg
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/99.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "93.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/DynamicCell/Others/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/DynamicCell/Others/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // DynamicCell
4 | //
5 | // Created by Mohannad on 27.03.2021.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/DynamicCell/Utilities/ApiService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ApiService.swift
3 | // MVVMArchitecture
4 | //
5 | // Created by Mohannad on 15.02.2021.
6 | //
7 |
8 | import Foundation
9 |
10 |
11 | class ApiService : NSObject {
12 |
13 | static let shared = ApiService()
14 |
15 |
16 |
17 |
18 | func getPhotos(completion : @escaping ([Photo]?)->()) {
19 |
20 |
21 | var urlComp = URLComponents(string:"\(Constants.identifiers.photosApi)")!
22 |
23 | urlComp.queryItems = [URLQueryItem(name: "page", value: "1" ),
24 | URLQueryItem(name: "limit", value: "50")]
25 |
26 | var request = URLRequest(url: urlComp.url!)
27 |
28 | request.httpMethod = "Get"
29 |
30 | request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
31 |
32 | request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")
33 |
34 | let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
35 |
36 | guard let data = data , error == nil else {
37 | print("error while fetching feeds \(error)")
38 | completion(nil)
39 | return
40 | }
41 |
42 | let result = try? JSONDecoder().decode([Photo].self, from: data)
43 |
44 | completion(result)
45 | }
46 |
47 | task.resume()
48 |
49 |
50 | }
51 |
52 |
53 |
54 |
55 | }
56 |
57 |
58 |
--------------------------------------------------------------------------------
/DynamicCell/Utilities/CommentFlowLayout.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CommentFlowLayout.swift
3 | // DynamicCell
4 | //
5 | // Created by Mohannad on 29.03.2021.
6 | //
7 |
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | final class CommentFlowLayout : UICollectionViewFlowLayout {
13 |
14 | override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
15 | let layoutAttributesObjects = super.layoutAttributesForElements(in: rect)?.map{ $0.copy() } as? [UICollectionViewLayoutAttributes]
16 | layoutAttributesObjects?.forEach({ layoutAttributes in
17 | if layoutAttributes.representedElementCategory == .cell {
18 | if let newFrame = layoutAttributesForItem(at: layoutAttributes.indexPath)?.frame {
19 | layoutAttributes.frame = newFrame
20 | }
21 | }
22 | })
23 | return layoutAttributesObjects
24 | }
25 |
26 |
27 | override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
28 |
29 |
30 | guard let collectionView = collectionView else {
31 | fatalError()
32 | }
33 | guard let layoutAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes else {
34 | return nil
35 | }
36 |
37 | layoutAttributes.frame.origin.x = sectionInset.left
38 | layoutAttributes.frame.size.width = collectionView.safeAreaLayoutGuide.layoutFrame.width - sectionInset.left - sectionInset.right
39 | return layoutAttributes
40 | }
41 |
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/DynamicCell/Utilities/Constants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Constants.swift
3 | // MVVMArchitecture
4 | //
5 | // Created by Mohannad on 15.02.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | struct Constants {
11 |
12 | struct identifiers {
13 | static let apiUrl = "https://dummyapi.io/data/api/"
14 | static let apiKey = "5fa160451843ad228d0a1c7c"
15 | static let photosApi = "https://picsum.photos/v2/list"
16 | }
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/DynamicCell/Utilities/PinterestLayout.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NewAutoSizingFlowLayout.swift
3 | // MVVMArchitecture
4 | //
5 | // Created by Mohannad on 17.03.2021.
6 | //
7 |
8 | import UIKit
9 |
10 |
11 | protocol PinterestLayoutDelegate: AnyObject {
12 | func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath , cellWidth : CGFloat ) -> CGFloat
13 | }
14 |
15 | class PinterestLayout: UICollectionViewLayout {
16 |
17 | weak var delegate: PinterestLayoutDelegate?
18 | private let numberOfColumns = 2
19 | private let cellPadding: CGFloat = 6
20 | private var cache: [UICollectionViewLayoutAttributes] = []
21 | private var contentHeight: CGFloat = 0
22 | private var contentWidth: CGFloat {
23 | guard let collectionView = collectionView else {
24 | return 0
25 | }
26 | let insets = collectionView.contentInset
27 | return collectionView.bounds.width - (insets.left + insets.right)
28 | }
29 |
30 | override var collectionViewContentSize: CGSize {
31 | return CGSize(width: contentWidth, height: contentHeight)
32 | }
33 |
34 | override func prepare() {
35 | guard cache.isEmpty == true,let collectionView = collectionView else {
36 | return
37 | }
38 | let columnWidth = contentWidth / CGFloat(numberOfColumns)
39 | var xOffset: [CGFloat] = []
40 | for column in 0.. [UICollectionViewLayoutAttributes]? {
65 | var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
66 |
67 | // Loop through the cache and look for items in the rect
68 | for attributes in cache {
69 | if attributes.frame.intersects(rect) {
70 | visibleLayoutAttributes.append(attributes)
71 | }
72 | }
73 | return visibleLayoutAttributes
74 | }
75 |
76 | override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
77 | return cache[indexPath.item]
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/DynamicCell/Views/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/DynamicCell/Views/Comments.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/DynamicCell/Views/CustomCells/CommentCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CommentCell.swift
3 | // DynamicCell
4 | //
5 | // Created by Mohannad on 29.03.2021.
6 | //
7 |
8 | import UIKit
9 |
10 | class CommentCell: UICollectionViewCell {
11 |
12 | var comment : Comment! {
13 |
14 | didSet {
15 |
16 | messageLab.text = comment.message //comment.message
17 | nameLab.text = comment.owner
18 | img.image = UIImage(named: comment.ownerPhoto)
19 |
20 |
21 | }
22 | }
23 |
24 | var messageLab : UILabel = {
25 | let lab = UILabel()
26 | lab.text = ""
27 | lab.numberOfLines = 10
28 | lab.textColor = .white
29 | return lab
30 | }()
31 |
32 | var nameLab : UILabel = {
33 | let lab = UILabel()
34 | lab.text = "Mohannad bakbouk"
35 | lab.textColor = .systemGray6
36 | lab.numberOfLines = 1
37 | return lab
38 | }()
39 |
40 | var img : UIImageView = {
41 | let img = UIImageView()
42 | img.backgroundColor = .gray
43 | img.contentMode = .scaleAspectFill
44 | img.clipsToBounds = true
45 | img.kf.indicatorType = .activity
46 | img.layer.cornerRadius = 25
47 | return img
48 | }()
49 |
50 | var container : UIView = {
51 | let view = UIView()
52 | view.clipsToBounds = true
53 | //view.backgroundColor = .systemGray6
54 | view.backgroundColor = .mainColor
55 | view.layer.cornerRadius = 8
56 | return view
57 | }()
58 |
59 | override init(frame: CGRect) {
60 | super.init(frame: frame)
61 | setupViews()
62 | }
63 |
64 | required init?(coder: NSCoder) {
65 | super.init(coder: coder)
66 | setupViews()
67 | }
68 |
69 | func setupViews(){
70 |
71 | contentView.addSubview(img)
72 | contentView.addSubview(container)
73 | container.addSubview(nameLab)
74 | container.addSubview(messageLab)
75 |
76 | img.anchor(top: contentView.topAnchor, paddingTop: 5, bottom: nil, paddingBottom: 0, left: contentView.leadingAnchor, paddingLeft: 10, right: nil, paddingRight: 0, width: 50, height: 50)
77 |
78 | container.anchor(top: contentView.topAnchor, paddingTop: 0, bottom: contentView.bottomAnchor, paddingBottom: -10, left: img.trailingAnchor, paddingLeft: 10, right: contentView.trailingAnchor, paddingRight: -10, width: 0, height: 0)
79 |
80 |
81 | nameLab.anchor(top: container.topAnchor, paddingTop: 10, bottom: nil, paddingBottom: 0, left: container.leadingAnchor, paddingLeft: 10, right: container.trailingAnchor, paddingRight: -10, width: 0, height: 0)
82 |
83 | messageLab.anchor(top: nameLab.bottomAnchor, paddingTop: 10, bottom: container.bottomAnchor, paddingBottom: -5, left: container.leadingAnchor, paddingLeft: 10, right: container.trailingAnchor, paddingRight: -10, width: 0, height: 0)
84 |
85 |
86 | }
87 |
88 |
89 | override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
90 | let targetSize = CGSize(width: layoutAttributes.frame.width, height: 0)
91 | layoutAttributes.frame.size = contentView.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
92 | return layoutAttributes
93 | }
94 |
95 | }
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/DynamicCell/Views/CustomCells/FeedCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FeedCell.swift
3 | // DynamicCell
4 | //
5 | // Created by Mohannad on 29.03.2021.
6 | //
7 |
8 |
9 | import UIKit
10 | import Kingfisher
11 |
12 | class FeedCell: UICollectionViewCell {
13 |
14 | var img : UIImageView = {
15 | let img = UIImageView()
16 | img.backgroundColor = .gray
17 | img.contentMode = .scaleAspectFill
18 | img.clipsToBounds = true
19 | img.translatesAutoresizingMaskIntoConstraints = false
20 | img.setContentHuggingPriority(.defaultLow, for: .vertical)
21 | return img
22 | }()
23 |
24 | var descLab : UILabel = {
25 | let lab = UILabel()
26 | lab.textColor = .white
27 | lab.numberOfLines = 0
28 | lab.lineBreakMode = .byWordWrapping
29 | lab.translatesAutoresizingMaskIntoConstraints = false
30 | lab.font = UIFont(name: "Helvetica", size: 16)
31 | lab.setContentHuggingPriority(.defaultHigh, for: .vertical)
32 | return lab
33 | }()
34 |
35 | var info : Photo? {
36 | didSet {
37 | assignPhoto()
38 | }
39 | }
40 |
41 | override func layoutSubviews() {
42 | super.layoutSubviews()
43 | setupViews()
44 | setupConstraints()
45 | }
46 |
47 | override init(frame: CGRect) {
48 | super.init(frame: frame)
49 | }
50 |
51 | required init?(coder: NSCoder) {
52 | super.init(coder: coder)
53 | }
54 |
55 | override func prepareForReuse() {
56 | super.prepareForReuse()
57 | info = nil
58 | img.removeFromSuperview()
59 | descLab.removeFromSuperview()
60 |
61 | }
62 |
63 | deinit {
64 | info = nil
65 | }
66 |
67 |
68 | func setupViews(){
69 |
70 | layer.borderWidth = 1
71 | layer.borderColor = UIColor.lightGray.cgColor
72 | backgroundColor = .mainColor
73 | contentView.addSubview(img)
74 | contentView.addSubview(descLab)
75 |
76 | }
77 |
78 | func setupConstraints(){
79 | img.anchor(top: contentView.topAnchor, paddingTop: 0, bottom: nil, paddingBottom: 0, left: contentView.leadingAnchor, paddingLeft: 0, right: contentView.trailingAnchor, paddingRight: 0, width: 0, height: 0)
80 |
81 | descLab.anchor(top: img.bottomAnchor , paddingTop: 5, bottom: contentView.bottomAnchor, paddingBottom: -5, left: contentView.leadingAnchor, paddingLeft: 5, right: contentView.trailingAnchor, paddingRight: -5, width: 0, height: 0)
82 | }
83 |
84 | func assignPhoto(){
85 |
86 | guard let data = info else {
87 | return
88 | }
89 |
90 | img.kf.setImage(with: URL(string: data.download_url)!) { res in
91 | if case .success(let value) = res {
92 | ImageCache.default.store(value.image, forKey: data.download_url)
93 |
94 | }
95 | }
96 | }
97 |
98 | }
99 |
100 |
--------------------------------------------------------------------------------
/DynamicCell/Views/Feeds.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/DynamicCellTests/DynamicCellTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DynamicCellTests.swift
3 | // DynamicCellTests
4 | //
5 | // Created by Mohannad on 27.03.2021.
6 | //
7 |
8 | import XCTest
9 | @testable import DynamicCell
10 |
11 | class DynamicCellTests: XCTestCase {
12 |
13 | override func setUpWithError() throws {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 | }
16 |
17 | override func tearDownWithError() throws {
18 | // Put teardown code here. This method is called after the invocation of each test method in the class.
19 | }
20 |
21 | func testExample() throws {
22 | // This is an example of a functional test case.
23 | // Use XCTAssert and related functions to verify your tests produce the correct results.
24 | }
25 |
26 | func testPerformanceExample() throws {
27 | // This is an example of a performance test case.
28 | self.measure {
29 | // Put the code you want to measure the time of here.
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/DynamicCellTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/DynamicCellUITests/DynamicCellUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DynamicCellUITests.swift
3 | // DynamicCellUITests
4 | //
5 | // Created by Mohannad on 27.03.2021.
6 | //
7 |
8 | import XCTest
9 |
10 | class DynamicCellUITests: XCTestCase {
11 |
12 | override func setUpWithError() throws {
13 | // Put setup code here. This method is called before the invocation of each test method in the class.
14 |
15 | // In UI tests it is usually best to stop immediately when a failure occurs.
16 | continueAfterFailure = false
17 |
18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
19 | }
20 |
21 | override func tearDownWithError() throws {
22 | // Put teardown code here. This method is called after the invocation of each test method in the class.
23 | }
24 |
25 | func testExample() throws {
26 | // UI tests must launch the application that they test.
27 | let app = XCUIApplication()
28 | app.launch()
29 |
30 | // Use recording to get started writing UI tests.
31 | // Use XCTAssert and related functions to verify your tests produce the correct results.
32 | }
33 |
34 | func testLaunchPerformance() throws {
35 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) {
36 | // This measures how long it takes to launch your application.
37 | measure(metrics: [XCTApplicationLaunchMetric()]) {
38 | XCUIApplication().launch()
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/DynamicCellUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment the next line to define a global platform for your project
2 | platform :ios, '14.0'
3 |
4 | target 'DynamicCell' do
5 | # Comment the next line if you don't want to use dynamic frameworks
6 | use_frameworks!
7 |
8 | # Pods for DynamicCell
9 | pod 'Kingfisher', '~> 6.0'
10 | pod 'Fakery'
11 |
12 | target 'DynamicCellTests' do
13 | inherit! :search_paths
14 | # Pods for testing
15 |
16 | end
17 |
18 | target 'DynamicCellUITests' do
19 | # Pods for testing
20 | end
21 |
22 | end
23 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Fakery (5.1.0)
3 | - Kingfisher (6.0.1)
4 |
5 | DEPENDENCIES:
6 | - Fakery
7 | - Kingfisher (~> 6.0)
8 |
9 | SPEC REPOS:
10 | trunk:
11 | - Fakery
12 | - Kingfisher
13 |
14 | SPEC CHECKSUMS:
15 | Fakery: a90caff00ca5cacde6c161c3eafc72314a03d34d
16 | Kingfisher: adde87a4f74f6a3845395769354efff593581740
17 |
18 | PODFILE CHECKSUM: 2e75b4b78d18cf325281d383317394c9eb3d64ac
19 |
20 | COCOAPODS: 1.10.0
21 |
--------------------------------------------------------------------------------
/Pods/Fakery/LICENSE.md:
--------------------------------------------------------------------------------
1 | Licensed under the **MIT** license
2 |
3 | > Copyright (c) 2015 Vadym Markov
4 | >
5 | > Permission is hereby granted, free of charge, to any person obtaining
6 | > a copy of this software and associated documentation files (the
7 | > "Software"), to deal in the Software without restriction, including
8 | > without limitation the rights to use, copy, modify, merge, publish,
9 | > distribute, sublicense, and/or sell copies of the Software, and to
10 | > permit persons to whom the Software is furnished to do so, subject to
11 | > the following conditions:
12 | >
13 | > The above copyright notice and this permission notice shall be
14 | > included in all copies or substantial portions of the Software.
15 | >
16 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | > IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | > CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 | > TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 | > SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Config.swift:
--------------------------------------------------------------------------------
1 | public struct Config {
2 | public static let defaultLocale: String = "en"
3 | public static let pathExtension: String = "json"
4 | public static var dirPath: String = "Resources/Locales"
5 | public static var dirFrameworkPath: String = ""
6 | public static var dirResourcePath: String = ""
7 | }
8 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Data/Parser.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public final class Parser {
4 | public var locale: String {
5 | didSet {
6 | if locale != oldValue {
7 | loadData(forLocale: locale)
8 | }
9 | }
10 | }
11 |
12 | private var data = [String: Any]()
13 | let provider: Provider
14 |
15 | // MARK: - Initialization
16 |
17 | public init(locale: String = Config.defaultLocale) {
18 | self.locale = locale
19 | provider = Provider()
20 | loadData(forLocale: locale)
21 |
22 | if locale != Config.defaultLocale {
23 | loadData(forLocale: Config.defaultLocale)
24 | }
25 | }
26 |
27 | // MARK: - Parsing
28 |
29 | public func fetch(_ key: String) -> String {
30 | var parsed = ""
31 |
32 | guard let keyData = fetchRaw(key) else {
33 | return parsed
34 | }
35 |
36 | let subject = getSubject(key)
37 |
38 | if let value = keyData as? String {
39 | parsed = value
40 | } else if let array = keyData as? [String], let item = array.random() {
41 | parsed = item
42 | }
43 |
44 | if parsed.range(of: "#{") != nil {
45 | parsed = parse(parsed, forSubject: subject)
46 | }
47 |
48 | return parsed
49 | }
50 |
51 | public func fetchRaw(_ key: String) -> Any? {
52 | let result = fetchRaw(key, forLocale: locale)
53 |
54 | guard locale != Config.defaultLocale else {
55 | return result
56 | }
57 |
58 | return result ?? fetchRaw(key, forLocale: Config.defaultLocale)
59 | }
60 |
61 | func parse(_ template: String, forSubject subject: String) -> String {
62 | var text = ""
63 | let string = NSString(string: template)
64 | var regex: NSRegularExpression
65 |
66 | do {
67 | try regex = NSRegularExpression(pattern: "(\\(?)#\\{([A-Za-z]+\\.)?([^\\}]+)\\}([^#]+)?",
68 | options: .caseInsensitive)
69 |
70 | let matches = regex.matches(in: template,
71 | options: .reportCompletion,
72 | range: NSRange(location: 0, length: string.length))
73 |
74 | guard !matches.isEmpty else {
75 | return template
76 | }
77 |
78 | for match in matches {
79 | if match.numberOfRanges < 4 {
80 | continue
81 | }
82 |
83 | let prefixRange = match.range(at: 1)
84 | let subjectRange = match.range(at: 2)
85 | let methodRange = match.range(at: 3)
86 | let otherRange = match.range(at: 4)
87 |
88 | if prefixRange.length > 0 {
89 | text += string.substring(with: prefixRange)
90 | }
91 |
92 | var subjectWithDot = subject + "."
93 |
94 | if subjectRange.length > 0 {
95 | subjectWithDot = string.substring(with: subjectRange)
96 | }
97 |
98 | if methodRange.length > 0 {
99 | let key = subjectWithDot.lowercased() + string.substring(with: methodRange)
100 | text += fetch(key)
101 | }
102 |
103 | if otherRange.length > 0 {
104 | text += string.substring(with: otherRange)
105 | }
106 | }
107 | } catch {}
108 |
109 | return text
110 | }
111 |
112 | private func fetchRaw(_ key: String, forLocale locale: String) -> Any? {
113 | let parts = key.components(separatedBy: ".")
114 |
115 | guard let localeData = data[locale] as? [String: Any],
116 | var parsed = localeData["faker"] as? [String: Any],
117 | !parts.isEmpty else { return nil }
118 |
119 | var result: Any?
120 |
121 | for part in parts {
122 | guard let parsedPart = parsed[part] as? [String: Any] else {
123 | result = parsed[part]
124 | continue
125 | }
126 |
127 | parsed = parsedPart
128 | result = parsedPart
129 | }
130 |
131 | return result
132 | }
133 |
134 | private func getSubject(_ key: String) -> String {
135 | var subject: String = ""
136 | let parts = key.components(separatedBy: ".")
137 |
138 | if !parts.isEmpty {
139 | subject = parts[0]
140 | }
141 |
142 | return subject
143 | }
144 |
145 | // MARK: - Data loading
146 |
147 | private func loadData(forLocale locale: String) {
148 | guard let localeData = provider.dataForLocale(locale),
149 | let parsedData = try? JSONSerialization.jsonObject(with: localeData, options: .allowFragments),
150 | let json = parsedData as? [String: Any],
151 | let localeJson = json[locale] else {
152 | print("JSON file for '\(locale)' locale was not found.")
153 | return
154 | }
155 |
156 | data[locale] = localeJson
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Data/Provider.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public final class Provider {
4 | var translations: [String: Data] = [:]
5 |
6 | // MARK: - Locale data
7 |
8 | public func dataForLocale(_ locale: String) -> Data? {
9 | var translation: Data?
10 |
11 | if let translationData = translations[locale] {
12 | translation = translationData
13 | } else {
14 | #if SWIFT_PACKAGE
15 | let bundle = Bundle.module
16 | #else
17 | let bundle = Bundle(for: Provider.self)
18 | #endif
19 |
20 | var path = bundle.path(forResource: locale,
21 | ofType: Config.pathExtension,
22 | inDirectory: Config.dirPath) ??
23 | bundle.path(forResource: locale,
24 | ofType: Config.pathExtension,
25 | inDirectory: Config.dirFrameworkPath)
26 |
27 | if !Config.dirResourcePath.isEmpty {
28 | path = "\(Config.dirResourcePath)/\(locale).\(Config.pathExtension)"
29 | }
30 |
31 | if let resourcePath = Bundle(for: Provider.self).resourcePath {
32 | let bundlePath = resourcePath + "/Faker.bundle"
33 |
34 | if let bundle = Bundle(path: bundlePath) {
35 | path = bundle.path(forResource: locale, ofType: Config.pathExtension)
36 | }
37 | }
38 |
39 | if let path = path {
40 | let fileURL = URL(fileURLWithPath: path)
41 |
42 | if let data = try? Data(contentsOf: fileURL) {
43 | translation = data
44 | translations[locale] = data
45 | }
46 | }
47 | }
48 |
49 | return translation
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Extensions/ArrayExtension.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Array {
4 | func at(_ index: Int?) -> Element? {
5 | guard let index = index, index >= 0 && index < endIndex else {
6 | return nil
7 | }
8 |
9 | return self[index]
10 | }
11 |
12 | func random() -> Element? {
13 | // swiftlint:disable empty_count
14 | guard count > 0 else {
15 | return nil
16 | }
17 | #if swift(>=4.2)
18 | return self.randomElement()
19 | #else
20 | return self[Int(arc4random_uniform(UInt32(count)))]
21 | #endif
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Extensions/StringExtensions.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension String {
4 | static func characters(amount: Int = 255) -> String {
5 | var chars = ""
6 |
7 | if amount > 0 {
8 | for _ in 0..=4.2)
10 | let char = Character(UnicodeScalar(Int.random(in: 0.. String {
15 | return generate("address.city")
16 | }
17 |
18 | public func streetName() -> String {
19 | return generate("address.street_name")
20 | }
21 |
22 | public func secondaryAddress() -> String {
23 | return numerify(generate("address.secondary_address"))
24 | }
25 |
26 | public func streetAddress(includeSecondary: Bool = false) -> String {
27 | var streetAddress = numerify(generate("address.street_address"))
28 |
29 | if includeSecondary {
30 | streetAddress += " " + secondaryAddress()
31 | }
32 |
33 | return streetAddress
34 | }
35 |
36 | public func buildingNumber() -> String {
37 | return bothify(generate("address.building_number"))
38 | }
39 |
40 | public func postcode(stateAbbreviation: String = "") -> String {
41 | if stateAbbreviation.isEmpty {
42 | return bothify(generate("address.postcode"))
43 | }
44 |
45 | return bothify(generate("address.postcode_by_state.\(stateAbbreviation)"))
46 | }
47 |
48 | public func timeZone() -> String {
49 | return generate("address.time_zone")
50 | }
51 |
52 | public func streetSuffix() -> String {
53 | return generate("address.street_suffix")
54 | }
55 |
56 | public func citySuffix() -> String {
57 | return generate("address.city_suffix")
58 | }
59 |
60 | public func cityPrefix() -> String {
61 | return generate("address.city_prefix")
62 | }
63 |
64 | public func stateAbbreviation() -> String {
65 | return generate("address.state_abbr")
66 | }
67 |
68 | public func state() -> String {
69 | return generate("address.state")
70 | }
71 |
72 | public func county() -> String {
73 | return generate("address.county")
74 | }
75 |
76 | public func country() -> String {
77 | return generate("address.country")
78 | }
79 |
80 | public func countryCode() -> String {
81 | return generate("address.country_code")
82 | }
83 |
84 | public func latitude() -> Double {
85 | return drand48() * 180.0 - 90.0
86 | }
87 |
88 | public func longitude() -> Double {
89 | return drand48() * 360.0 - 180.0
90 | }
91 |
92 | public func coordinate(inRadius radius: Double, fromCenter center: Location) -> Location {
93 | let y0 = center.latitude
94 | let x0 = center.longitude
95 |
96 | // Convert meters to degrees for radius
97 | let radiusInDegrees = radius / 111300.0
98 |
99 | // Random point in circle
100 | #if swift(>=4.2)
101 | let rhoRandom = Double.random(in: 0.. String {
4 | return generate("app.name")
5 | }
6 |
7 | public func version() -> String {
8 | return numerify(generate("app.version"))
9 | }
10 |
11 | public func author() -> String {
12 | return generate("app.author")
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Bank.swift:
--------------------------------------------------------------------------------
1 | extension Faker {
2 | public final class Bank: Generator {
3 | public func name() -> String {
4 | return generate("bank.name")
5 | }
6 |
7 | public func swiftBic() -> String {
8 | return generate("bank.swiftBic")
9 | }
10 |
11 | public func iban() -> String {
12 | let bankCountryCode = generate("bank.ibanDetails.bankCountryCode")
13 | let bankCountryString = numerify("##")
14 | let ibanLetterCode = letterify(generate("bank.ibanDetails.ibanLetterCode"))
15 | let iban = numerify(generate("bank.ibanDetails.ibanDigits"))
16 |
17 | return bankCountryCode + bankCountryString + ibanLetterCode + iban
18 | }
19 |
20 | public func bban() -> String {
21 | let ibanLetterCode: String = letterify(generate("bank.ibanDetails.ibanLetterCode"))
22 | let iban: String = numerify(generate("bank.ibanDetails.ibanDigits"))
23 |
24 | return ibanLetterCode + iban
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Business.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Faker {
4 | public final class Business: Generator {
5 | public func creditCardNumber() -> String {
6 | return generate("business.credit_card_numbers")
7 | }
8 |
9 | public func creditCardType() -> String {
10 | return generate("business.credit_card_types")
11 | }
12 |
13 | public func creditCardExpiryDate() -> Foundation.Date? {
14 | let dateString = generate("business.credit_card_expiry_dates")
15 | return dateFormatter.date(from: dateString)
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Car.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Faker {
4 | public final class Car: Generator {
5 | public func brand() -> String {
6 | return generate("car.brand")
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Cat.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Faker {
4 | public final class Cat: Generator {
5 | public func name() -> String {
6 | return generate("cat.name")
7 | }
8 |
9 | public func breed() -> String {
10 | return generate("cat.breed")
11 | }
12 |
13 | public func registry() -> String {
14 | return generate("cat.registry")
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Commerce.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Faker {
4 | public final class Commerce: Generator {
5 | public func color() -> String {
6 | return generate("commerce.color")
7 | }
8 |
9 | public func department(maximum: Int = 3, fixedAmount: Bool = false) -> String {
10 | #if swift(>=4.2)
11 | let amount = fixedAmount ? maximum : 1 + Int.random(in: 0.. 1 {
21 | department = merge(categories: fetchedCategories)
22 | } else if count == 1 {
23 | department = fetchedCategories[0]
24 | }
25 |
26 | return department
27 | }
28 |
29 | public func productName() -> String {
30 | return generate("commerce.product_name.adjective") + " "
31 | + generate("commerce.product_name.material") + " "
32 | + generate("commerce.product_name.product")
33 | }
34 |
35 | public func price() -> Double {
36 | let arc4randoMax: Double = 0x100000000
37 | #if swift(>=4.2)
38 | return floor(Double((Double(UInt32.random(in: 0.. [String] {
47 | var categories: [String] = []
48 |
49 | while categories.count < amount {
50 | let category = generate("commerce.department")
51 |
52 | if !categories.contains(category) {
53 | categories.append(category)
54 | }
55 | }
56 |
57 | return categories
58 | }
59 |
60 | public func merge(categories: [String]) -> String {
61 | let separator = generate("separator")
62 | let commaSeparated = categories[0.. String {
6 | return generate("company.name")
7 | }
8 |
9 | public func suffix() -> String {
10 | return generate("company.suffix")
11 | }
12 |
13 | public func catchPhrase() -> String {
14 | return randomWordsFromKey("company.buzzwords")
15 | }
16 |
17 | public func bs() -> String {
18 | return randomWordsFromKey("company.bs")
19 | }
20 |
21 | public func logo() -> String {
22 | #if swift(>=4.2)
23 | let number = Int.random(in: 0..<13) + 1
24 | #else
25 | let number = Int(arc4random_uniform(13)) + 1
26 | #endif
27 | return "https://pigment.github.io/fake-logos/logos/medium/color/\(number).png"
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Date.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Faker {
4 | public final class Date: Generator {
5 | public func backward(days: Int) -> Foundation.Date {
6 | return todayAddingDays(-days)
7 | }
8 |
9 | public func forward(_ days: Int) -> Foundation.Date {
10 | return todayAddingDays(days)
11 | }
12 |
13 | public func between(_ from: Foundation.Date, _ to: Foundation.Date) -> Foundation.Date {
14 | let fromInSeconds = from.timeIntervalSince1970
15 | let toInSeconds = to.timeIntervalSince1970
16 | let targetInSeconds = Number().randomDouble(min: fromInSeconds, max: toInSeconds)
17 | return Foundation.Date(timeIntervalSince1970: targetInSeconds)
18 | }
19 |
20 | public func birthday(_ minAge: Int, _ maxAge: Int) -> Foundation.Date {
21 | let olderAgeBirthDate = todayAddingYears(-maxAge)
22 | let earlierAgeBirthDate = todayAddingYears(-minAge)
23 | return between(earlierAgeBirthDate, olderAgeBirthDate)
24 | }
25 |
26 | private func todayAddingDays(_ days: Int) -> Foundation.Date {
27 | var dateComponents = DateComponents()
28 | dateComponents.day = days
29 | return todayAdding(dateComponents)
30 | }
31 |
32 | private func todayAddingYears(_ years: Int) -> Foundation.Date {
33 | var dateComponents = DateComponents()
34 | dateComponents.year = years
35 | return todayAdding(dateComponents)
36 | }
37 |
38 | private func todayAdding(_ dateComponents: DateComponents) -> Foundation.Date {
39 | let calendar = Calendar.current
40 |
41 | let todayDate = Foundation.Date()
42 | return calendar.date(byAdding: dateComponents, to: todayDate)!
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Gender.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Faker {
4 | public final class Gender: Generator {
5 | public func type() -> String {
6 | return generate("gender.type")
7 | }
8 |
9 | public func binaryType() -> String {
10 | return generate("gender.binary_type")
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Generator.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Faker {
4 | public class Generator {
5 | // swiftlint:disable nesting
6 | public struct Constants {
7 | public static let uppercaseLetters = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
8 | public static let letters = Array("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
9 | public static let numbers = Array("0123456789")
10 | }
11 |
12 | let parser: Parser
13 | let dateFormatter: DateFormatter
14 |
15 | public required init(parser: Parser = Parser()) {
16 | self.parser = parser
17 | dateFormatter = DateFormatter()
18 | dateFormatter.dateFormat = "yyyy-MM-dd"
19 | }
20 |
21 | public func generate(_ key: String) -> String {
22 | return parser.fetch(key)
23 | }
24 |
25 | // MARK: - Filling
26 |
27 | public func numerify(_ string: String) -> String {
28 | let count = UInt32(Constants.numbers.count)
29 |
30 | return String(string.enumerated().map { (index, item) in
31 | #if swift(>=4.2)
32 | let numberIndex = index == 0 ? UInt32.random(in: 0..<(count - 1)) : UInt32.random(in: 0.. String {
42 | return String(string.enumerated().map { _, item in
43 | #if swift(>=4.2)
44 | let char = Constants.uppercaseLetters.randomElement() ?? Character("")
45 | #else
46 | let count = UInt32(Constants.uppercaseLetters.count)
47 | let char = Constants.uppercaseLetters[Int(arc4random_uniform(count))]
48 | #endif
49 | return String(item) == "?" ? char : item
50 | })
51 | }
52 |
53 | public func bothify(_ string: String) -> String {
54 | return letterify(numerify(string))
55 | }
56 |
57 | public func alphaNumerify(_ string: String) -> String {
58 | return string.replacingOccurrences(of: "[^A-Za-z0-9_]",
59 | with: "",
60 | options: .regularExpression,
61 | range: nil)
62 | }
63 |
64 | public func randomWordsFromKey(_ key: String) -> String {
65 | var string = ""
66 |
67 | var list = [String]()
68 | if let wordsList = parser.fetchRaw(key) as? [[String]] {
69 | for words in wordsList {
70 | if let item = words.random() {
71 | list.append(item)
72 | }
73 | }
74 |
75 | string = list.joined(separator: " ")
76 | }
77 |
78 | return string
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Ham.swift:
--------------------------------------------------------------------------------
1 | extension Faker {
2 | public final class Ham: Generator {
3 | public func name() -> String {
4 | return generate("ham.name")
5 | }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Hobbit.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Faker {
4 | public final class Hobbit: Generator {
5 | public func character() -> String {
6 | return generate("hobbit.character")
7 | }
8 |
9 | public func thorinsCompany() -> String {
10 | return generate("hobbit.thorins_company")
11 | }
12 |
13 | public func quote() -> String {
14 | return generate("hobbit.quote")
15 | }
16 |
17 | public func location() -> String {
18 | return generate("hobbit.location")
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/House.swift:
--------------------------------------------------------------------------------
1 | extension Faker {
2 | public final class House: Generator {
3 | public func furniture() -> String {
4 | return generate("house.furniture")
5 | }
6 |
7 | public func room() -> String {
8 | return generate("house.room")
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Internet.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Faker {
4 | public final class Internet: Generator {
5 | public required init(parser: Parser) {
6 | super.init(parser: parser)
7 | }
8 |
9 | public func username(separator: String? = nil) -> String {
10 | #if swift(>=4.2)
11 | let lastRandomComponent = Int.random(in: 0..<10000)
12 | #else
13 | let lastRandomComponent = arc4random_uniform(10000)
14 | #endif
15 | let components: [String] = [
16 | generate("name.first_name"),
17 | generate("name.last_name"),
18 | "\(lastRandomComponent)"
19 | ]
20 |
21 | let randomCount = components.count - 1
22 | #if swift(>=4.2)
23 | let count = Int.random(in: 0.. String {
39 | return domainWord(alphaNumericOnly: alphaNumericOnly) + "." + domainSuffix()
40 | }
41 |
42 | public func domainWord(alphaNumericOnly: Bool = true) -> String {
43 | let nameParts = generate("company.name").components(separatedBy: " ")
44 | var name = ""
45 |
46 | if let first = nameParts.first {
47 | name = first
48 | } else {
49 | name = letterify("?????")
50 | }
51 |
52 | let result = alphaNumericOnly ? alphaNumerify(name) : name
53 |
54 | return result.lowercased()
55 | }
56 |
57 | public func domainSuffix() -> String {
58 | return generate("internet.domain_suffix")
59 | }
60 |
61 | public func email() -> String {
62 | return [username(), domainName()].joined(separator: "@")
63 | }
64 |
65 | public func freeEmail() -> String {
66 | return [username(), generate("internet.free_email")].joined(separator: "@")
67 | }
68 |
69 | public func safeEmail() -> String {
70 | let topLevelDomains = ["org", "com", "net"]
71 | #if swift(>=4.2)
72 | let topLevelDomain = topLevelDomains.randomElement() ?? ""
73 | #else
74 | let count = UInt32(topLevelDomains.count)
75 | let topLevelDomain = topLevelDomains[Int(arc4random_uniform(count))]
76 | #endif
77 |
78 | return [username(), "example." + topLevelDomain].joined(separator: "@")
79 | }
80 |
81 | public func password(minimumLength: Int = 8, maximumLength: Int = 16) -> String {
82 | var temp = String.characters(amount: minimumLength)
83 | let diffLength = maximumLength - minimumLength
84 |
85 | if diffLength > 0 {
86 | #if swift(>=4.2)
87 | let diffRandom = Int.random(in: 0.. String {
98 | #if swift(>=4.2)
99 | let randomNumber = UInt32.random(in: 0.. String {
111 | #if swift(>=4.2)
112 | let randomNumber = UInt32.random(in: 0.. String {
127 | return "https://\(domainName())/\(username())"
128 | }
129 |
130 | public func image(width: Int = 320, height: Int = 200) -> String {
131 | return "https://lorempixel.com/\(width)/\(height)"
132 | }
133 |
134 | public func templateImage(width: Int = 320, height: Int = 200,
135 | backColorHex: String = "000000", frontColorHex: String = "ffffff") -> String {
136 | return "https://dummyimage.com/\(width)x\(height)/\(backColorHex)/\(frontColorHex)"
137 | }
138 |
139 | public func hashtag() -> String {
140 | return generate("internet.hashtag")
141 | }
142 |
143 | // @ToDo - slug
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Lorem.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension Faker {
4 | public final class Lorem: Generator {
5 | public func word() -> String {
6 | return generate("lorem.words")
7 | }
8 |
9 | public func words(amount: Int = 3) -> String {
10 | var words: [String] = []
11 |
12 | for _ in 0.. String {
20 | return characters(amount: 1)
21 | }
22 |
23 | public func characters(amount: Int = 255) -> String {
24 | return String.characters(amount: amount)
25 | }
26 |
27 | public func sentence(wordsAmount: Int = 4) -> String {
28 | var sentence = words(amount: wordsAmount) + "."
29 | sentence.replaceSubrange(sentence.startIndex...sentence.startIndex,
30 | with: String(sentence[sentence.startIndex]).capitalized)
31 | return sentence
32 | }
33 |
34 | public func sentences(amount: Int = 3) -> String {
35 | var sentences: [String] = []
36 |
37 | for _ in 0.. String {
45 | return sentences(amount: sentencesAmount)
46 | }
47 |
48 | public func paragraphs(amount: Int = 3) -> String {
49 | var paragraphs: [String] = []
50 |
51 | for _ in 0.. String {
4 | return generate("name.name")
5 | }
6 |
7 | public func firstName() -> String {
8 | return generate("name.first_name")
9 | }
10 |
11 | public func lastName() -> String {
12 | return generate("name.last_name")
13 | }
14 |
15 | public func prefix() -> String {
16 | return generate("name.prefix")
17 | }
18 |
19 | public func suffix() -> String {
20 | return generate("name.suffix")
21 | }
22 |
23 | public func title() -> String {
24 | return generate("name.title.descriptor") + " "
25 | + generate("name.title.level") + " "
26 | + generate("name.title.job")
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Number.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | #if !os(Linux)
3 | import CoreGraphics
4 | #endif
5 |
6 | extension Faker {
7 | public final class Number: Generator {
8 | fileprivate var lastUsedId: Int64 = 0
9 |
10 | public func randomBool() -> Bool {
11 | return randomInt() % 2 == 0
12 | }
13 |
14 | public func randomInt(min: Int = 0, max: Int = 1000) -> Int {
15 | var rand: Int = 0
16 | #if swift(>=4.2)
17 | rand = Int.random(in: rand..= 0 && max - Int.max >= min {
24 | return min + rand
25 | }
26 |
27 | return min + (rand % (max - min))
28 | }
29 |
30 | public func randomFloat(min: Float = 0, max: Float = 1000) -> Float {
31 | #if swift(>=4.2)
32 | return (Float.random(in: 0.. CGFloat {
40 | return CGFloat(Float(arc4random()) / Float(UInt32.max)) * (max - min) + min
41 | }
42 | #endif
43 |
44 | public func randomDouble(min: Double = 0, max: Double = 1000) -> Double {
45 | #if swift(>=4.2)
46 | return (Double.random(in: 0.. Int {
54 | #if os(Linux)
55 | // increasing just by one on linux due to the lack of an method like OSAtomicIncrement64
56 | lastUsedId += 1
57 | #else
58 | OSAtomicIncrement64(&lastUsedId)
59 | #endif
60 | return Int(lastUsedId)
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/PhoneNumber.swift:
--------------------------------------------------------------------------------
1 | extension Faker {
2 | public final class PhoneNumber: Generator {
3 | public func phoneNumber() -> String {
4 | return numerify(generate("phone_number.formats"))
5 | }
6 |
7 | public func cellPhone() -> String {
8 | return numerify(generate("cell_phone.formats"))
9 | }
10 |
11 | // US only
12 | public func areaCode() -> String {
13 | return generate("phone_number.area_code")
14 | }
15 |
16 | // US only
17 | public func exchangeCode() -> String {
18 | return generate("phone_number.exchange_code")
19 | }
20 |
21 | // US only
22 | public func subscriberNumber() -> String {
23 | return numerify("####")
24 | }
25 |
26 | public func numberExtension(_ length: Int) -> String {
27 | var template = ""
28 |
29 | for _ in 1...length {
30 | template += "#"
31 | }
32 |
33 | return numerify(template)
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/ProgrammingLanguage.swift:
--------------------------------------------------------------------------------
1 | extension Faker {
2 | public final class ProgrammingLanguage: Generator {
3 | public func name() -> String {
4 | return generate("programming_language.name")
5 | }
6 |
7 | public func creator() -> String {
8 | return generate("programming_language.creator")
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Team.swift:
--------------------------------------------------------------------------------
1 | extension Faker {
2 | public final class Team: Generator {
3 | public func name() -> String {
4 | return generate("team.name")
5 | }
6 |
7 | public func creature() -> String {
8 | return generate("team.creature")
9 | }
10 |
11 | public func state() -> String {
12 | return generate("address.state").capitalized
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Vehicle.swift:
--------------------------------------------------------------------------------
1 | extension Faker {
2 | public final class Vehicle: Generator {
3 | public func manufacture() -> String {
4 | return generate("vehicle.manufacture")
5 | }
6 |
7 | public func make() -> String {
8 | return generate("vehicle.makes")
9 | }
10 |
11 | public func colors() -> String {
12 | return generate("vehicle.colors")
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Generators/Zelda.swift:
--------------------------------------------------------------------------------
1 | extension Faker {
2 | public final class Zelda: Generator {
3 | public func game() -> String {
4 | return generate("zelda.game")
5 | }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Resources/Locales/de-CH.json:
--------------------------------------------------------------------------------
1 | {
2 | "de-CH": {
3 | "faker": {
4 | "address": {
5 | "country_code": [
6 | "CH",
7 | "CH",
8 | "CH",
9 | "DE",
10 | "AT",
11 | "US",
12 | "LI",
13 | "US",
14 | "HK",
15 | "VN"
16 | ],
17 | "postcode": [
18 | "1###",
19 | "2###",
20 | "3###",
21 | "4###",
22 | "5###",
23 | "6###",
24 | "7###",
25 | "8###",
26 | "9###"
27 | ],
28 | "default_country": [
29 | "Schweiz"
30 | ]
31 | },
32 | "company": {
33 | "suffix": [
34 | "AG",
35 | "GmbH",
36 | "und Söhne",
37 | "und Partner",
38 | "& Co.",
39 | "Gruppe",
40 | "LLC",
41 | "Inc."
42 | ],
43 | "name": [
44 | "#{Name.last_name} #{suffix}",
45 | "#{Name.last_name}-#{Name.last_name}",
46 | "#{Name.last_name}, #{Name.last_name} und #{Name.last_name}"
47 | ]
48 | },
49 | "internet": {
50 | "domain_suffix": [
51 | "com",
52 | "net",
53 | "biz",
54 | "ch",
55 | "de",
56 | "li",
57 | "at",
58 | "ch",
59 | "ch"
60 | ]
61 | },
62 | "phone_number": {
63 | "formats": [
64 | "0800 ### ###",
65 | "0800 ## ## ##",
66 | "0## ### ## ##",
67 | "0## ### ## ##",
68 | "+41 ## ### ## ##",
69 | "0900 ### ###",
70 | "076 ### ## ##",
71 | "+4178 ### ## ##",
72 | "0041 79 ### ## ##"
73 | ]
74 | }
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Resources/Locales/en-CA.json:
--------------------------------------------------------------------------------
1 | {
2 | "en-CA": {
3 | "faker": {
4 | "address": {
5 | "postcode": "/[A-CEJ-NPR-TVXY][0-9][A-CEJ-NPR-TV-Z] ?[0-9][A-CEJ-NPR-TV-Z][0-9]/",
6 | "state": [
7 | "Alberta",
8 | "British Columbia",
9 | "Manitoba",
10 | "New Brunswick",
11 | "Newfoundland and Labrador",
12 | "Nova Scotia",
13 | "Northwest Territories",
14 | "Nunavut",
15 | "Ontario",
16 | "Prince Edward Island",
17 | "Quebec",
18 | "Saskatchewan",
19 | "Yukon"
20 | ],
21 | "state_abbr": [
22 | "AB",
23 | "BC",
24 | "MB",
25 | "NB",
26 | "NL",
27 | "NS",
28 | "NU",
29 | "NT",
30 | "ON",
31 | "PE",
32 | "QC",
33 | "SK",
34 | "YT"
35 | ],
36 | "default_country": [
37 | "Canada"
38 | ]
39 | },
40 | "internet": {
41 | "free_email": [
42 | "gmail.com",
43 | "yahoo.ca",
44 | "hotmail.com"
45 | ],
46 | "domain_suffix": [
47 | "ca",
48 | "com",
49 | "biz",
50 | "info",
51 | "name",
52 | "net",
53 | "org"
54 | ]
55 | },
56 | "phone_number": {
57 | "formats": [
58 | "###-###-####",
59 | "(###)###-####",
60 | "###.###.####",
61 | "1-###-###-####",
62 | "###-###-#### x###",
63 | "(###)###-#### x###",
64 | "1-###-###-#### x###",
65 | "###.###.#### x###",
66 | "###-###-#### x####",
67 | "(###)###-#### x####",
68 | "1-###-###-#### x####",
69 | "###.###.#### x####",
70 | "###-###-#### x#####",
71 | "(###)###-#### x#####",
72 | "1-###-###-#### x#####",
73 | "###.###.#### x#####"
74 | ]
75 | }
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Resources/Locales/en-GB.json:
--------------------------------------------------------------------------------
1 | {
2 | "en-GB": {
3 | "faker": {
4 | "address": {
5 | "postcode": "/[A-PR-UWYZ][A-HK-Y]?[0-9][ABEHMNPRVWXY0-9]? [0-9][ABD-HJLN-UW-Z]{2}/",
6 | "county": [
7 | "Avon",
8 | "Bedfordshire",
9 | "Berkshire",
10 | "Borders",
11 | "Buckinghamshire",
12 | "Cambridgeshire",
13 | "Central",
14 | "Cheshire",
15 | "Cleveland",
16 | "Clwyd",
17 | "Cornwall",
18 | "County Antrim",
19 | "County Armagh",
20 | "County Down",
21 | "County Fermanagh",
22 | "County Londonderry",
23 | "County Tyrone",
24 | "Cumbria",
25 | "Derbyshire",
26 | "Devon",
27 | "Dorset",
28 | "Dumfries and Galloway",
29 | "Durham",
30 | "Dyfed",
31 | "East Sussex",
32 | "Essex",
33 | "Fife",
34 | "Gloucestershire",
35 | "Grampian",
36 | "Greater Manchester",
37 | "Gwent",
38 | "Gwynedd County",
39 | "Hampshire",
40 | "Herefordshire",
41 | "Hertfordshire",
42 | "Highlands and Islands",
43 | "Humberside",
44 | "Isle of Wight",
45 | "Kent",
46 | "Lancashire",
47 | "Leicestershire",
48 | "Lincolnshire",
49 | "Lothian",
50 | "Merseyside",
51 | "Mid Glamorgan",
52 | "Norfolk",
53 | "North Yorkshire",
54 | "Northamptonshire",
55 | "Northumberland",
56 | "Nottinghamshire",
57 | "Oxfordshire",
58 | "Powys",
59 | "Rutland",
60 | "Shropshire",
61 | "Somerset",
62 | "South Glamorgan",
63 | "South Yorkshire",
64 | "Staffordshire",
65 | "Strathclyde",
66 | "Suffolk",
67 | "Surrey",
68 | "Tayside",
69 | "Tyne and Wear",
70 | "Warwickshire",
71 | "West Glamorgan",
72 | "West Midlands",
73 | "West Sussex",
74 | "West Yorkshire",
75 | "Wiltshire",
76 | "Worcestershire"
77 | ],
78 | "uk_country": [
79 | "England",
80 | "Scotland",
81 | "Wales",
82 | "Northern Ireland"
83 | ],
84 | "default_country": [
85 | "England",
86 | "Scotland",
87 | "Wales",
88 | "Northern Ireland"
89 | ]
90 | },
91 | "internet": {
92 | "domain_suffix": [
93 | "co.uk",
94 | "com",
95 | "biz",
96 | "info",
97 | "name"
98 | ]
99 | },
100 | "phone_number": {
101 | "formats": [
102 | "01#### #####",
103 | "01### ######",
104 | "01#1 ### ####",
105 | "011# ### ####",
106 | "02# #### ####",
107 | "03## ### ####",
108 | "055 #### ####",
109 | "056 #### ####",
110 | "0800 ### ####",
111 | "08## ### ####",
112 | "09## ### ####",
113 | "016977 ####",
114 | "01### #####",
115 | "0500 ######",
116 | "0800 ######"
117 | ]
118 | },
119 | "cell_phone": {
120 | "formats": [
121 | "074## ######",
122 | "075## ######",
123 | "076## ######",
124 | "077## ######",
125 | "078## ######",
126 | "079## ######"
127 | ]
128 | }
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Resources/Locales/ja.json:
--------------------------------------------------------------------------------
1 | {
2 | "ja": {
3 | "faker": {
4 | "address": {
5 | "postcode": [
6 | "###-####"
7 | ],
8 | "state": [
9 | "北海道",
10 | "青森県",
11 | "岩手県",
12 | "宮城県",
13 | "秋田県",
14 | "山形県",
15 | "福島県",
16 | "茨城県",
17 | "栃木県",
18 | "群馬県",
19 | "埼玉県",
20 | "千葉県",
21 | "東京都",
22 | "神奈川県",
23 | "新潟県",
24 | "富山県",
25 | "石川県",
26 | "福井県",
27 | "山梨県",
28 | "長野県",
29 | "岐阜県",
30 | "静岡県",
31 | "愛知県",
32 | "三重県",
33 | "滋賀県",
34 | "京都府",
35 | "大阪府",
36 | "兵庫県",
37 | "奈良県",
38 | "和歌山県",
39 | "鳥取県",
40 | "島根県",
41 | "岡山県",
42 | "広島県",
43 | "山口県",
44 | "徳島県",
45 | "香川県",
46 | "愛媛県",
47 | "高知県",
48 | "福岡県",
49 | "佐賀県",
50 | "長崎県",
51 | "熊本県",
52 | "大分県",
53 | "宮崎県",
54 | "鹿児島県",
55 | "沖縄県"
56 | ],
57 | "state_abbr": [
58 | "1",
59 | "2",
60 | "3",
61 | "4",
62 | "5",
63 | "6",
64 | "7",
65 | "8",
66 | "9",
67 | "10",
68 | "11",
69 | "12",
70 | "13",
71 | "14",
72 | "15",
73 | "16",
74 | "17",
75 | "18",
76 | "19",
77 | "20",
78 | "21",
79 | "22",
80 | "23",
81 | "24",
82 | "25",
83 | "26",
84 | "27",
85 | "28",
86 | "29",
87 | "30",
88 | "31",
89 | "32",
90 | "33",
91 | "34",
92 | "35",
93 | "36",
94 | "37",
95 | "38",
96 | "39",
97 | "40",
98 | "41",
99 | "42",
100 | "43",
101 | "44",
102 | "45",
103 | "46",
104 | "47"
105 | ],
106 | "city_prefix": [
107 | "北",
108 | "東",
109 | "西",
110 | "南",
111 | "新",
112 | "湖",
113 | "港"
114 | ],
115 | "city_suffix": [
116 | "市",
117 | "区",
118 | "町",
119 | "村"
120 | ],
121 | "city": [
122 | "#{city_prefix}#{Name.first_name}#{city_suffix}",
123 | "#{Name.first_name}#{city_suffix}",
124 | "#{city_prefix}#{Name.last_name}#{city_suffix}",
125 | "#{Name.last_name}#{city_suffix}"
126 | ],
127 | "street_name": [
128 | "#{Name.first_name}#{street_suffix}",
129 | "#{Name.last_name}#{street_suffix}"
130 | ]
131 | },
132 | "phone_number": {
133 | "formats": [
134 | "0####-#-####",
135 | "0###-##-####",
136 | "0##-###-####",
137 | "0#-####-####"
138 | ]
139 | },
140 | "cell_phone": {
141 | "formats": [
142 | "090-####-####",
143 | "080-####-####",
144 | "070-####-####"
145 | ]
146 | },
147 | "name": {
148 | "last_name": [
149 | "佐藤",
150 | "鈴木",
151 | "高橋",
152 | "田中",
153 | "渡辺",
154 | "伊藤",
155 | "山本",
156 | "中村",
157 | "小林",
158 | "加藤",
159 | "吉田",
160 | "山田",
161 | "佐々木",
162 | "山口",
163 | "斎藤",
164 | "松本",
165 | "井上",
166 | "木村",
167 | "林",
168 | "清水"
169 | ],
170 | "first_name": [
171 | "大翔",
172 | "蓮",
173 | "颯太",
174 | "樹",
175 | "大和",
176 | "陽翔",
177 | "陸斗",
178 | "太一",
179 | "海翔",
180 | "蒼空",
181 | "翼",
182 | "陽菜",
183 | "結愛",
184 | "結衣",
185 | "杏",
186 | "莉子",
187 | "美羽",
188 | "結菜",
189 | "心愛",
190 | "愛菜",
191 | "美咲"
192 | ],
193 | "name": [
194 | "#{last_name} #{first_name}"
195 | ]
196 | },
197 | "gender": {
198 | "binary_type": [
199 | "女性",
200 | "男性"
201 | ]
202 | }
203 | }
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/Pods/Fakery/Sources/Fakery/Resources/Locales/nl.json:
--------------------------------------------------------------------------------
1 | {
2 | "nl": {
3 | "faker": {
4 | "address": {
5 | "postcode": "####??"
6 | },
7 | "bank": {
8 | "name": [
9 | "UBS CLEARING AND EXECUTION SERVICES LIMITED",
10 | "ABN AMRO CORPORATE FINANCE LIMITED",
11 | "ABN AMRO FUND MANAGERS LIMITED",
12 | "ABN AMRO HOARE GOVETT SECURITIES",
13 | "ABN AMRO HOARE GOVETT CORPORATE FINANCE LTD.",
14 | "ALKEN ASSET MANAGEMENT",
15 | "ABN AMRO HOARE GOVETT LIMITED",
16 | "AAC CAPITAL PARTNERS LIMITED",
17 | "ABBOTSTONE AGRICULTURAL PROPERTY UNIT TRUST",
18 | "ABN AMRO QUOTED INVESTMENTS (UK) LIMITED",
19 | "ABN AMRO MEZZANINE (UK) LIMITED",
20 | "ABBEY LIFE",
21 | "SANTANDER UK PLC",
22 | "OTKRITIE SECURITIES LIMITED",
23 | "ABC INTERNATIONAL BANK PLC",
24 | "ALLIED BANK PHILIPPINES (UK) PLC",
25 | "ABU DHABI ISLAMIC BANK",
26 | "ABG SUNDAL COLLIER LIMITED",
27 | "PGMS (GLASGOW) LIMITED",
28 | "ABINGWORTH MANAGEMENT LIMITED",
29 | "THE ROYAL BANK OF SCOTLAND PLC (FORMER RBS NV)"
30 | ],
31 | "swiftBic": [
32 | "AACCGB21",
33 | "AACNGB21",
34 | "AAFMGB21",
35 | "AAHOGB21",
36 | "AAHVGB21",
37 | "AANLGB21",
38 | "AANLGB2L",
39 | "AAOGGB21",
40 | "AAPEGB21",
41 | "AAPUGB21",
42 | "AAQIGB21",
43 | "ABAZGB21",
44 | "ABBEGB21",
45 | "ABBYGB2L",
46 | "ABCCGB22",
47 | "ABCEGB2L",
48 | "ABCMGB21",
49 | "ABDIGB21",
50 | "ABECGB21",
51 | "ABFIGB21",
52 | "ABMNGB21",
53 | "ABNAGB21VOC"
54 | ],
55 | "ibanDetails": {
56 | "bankCountryCode": "NL",
57 | "ibanLetterCode": ["RABO", "BUNQ", "ABNA", "INGB"],
58 | "ibanDigits": "############",
59 | }
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 Wei Wang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Cache/Storage.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Storage.swift
3 | // Kingfisher
4 | //
5 | // Created by Wei Wang on 2018/10/15.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 |
29 | /// Constants for some time intervals
30 | struct TimeConstants {
31 | static let secondsInOneMinute = 60
32 | static let minutesInOneHour = 60
33 | static let hoursInOneDay = 24
34 | static let secondsInOneDay = 86_400
35 | }
36 |
37 | /// Represents the expiration strategy used in storage.
38 | ///
39 | /// - never: The item never expires.
40 | /// - seconds: The item expires after a time duration of given seconds from now.
41 | /// - days: The item expires after a time duration of given days from now.
42 | /// - date: The item expires after a given date.
43 | public enum StorageExpiration {
44 | /// The item never expires.
45 | case never
46 | /// The item expires after a time duration of given seconds from now.
47 | case seconds(TimeInterval)
48 | /// The item expires after a time duration of given days from now.
49 | case days(Int)
50 | /// The item expires after a given date.
51 | case date(Date)
52 | /// Indicates the item is already expired. Use this to skip cache.
53 | case expired
54 |
55 | func estimatedExpirationSince(_ date: Date) -> Date {
56 | switch self {
57 | case .never: return .distantFuture
58 | case .seconds(let seconds):
59 | return date.addingTimeInterval(seconds)
60 | case .days(let days):
61 | let duration: TimeInterval = TimeInterval(TimeConstants.secondsInOneDay) * TimeInterval(days)
62 | return date.addingTimeInterval(duration)
63 | case .date(let ref):
64 | return ref
65 | case .expired:
66 | return .distantPast
67 | }
68 | }
69 |
70 | var estimatedExpirationSinceNow: Date {
71 | return estimatedExpirationSince(Date())
72 | }
73 |
74 | var isExpired: Bool {
75 | return timeInterval <= 0
76 | }
77 |
78 | var timeInterval: TimeInterval {
79 | switch self {
80 | case .never: return .infinity
81 | case .seconds(let seconds): return seconds
82 | case .days(let days): return TimeInterval(TimeConstants.secondsInOneDay) * TimeInterval(days)
83 | case .date(let ref): return ref.timeIntervalSinceNow
84 | case .expired: return -(.infinity)
85 | }
86 | }
87 | }
88 |
89 | /// Represents the expiration extending strategy used in storage to after access.
90 | ///
91 | /// - none: The item expires after the original time, without extending after access.
92 | /// - cacheTime: The item expiration extends by the original cache time after each access.
93 | /// - expirationTime: The item expiration extends by the provided time after each access.
94 | public enum ExpirationExtending {
95 | /// The item expires after the original time, without extending after access.
96 | case none
97 | /// The item expiration extends by the original cache time after each access.
98 | case cacheTime
99 | /// The item expiration extends by the provided time after each access.
100 | case expirationTime(_ expiration: StorageExpiration)
101 | }
102 |
103 | /// Represents types which cost in memory can be calculated.
104 | public protocol CacheCostCalculable {
105 | var cacheCost: Int { get }
106 | }
107 |
108 | /// Represents types which can be converted to and from data.
109 | public protocol DataTransformable {
110 | func toData() throws -> Data
111 | static func fromData(_ data: Data) throws -> Self
112 | static var empty: Self { get }
113 | }
114 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/General/ImageSource/Resource.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Resource.swift
3 | // Kingfisher
4 | //
5 | // Created by Wei Wang on 15/4/6.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 |
29 | /// Represents an image resource at a certain url and a given cache key.
30 | /// Kingfisher will use a `Resource` to download a resource from network and cache it with the cache key when
31 | /// using `Source.network` as its image setting source.
32 | public protocol Resource {
33 |
34 | /// The key used in cache.
35 | var cacheKey: String { get }
36 |
37 | /// The target image URL.
38 | var downloadURL: URL { get }
39 | }
40 |
41 | extension Resource {
42 |
43 | /// Converts `self` to a valid `Source` based on its `downloadURL` scheme. A `.provider` with
44 | /// `LocalFileImageDataProvider` associated will be returned if the URL points to a local file. Otherwise,
45 | /// `.network` is returned.
46 | public func convertToSource() -> Source {
47 | return downloadURL.isFileURL ?
48 | .provider(LocalFileImageDataProvider(fileURL: downloadURL, cacheKey: cacheKey)) :
49 | .network(self)
50 | }
51 | }
52 |
53 | /// ImageResource is a simple combination of `downloadURL` and `cacheKey`.
54 | /// When passed to image view set methods, Kingfisher will try to download the target
55 | /// image from the `downloadURL`, and then store it with the `cacheKey` as the key in cache.
56 | public struct ImageResource: Resource {
57 |
58 | // MARK: - Initializers
59 |
60 | /// Creates an image resource.
61 | ///
62 | /// - Parameters:
63 | /// - downloadURL: The target image URL from where the image can be downloaded.
64 | /// - cacheKey: The cache key. If `nil`, Kingfisher will use the `absoluteString` of `downloadURL` as the key.
65 | /// Default is `nil`.
66 | public init(downloadURL: URL, cacheKey: String? = nil) {
67 | self.downloadURL = downloadURL
68 | self.cacheKey = cacheKey ?? downloadURL.absoluteString
69 | }
70 |
71 | // MARK: Protocol Conforming
72 |
73 | /// The key used in cache.
74 | public let cacheKey: String
75 |
76 | /// The target image URL.
77 | public let downloadURL: URL
78 | }
79 |
80 | /// URL conforms to `Resource` in Kingfisher.
81 | /// The `absoluteString` of this URL is used as `cacheKey`. And the URL itself will be used as `downloadURL`.
82 | /// If you need customize the url and/or cache key, use `ImageResource` instead.
83 | extension URL: Resource {
84 | public var cacheKey: String { return absoluteString }
85 | public var downloadURL: URL { return self }
86 | }
87 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/General/ImageSource/Source.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Source.swift
3 | // Kingfisher
4 | //
5 | // Created by onevcat on 2018/11/17.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 |
29 | /// Represents an image setting source for Kingfisher methods.
30 | ///
31 | /// A `Source` value indicates the way how the target image can be retrieved and cached.
32 | ///
33 | /// - network: The target image should be got from network remotely. The associated `Resource`
34 | /// value defines detail information like image URL and cache key.
35 | /// - provider: The target image should be provided in a data format. Normally, it can be an image
36 | /// from local storage or in any other encoding format (like Base64).
37 | public enum Source {
38 |
39 | /// Represents the source task identifier when setting an image to a view with extension methods.
40 | public enum Identifier {
41 |
42 | /// The underlying value type of source identifier.
43 | public typealias Value = UInt
44 | static var current: Value = 0
45 | static func next() -> Value {
46 | current += 1
47 | return current
48 | }
49 | }
50 |
51 | // MARK: Member Cases
52 |
53 | /// The target image should be got from network remotely. The associated `Resource`
54 | /// value defines detail information like image URL and cache key.
55 | case network(Resource)
56 |
57 | /// The target image should be provided in a data format. Normally, it can be an image
58 | /// from local storage or in any other encoding format (like Base64).
59 | case provider(ImageDataProvider)
60 |
61 | // MARK: Getting Properties
62 |
63 | /// The cache key defined for this source value.
64 | public var cacheKey: String {
65 | switch self {
66 | case .network(let resource): return resource.cacheKey
67 | case .provider(let provider): return provider.cacheKey
68 | }
69 | }
70 |
71 | /// The URL defined for this source value.
72 | ///
73 | /// For a `.network` source, it is the `downloadURL` of associated `Resource` instance.
74 | /// For a `.provider` value, it is always `nil`.
75 | public var url: URL? {
76 | switch self {
77 | case .network(let resource): return resource.downloadURL
78 | case .provider(let provider): return provider.contentURL
79 | }
80 | }
81 | }
82 |
83 | extension Source {
84 | var asResource: Resource? {
85 | guard case .network(let resource) = self else {
86 | return nil
87 | }
88 | return resource
89 | }
90 |
91 | var asProvider: ImageDataProvider? {
92 | guard case .provider(let provider) = self else {
93 | return nil
94 | }
95 | return provider
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/General/Kingfisher.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Kingfisher.swift
3 | // Kingfisher
4 | //
5 | // Created by Wei Wang on 16/9/14.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 | import ImageIO
29 |
30 | #if os(macOS)
31 | import AppKit
32 | public typealias KFCrossPlatformImage = NSImage
33 | public typealias KFCrossPlatformView = NSView
34 | public typealias KFCrossPlatformColor = NSColor
35 | public typealias KFCrossPlatformImageView = NSImageView
36 | public typealias KFCrossPlatformButton = NSButton
37 | #else
38 | import UIKit
39 | public typealias KFCrossPlatformImage = UIImage
40 | public typealias KFCrossPlatformColor = UIColor
41 | #if !os(watchOS)
42 | public typealias KFCrossPlatformImageView = UIImageView
43 | public typealias KFCrossPlatformView = UIView
44 | public typealias KFCrossPlatformButton = UIButton
45 | #if canImport(TVUIKit)
46 | import TVUIKit
47 | #endif
48 | #else
49 | import WatchKit
50 | #endif
51 | #endif
52 |
53 | /// Wrapper for Kingfisher compatible types. This type provides an extension point for
54 | /// connivence methods in Kingfisher.
55 | public struct KingfisherWrapper {
56 | public let base: Base
57 | public init(_ base: Base) {
58 | self.base = base
59 | }
60 | }
61 |
62 | /// Represents an object type that is compatible with Kingfisher. You can use `kf` property to get a
63 | /// value in the namespace of Kingfisher.
64 | public protocol KingfisherCompatible: AnyObject { }
65 |
66 | /// Represents a value type that is compatible with Kingfisher. You can use `kf` property to get a
67 | /// value in the namespace of Kingfisher.
68 | public protocol KingfisherCompatibleValue {}
69 |
70 | extension KingfisherCompatible {
71 | /// Gets a namespace holder for Kingfisher compatible types.
72 | public var kf: KingfisherWrapper {
73 | get { return KingfisherWrapper(self) }
74 | set { }
75 | }
76 | }
77 |
78 | extension KingfisherCompatibleValue {
79 | /// Gets a namespace holder for Kingfisher compatible types.
80 | public var kf: KingfisherWrapper {
81 | get { return KingfisherWrapper(self) }
82 | set { }
83 | }
84 | }
85 |
86 | extension KFCrossPlatformImage: KingfisherCompatible { }
87 | #if !os(watchOS)
88 | extension KFCrossPlatformImageView: KingfisherCompatible { }
89 | extension KFCrossPlatformButton: KingfisherCompatible { }
90 | extension NSTextAttachment: KingfisherCompatible { }
91 | #else
92 | extension WKInterfaceImage: KingfisherCompatible { }
93 | #endif
94 |
95 | #if os(tvOS) && canImport(TVUIKit)
96 | @available(tvOS 12.0, *)
97 | extension TVMonogramView: KingfisherCompatible { }
98 | #endif
99 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Image/Placeholder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Placeholder.swift
3 | // Kingfisher
4 | //
5 | // Created by Tieme van Veen on 28/08/2017.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #if !os(watchOS)
28 |
29 | #if canImport(AppKit) && !targetEnvironment(macCatalyst)
30 | import AppKit
31 | #endif
32 |
33 | #if canImport(UIKit)
34 | import UIKit
35 | #endif
36 |
37 | /// Represents a placeholder type which could be set while loading as well as
38 | /// loading finished without getting an image.
39 | public protocol Placeholder {
40 |
41 | /// How the placeholder should be added to a given image view.
42 | func add(to imageView: KFCrossPlatformImageView)
43 |
44 | /// How the placeholder should be removed from a given image view.
45 | func remove(from imageView: KFCrossPlatformImageView)
46 | }
47 |
48 | /// Default implementation of an image placeholder. The image will be set or
49 | /// reset directly for `image` property of the image view.
50 | extension KFCrossPlatformImage: Placeholder {
51 | /// How the placeholder should be added to a given image view.
52 | public func add(to imageView: KFCrossPlatformImageView) { imageView.image = self }
53 |
54 | /// How the placeholder should be removed from a given image view.
55 | public func remove(from imageView: KFCrossPlatformImageView) { imageView.image = nil }
56 | }
57 |
58 | /// Default implementation of an arbitrary view as placeholder. The view will be
59 | /// added as a subview when adding and be removed from its super view when removing.
60 | ///
61 | /// To use your customize View type as placeholder, simply let it conforming to
62 | /// `Placeholder` by `extension MyView: Placeholder {}`.
63 | extension Placeholder where Self: KFCrossPlatformView {
64 |
65 | /// How the placeholder should be added to a given image view.
66 | public func add(to imageView: KFCrossPlatformImageView) {
67 | imageView.addSubview(self)
68 | translatesAutoresizingMaskIntoConstraints = false
69 |
70 | centerXAnchor.constraint(equalTo: imageView.centerXAnchor).isActive = true
71 | centerYAnchor.constraint(equalTo: imageView.centerYAnchor).isActive = true
72 | heightAnchor.constraint(equalTo: imageView.heightAnchor).isActive = true
73 | widthAnchor.constraint(equalTo: imageView.widthAnchor).isActive = true
74 | }
75 |
76 | /// How the placeholder should be removed from a given image view.
77 | public func remove(from imageView: KFCrossPlatformImageView) {
78 | removeFromSuperview()
79 | }
80 | }
81 |
82 | #endif
83 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Kingfisher.h:
--------------------------------------------------------------------------------
1 | //
2 | // Kingfisher.h
3 | // Kingfisher
4 | //
5 | // Created by Wei Wang on 15/4/6.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 | //! Project version number for Kingfisher.
30 | FOUNDATION_EXPORT double KingfisherVersionNumber;
31 |
32 | //! Project version string for Kingfisher.
33 | FOUNDATION_EXPORT const unsigned char KingfisherVersionString[];
34 |
35 | // In this header, you should import all the public headers of your framework using statements like #import
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Networking/AuthenticationChallengeResponsable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AuthenticationChallengeResponsable.swift
3 | // Kingfisher
4 | //
5 | // Created by Wei Wang on 2018/10/11.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 |
29 | /// Protocol indicates that an authentication challenge could be handled.
30 | public protocol AuthenticationChallengeResponsable: AnyObject {
31 |
32 | /// Called when a session level authentication challenge is received.
33 | /// This method provide a chance to handle and response to the authentication
34 | /// challenge before downloading could start.
35 | ///
36 | /// - Parameters:
37 | /// - downloader: The downloader which receives this challenge.
38 | /// - challenge: An object that contains the request for authentication.
39 | /// - completionHandler: A handler that your delegate method must call.
40 | ///
41 | /// - Note: This method is a forward from `URLSessionDelegate.urlSession(:didReceiveChallenge:completionHandler:)`.
42 | /// Please refer to the document of it in `URLSessionDelegate`.
43 | func downloader(
44 | _ downloader: ImageDownloader,
45 | didReceive challenge: URLAuthenticationChallenge,
46 | completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
47 |
48 | /// Called when a task level authentication challenge is received.
49 | /// This method provide a chance to handle and response to the authentication
50 | /// challenge before downloading could start.
51 | ///
52 | /// - Parameters:
53 | /// - downloader: The downloader which receives this challenge.
54 | /// - task: The task whose request requires authentication.
55 | /// - challenge: An object that contains the request for authentication.
56 | /// - completionHandler: A handler that your delegate method must call.
57 | func downloader(
58 | _ downloader: ImageDownloader,
59 | task: URLSessionTask,
60 | didReceive challenge: URLAuthenticationChallenge,
61 | completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
62 | }
63 |
64 | extension AuthenticationChallengeResponsable {
65 |
66 | public func downloader(
67 | _ downloader: ImageDownloader,
68 | didReceive challenge: URLAuthenticationChallenge,
69 | completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
70 | {
71 | if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
72 | if let trustedHosts = downloader.trustedHosts, trustedHosts.contains(challenge.protectionSpace.host) {
73 | let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
74 | completionHandler(.useCredential, credential)
75 | return
76 | }
77 | }
78 |
79 | completionHandler(.performDefaultHandling, nil)
80 | }
81 |
82 | public func downloader(
83 | _ downloader: ImageDownloader,
84 | task: URLSessionTask,
85 | didReceive challenge: URLAuthenticationChallenge,
86 | completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
87 | {
88 | completionHandler(.performDefaultHandling, nil)
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Networking/ImageDataProcessor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImageDataProcessor.swift
3 | // Kingfisher
4 | //
5 | // Created by Wei Wang on 2018/10/11.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 |
29 | private let sharedProcessingQueue: CallbackQueue =
30 | .dispatch(DispatchQueue(label: "com.onevcat.Kingfisher.ImageDownloader.Process"))
31 |
32 | // Handles image processing work on an own process queue.
33 | class ImageDataProcessor {
34 | let data: Data
35 | let callbacks: [SessionDataTask.TaskCallback]
36 | let queue: CallbackQueue
37 |
38 | // Note: We have an optimization choice there, to reduce queue dispatch by checking callback
39 | // queue settings in each option...
40 | let onImageProcessed = Delegate<(Result, SessionDataTask.TaskCallback), Void>()
41 |
42 | init(data: Data, callbacks: [SessionDataTask.TaskCallback], processingQueue: CallbackQueue?) {
43 | self.data = data
44 | self.callbacks = callbacks
45 | self.queue = processingQueue ?? sharedProcessingQueue
46 | }
47 |
48 | func process() {
49 | queue.execute(doProcess)
50 | }
51 |
52 | private func doProcess() {
53 | var processedImages = [String: KFCrossPlatformImage]()
54 | for callback in callbacks {
55 | let processor = callback.options.processor
56 | var image = processedImages[processor.identifier]
57 | if image == nil {
58 | image = processor.process(item: .data(data), options: callback.options)
59 | processedImages[processor.identifier] = image
60 | }
61 |
62 | let result: Result
63 | if let image = image {
64 | var finalImage = image
65 | if let imageModifier = callback.options.imageModifier {
66 | finalImage = imageModifier.modify(image)
67 | }
68 | if callback.options.backgroundDecode {
69 | finalImage = finalImage.kf.decoded
70 | }
71 | result = .success(finalImage)
72 | } else {
73 | let error = KingfisherError.processorError(
74 | reason: .processingFailed(processor: processor, item: .data(data)))
75 | result = .failure(error)
76 | }
77 | onImageProcessed.call((result, callback))
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Networking/RedirectHandler.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RedirectHandler.swift
3 | // Kingfisher
4 | //
5 | // Created by Roman Maidanovych on 2018/12/10.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 |
29 | /// Represents and wraps a method for modifying request during an image download request redirection.
30 | public protocol ImageDownloadRedirectHandler {
31 |
32 | /// The `ImageDownloadRedirectHandler` contained will be used to change the request before redirection.
33 | /// This is the posibility you can modify the image download request during redirection. You can modify the
34 | /// request for some customizing purpose, such as adding auth token to the header, do basic HTTP auth or
35 | /// something like url mapping.
36 | ///
37 | /// Usually, you pass an `ImageDownloadRedirectHandler` as the associated value of
38 | /// `KingfisherOptionsInfoItem.redirectHandler` and use it as the `options` parameter in related methods.
39 | ///
40 | /// If you do nothing with the input `request` and return it as is, a downloading process will redirect with it.
41 | ///
42 | /// - Parameters:
43 | /// - task: The current `SessionDataTask` which triggers this redirect.
44 | /// - response: The response received during redirection.
45 | /// - newRequest: The request for redirection which can be modified.
46 | /// - completionHandler: A closure for being called with modified request.
47 | func handleHTTPRedirection(
48 | for task: SessionDataTask,
49 | response: HTTPURLResponse,
50 | newRequest: URLRequest,
51 | completionHandler: @escaping (URLRequest?) -> Void)
52 | }
53 |
54 | /// A wrapper for creating an `ImageDownloadRedirectHandler` easier.
55 | /// This type conforms to `ImageDownloadRedirectHandler` and wraps a redirect request modify block.
56 | public struct AnyRedirectHandler: ImageDownloadRedirectHandler {
57 |
58 | let block: (SessionDataTask, HTTPURLResponse, URLRequest, @escaping (URLRequest?) -> Void) -> Void
59 |
60 | public func handleHTTPRedirection(
61 | for task: SessionDataTask,
62 | response: HTTPURLResponse,
63 | newRequest: URLRequest,
64 | completionHandler: @escaping (URLRequest?) -> Void)
65 | {
66 | block(task, response, newRequest, completionHandler)
67 | }
68 |
69 | /// Creates a value of `ImageDownloadRedirectHandler` which runs `modify` block.
70 | ///
71 | /// - Parameter modify: The request modifying block runs when a request modifying task comes.
72 | ///
73 | public init(handle: @escaping (SessionDataTask, HTTPURLResponse, URLRequest, @escaping (URLRequest?) -> Void) -> Void) {
74 | block = handle
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Utility/Box.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Box.swift
3 | // Kingfisher
4 | //
5 | // Created by Wei Wang on 2018/3/17.
6 | // Copyright (c) 2019 Wei Wang
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import Foundation
27 |
28 | class Box {
29 | var value: T
30 |
31 | init(_ value: T) {
32 | self.value = value
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Utility/CallbackQueue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CallbackQueue.swift
3 | // Kingfisher
4 | //
5 | // Created by onevcat on 2018/10/15.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 |
29 | /// Represents callback queue behaviors when an calling of closure be dispatched.
30 | ///
31 | /// - asyncMain: Dispatch the calling to `DispatchQueue.main` with an `async` behavior.
32 | /// - currentMainOrAsync: Dispatch the calling to `DispatchQueue.main` with an `async` behavior if current queue is not
33 | /// `.main`. Otherwise, call the closure immediately in current main queue.
34 | /// - untouch: Do not change the calling queue for closure.
35 | /// - dispatch: Dispatches to a specified `DispatchQueue`.
36 | public enum CallbackQueue {
37 | /// Dispatch the calling to `DispatchQueue.main` with an `async` behavior.
38 | case mainAsync
39 | /// Dispatch the calling to `DispatchQueue.main` with an `async` behavior if current queue is not
40 | /// `.main`. Otherwise, call the closure immediately in current main queue.
41 | case mainCurrentOrAsync
42 | /// Do not change the calling queue for closure.
43 | case untouch
44 | /// Dispatches to a specified `DispatchQueue`.
45 | case dispatch(DispatchQueue)
46 |
47 | public func execute(_ block: @escaping () -> Void) {
48 | switch self {
49 | case .mainAsync:
50 | DispatchQueue.main.async { block() }
51 | case .mainCurrentOrAsync:
52 | DispatchQueue.main.safeAsync { block() }
53 | case .untouch:
54 | block()
55 | case .dispatch(let queue):
56 | queue.async { block() }
57 | }
58 | }
59 |
60 | var queue: DispatchQueue {
61 | switch self {
62 | case .mainAsync: return .main
63 | case .mainCurrentOrAsync: return .main
64 | case .untouch: return OperationQueue.current?.underlyingQueue ?? .main
65 | case .dispatch(let queue): return queue
66 | }
67 | }
68 | }
69 |
70 | extension DispatchQueue {
71 | // This method will dispatch the `block` to self.
72 | // If `self` is the main queue, and current thread is main thread, the block
73 | // will be invoked immediately instead of being dispatched.
74 | func safeAsync(_ block: @escaping ()->()) {
75 | if self === DispatchQueue.main && Thread.isMainThread {
76 | block()
77 | } else {
78 | async { block() }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Utility/Delegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Delegate.swift
3 | // Kingfisher
4 | //
5 | // Created by onevcat on 2018/10/10.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 | /// A class that keeps a weakly reference for `self` when implementing `onXXX` behaviors.
29 | /// Instead of remembering to keep `self` as weak in a stored closure:
30 | ///
31 | /// ```swift
32 | /// // MyClass.swift
33 | /// var onDone: (() -> Void)?
34 | /// func done() {
35 | /// onDone?()
36 | /// }
37 | ///
38 | /// // ViewController.swift
39 | /// var obj: MyClass?
40 | ///
41 | /// func doSomething() {
42 | /// obj = MyClass()
43 | /// obj!.onDone = { [weak self] in
44 | /// self?.reportDone()
45 | /// }
46 | /// }
47 | /// ```
48 | ///
49 | /// You can create a `Delegate` and observe on `self`. Now, there is no retain cycle inside:
50 | ///
51 | /// ```swift
52 | /// // MyClass.swift
53 | /// let onDone = Delegate<(), Void>()
54 | /// func done() {
55 | /// onDone.call()
56 | /// }
57 | ///
58 | /// // ViewController.swift
59 | /// var obj: MyClass?
60 | ///
61 | /// func doSomething() {
62 | /// obj = MyClass()
63 | /// obj!.onDone.delegate(on: self) { (self, _)
64 | /// // `self` here is shadowed and does not keep a strong ref.
65 | /// // So you can release both `MyClass` instance and `ViewController` instance.
66 | /// self.reportDone()
67 | /// }
68 | /// }
69 | /// ```
70 | ///
71 | public class Delegate {
72 | public init() {}
73 |
74 | private var block: ((Input) -> Output?)?
75 | public func delegate(on target: T, block: ((T, Input) -> Output)?) {
76 | self.block = { [weak target] input in
77 | guard let target = target else { return nil }
78 | return block?(target, input)
79 | }
80 | }
81 |
82 | public func call(_ input: Input) -> Output? {
83 | return block?(input)
84 | }
85 |
86 | public func callAsFunction(_ input: Input) -> Output? {
87 | return call(input)
88 | }
89 | }
90 |
91 | extension Delegate where Input == Void {
92 | public func call() -> Output? {
93 | return call(())
94 | }
95 |
96 | public func callAsFunction() -> Output? {
97 | return call()
98 | }
99 | }
100 |
101 | extension Delegate where Input == Void, Output: OptionalProtocol {
102 | public func call() -> Output {
103 | return call(())
104 | }
105 |
106 | public func callAsFunction() -> Output {
107 | return call()
108 | }
109 | }
110 |
111 | extension Delegate where Output: OptionalProtocol {
112 | public func call(_ input: Input) -> Output {
113 | if let result = block?(input) {
114 | return result
115 | } else {
116 | return Output._createNil
117 | }
118 | }
119 |
120 | public func callAsFunction(_ input: Input) -> Output {
121 | return call(input)
122 | }
123 | }
124 |
125 | public protocol OptionalProtocol {
126 | static var _createNil: Self { get }
127 | }
128 | extension Optional : OptionalProtocol {
129 | public static var _createNil: Optional {
130 | return nil
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Utility/Runtime.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Runtime.swift
3 | // Kingfisher
4 | //
5 | // Created by Wei Wang on 2018/10/12.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 |
29 | func getAssociatedObject(_ object: Any, _ key: UnsafeRawPointer) -> T? {
30 | return objc_getAssociatedObject(object, key) as? T
31 | }
32 |
33 | func setRetainedAssociatedObject(_ object: Any, _ key: UnsafeRawPointer, _ value: T) {
34 | objc_setAssociatedObject(object, key, value, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
35 | }
36 |
--------------------------------------------------------------------------------
/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Fakery (5.1.0)
3 | - Kingfisher (6.0.1)
4 |
5 | DEPENDENCIES:
6 | - Fakery
7 | - Kingfisher (~> 6.0)
8 |
9 | SPEC REPOS:
10 | trunk:
11 | - Fakery
12 | - Kingfisher
13 |
14 | SPEC CHECKSUMS:
15 | Fakery: a90caff00ca5cacde6c161c3eafc72314a03d34d
16 | Kingfisher: adde87a4f74f6a3845395769354efff593581740
17 |
18 | PODFILE CHECKSUM: 2e75b4b78d18cf325281d383317394c9eb3d64ac
19 |
20 | COCOAPODS: 1.10.0
21 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/mohannad.xcuserdatad/xcschemes/Fakery-Faker.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
53 |
54 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/mohannad.xcuserdatad/xcschemes/Fakery.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/mohannad.xcuserdatad/xcschemes/Kingfisher.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/mohannad.xcuserdatad/xcschemes/Pods-DynamicCell-DynamicCellUITests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
53 |
54 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/mohannad.xcuserdatad/xcschemes/Pods-DynamicCell.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
53 |
54 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/mohannad.xcuserdatad/xcschemes/Pods-DynamicCellTests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
53 |
54 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/mohannad.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Fakery-Faker.xcscheme
8 |
9 | isShown
10 |
11 | orderHint
12 | 1
13 |
14 | Fakery.xcscheme
15 |
16 | isShown
17 |
18 | orderHint
19 | 0
20 |
21 | Kingfisher.xcscheme
22 |
23 | isShown
24 |
25 | orderHint
26 | 2
27 |
28 | Pods-DynamicCell-DynamicCellUITests.xcscheme
29 |
30 | isShown
31 |
32 | orderHint
33 | 4
34 |
35 | Pods-DynamicCell.xcscheme
36 |
37 | isShown
38 |
39 | orderHint
40 | 3
41 |
42 | Pods-DynamicCellTests.xcscheme
43 |
44 | isShown
45 |
46 | orderHint
47 | 5
48 |
49 |
50 | SuppressBuildableAutocreation
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Fakery/Fakery-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 5.1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Fakery/Fakery-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Fakery : NSObject
3 | @end
4 | @implementation PodsDummy_Fakery
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Fakery/Fakery-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Fakery/Fakery-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double FakeryVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char FakeryVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Fakery/Fakery.debug.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Fakery
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | OTHER_LDFLAGS = $(inherited) -framework "Foundation"
5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_ROOT = ${SRCROOT}
9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Fakery
10 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
12 | SKIP_INSTALL = YES
13 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
14 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Fakery/Fakery.modulemap:
--------------------------------------------------------------------------------
1 | framework module Fakery {
2 | umbrella header "Fakery-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Fakery/Fakery.release.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Fakery
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | OTHER_LDFLAGS = $(inherited) -framework "Foundation"
5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_ROOT = ${SRCROOT}
9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Fakery
10 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
12 | SKIP_INSTALL = YES
13 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
14 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Fakery/ResourceBundle-Faker-Fakery-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleIdentifier
8 | ${PRODUCT_BUNDLE_IDENTIFIER}
9 | CFBundleInfoDictionaryVersion
10 | 6.0
11 | CFBundleName
12 | ${PRODUCT_NAME}
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 5.1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 6.0.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Kingfisher : NSObject
3 | @end
4 | @implementation PodsDummy_Kingfisher
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "Kingfisher.h"
14 |
15 | FOUNDATION_EXPORT double KingfisherVersionNumber;
16 | FOUNDATION_EXPORT const unsigned char KingfisherVersionString[];
17 |
18 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher.debug.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork"
5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_ROOT = ${SRCROOT}
9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Kingfisher
10 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
12 | SKIP_INSTALL = YES
13 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
14 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher.modulemap:
--------------------------------------------------------------------------------
1 | framework module Kingfisher {
2 | umbrella header "Kingfisher-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher.release.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork"
5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_ROOT = ${SRCROOT}
9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Kingfisher
10 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
12 | SKIP_INSTALL = YES
13 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
14 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## Fakery
5 |
6 | Licensed under the **MIT** license
7 |
8 | > Copyright (c) 2015 Vadym Markov
9 | >
10 | > Permission is hereby granted, free of charge, to any person obtaining
11 | > a copy of this software and associated documentation files (the
12 | > "Software"), to deal in the Software without restriction, including
13 | > without limitation the rights to use, copy, modify, merge, publish,
14 | > distribute, sublicense, and/or sell copies of the Software, and to
15 | > permit persons to whom the Software is furnished to do so, subject to
16 | > the following conditions:
17 | >
18 | > The above copyright notice and this permission notice shall be
19 | > included in all copies or substantial portions of the Software.
20 | >
21 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 | > IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25 | > CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 | > TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 | > SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 |
29 |
30 | ## Kingfisher
31 |
32 | The MIT License (MIT)
33 |
34 | Copyright (c) 2019 Wei Wang
35 |
36 | Permission is hereby granted, free of charge, to any person obtaining a copy
37 | of this software and associated documentation files (the "Software"), to deal
38 | in the Software without restriction, including without limitation the rights
39 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40 | copies of the Software, and to permit persons to whom the Software is
41 | furnished to do so, subject to the following conditions:
42 |
43 | The above copyright notice and this permission notice shall be included in all
44 | copies or substantial portions of the Software.
45 |
46 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52 | SOFTWARE.
53 |
54 |
55 | Generated by CocoaPods - https://cocoapods.org
56 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Licensed under the **MIT** license
18 |
19 | > Copyright (c) 2015 Vadym Markov
20 | >
21 | > Permission is hereby granted, free of charge, to any person obtaining
22 | > a copy of this software and associated documentation files (the
23 | > "Software"), to deal in the Software without restriction, including
24 | > without limitation the rights to use, copy, modify, merge, publish,
25 | > distribute, sublicense, and/or sell copies of the Software, and to
26 | > permit persons to whom the Software is furnished to do so, subject to
27 | > the following conditions:
28 | >
29 | > The above copyright notice and this permission notice shall be
30 | > included in all copies or substantial portions of the Software.
31 | >
32 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
35 | > IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
36 | > CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
37 | > TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
38 | > SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 |
40 | License
41 | MIT
42 | Title
43 | Fakery
44 | Type
45 | PSGroupSpecifier
46 |
47 |
48 | FooterText
49 | The MIT License (MIT)
50 |
51 | Copyright (c) 2019 Wei Wang
52 |
53 | Permission is hereby granted, free of charge, to any person obtaining a copy
54 | of this software and associated documentation files (the "Software"), to deal
55 | in the Software without restriction, including without limitation the rights
56 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57 | copies of the Software, and to permit persons to whom the Software is
58 | furnished to do so, subject to the following conditions:
59 |
60 | The above copyright notice and this permission notice shall be included in all
61 | copies or substantial portions of the Software.
62 |
63 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
64 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
65 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
66 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
67 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
69 | SOFTWARE.
70 |
71 |
72 | License
73 | MIT
74 | Title
75 | Kingfisher
76 | Type
77 | PSGroupSpecifier
78 |
79 |
80 | FooterText
81 | Generated by CocoaPods - https://cocoapods.org
82 | Title
83 |
84 | Type
85 | PSGroupSpecifier
86 |
87 |
88 | StringsTable
89 | Acknowledgements
90 | Title
91 | Acknowledgements
92 |
93 |
94 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_DynamicCell_DynamicCellUITests : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_DynamicCell_DynamicCellUITests
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-frameworks-Debug-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/Fakery/Fakery.framework
3 | ${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-frameworks-Debug-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Fakery.framework
2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Kingfisher.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-frameworks-Release-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/Fakery/Fakery.framework
3 | ${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-frameworks-Release-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Fakery.framework
2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Kingfisher.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_DynamicCell_DynamicCellUITestsVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_DynamicCell_DynamicCellUITestsVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery/Fakery.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers"
6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
7 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -framework "Fakery" -framework "Foundation" -framework "Kingfisher"
8 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
15 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_DynamicCell_DynamicCellUITests {
2 | umbrella header "Pods-DynamicCell-DynamicCellUITests-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell-DynamicCellUITests/Pods-DynamicCell-DynamicCellUITests.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery/Fakery.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers"
6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
7 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -framework "Fakery" -framework "Foundation" -framework "Kingfisher"
8 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
15 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## Fakery
5 |
6 | Licensed under the **MIT** license
7 |
8 | > Copyright (c) 2015 Vadym Markov
9 | >
10 | > Permission is hereby granted, free of charge, to any person obtaining
11 | > a copy of this software and associated documentation files (the
12 | > "Software"), to deal in the Software without restriction, including
13 | > without limitation the rights to use, copy, modify, merge, publish,
14 | > distribute, sublicense, and/or sell copies of the Software, and to
15 | > permit persons to whom the Software is furnished to do so, subject to
16 | > the following conditions:
17 | >
18 | > The above copyright notice and this permission notice shall be
19 | > included in all copies or substantial portions of the Software.
20 | >
21 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 | > IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25 | > CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 | > TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 | > SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 |
29 |
30 | ## Kingfisher
31 |
32 | The MIT License (MIT)
33 |
34 | Copyright (c) 2019 Wei Wang
35 |
36 | Permission is hereby granted, free of charge, to any person obtaining a copy
37 | of this software and associated documentation files (the "Software"), to deal
38 | in the Software without restriction, including without limitation the rights
39 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40 | copies of the Software, and to permit persons to whom the Software is
41 | furnished to do so, subject to the following conditions:
42 |
43 | The above copyright notice and this permission notice shall be included in all
44 | copies or substantial portions of the Software.
45 |
46 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52 | SOFTWARE.
53 |
54 |
55 | Generated by CocoaPods - https://cocoapods.org
56 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Licensed under the **MIT** license
18 |
19 | > Copyright (c) 2015 Vadym Markov
20 | >
21 | > Permission is hereby granted, free of charge, to any person obtaining
22 | > a copy of this software and associated documentation files (the
23 | > "Software"), to deal in the Software without restriction, including
24 | > without limitation the rights to use, copy, modify, merge, publish,
25 | > distribute, sublicense, and/or sell copies of the Software, and to
26 | > permit persons to whom the Software is furnished to do so, subject to
27 | > the following conditions:
28 | >
29 | > The above copyright notice and this permission notice shall be
30 | > included in all copies or substantial portions of the Software.
31 | >
32 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
35 | > IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
36 | > CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
37 | > TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
38 | > SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 |
40 | License
41 | MIT
42 | Title
43 | Fakery
44 | Type
45 | PSGroupSpecifier
46 |
47 |
48 | FooterText
49 | The MIT License (MIT)
50 |
51 | Copyright (c) 2019 Wei Wang
52 |
53 | Permission is hereby granted, free of charge, to any person obtaining a copy
54 | of this software and associated documentation files (the "Software"), to deal
55 | in the Software without restriction, including without limitation the rights
56 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57 | copies of the Software, and to permit persons to whom the Software is
58 | furnished to do so, subject to the following conditions:
59 |
60 | The above copyright notice and this permission notice shall be included in all
61 | copies or substantial portions of the Software.
62 |
63 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
64 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
65 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
66 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
67 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
69 | SOFTWARE.
70 |
71 |
72 | License
73 | MIT
74 | Title
75 | Kingfisher
76 | Type
77 | PSGroupSpecifier
78 |
79 |
80 | FooterText
81 | Generated by CocoaPods - https://cocoapods.org
82 | Title
83 |
84 | Type
85 | PSGroupSpecifier
86 |
87 |
88 | StringsTable
89 | Acknowledgements
90 | Title
91 | Acknowledgements
92 |
93 |
94 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_DynamicCell : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_DynamicCell
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-frameworks-Debug-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/Fakery/Fakery.framework
3 | ${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-frameworks-Debug-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Fakery.framework
2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Kingfisher.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-frameworks-Release-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/Fakery/Fakery.framework
3 | ${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-frameworks-Release-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Fakery.framework
2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Kingfisher.framework
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_DynamicCellVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_DynamicCellVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery/Fakery.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers"
6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
7 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -framework "Fakery" -framework "Foundation" -framework "Kingfisher"
8 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
15 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_DynamicCell {
2 | umbrella header "Pods-DynamicCell-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCell/Pods-DynamicCell.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery/Fakery.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers"
6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
7 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -framework "Fakery" -framework "Foundation" -framework "Kingfisher"
8 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
15 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCellTests/Pods-DynamicCellTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCellTests/Pods-DynamicCellTests-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 | Generated by CocoaPods - https://cocoapods.org
4 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCellTests/Pods-DynamicCellTests-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Generated by CocoaPods - https://cocoapods.org
18 | Title
19 |
20 | Type
21 | PSGroupSpecifier
22 |
23 |
24 | StringsTable
25 | Acknowledgements
26 | Title
27 | Acknowledgements
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCellTests/Pods-DynamicCellTests-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_DynamicCellTests : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_DynamicCellTests
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCellTests/Pods-DynamicCellTests-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_DynamicCellTestsVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_DynamicCellTestsVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCellTests/Pods-DynamicCellTests.debug.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery/Fakery.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers"
5 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -framework "Fakery" -framework "Foundation" -framework "Kingfisher"
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
9 | PODS_ROOT = ${SRCROOT}/Pods
10 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
11 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
12 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCellTests/Pods-DynamicCellTests.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_DynamicCellTests {
2 | umbrella header "Pods-DynamicCellTests-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-DynamicCellTests/Pods-DynamicCellTests.release.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Fakery/Fakery.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers"
5 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -framework "Fakery" -framework "Foundation" -framework "Kingfisher"
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
9 | PODS_ROOT = ${SRCROOT}/Pods
10 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
11 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DynamicCell
2 | How to implement a dynamic height UICollectionViewCell in Swift.
3 |
4 | This tutorial has two parts. First, We're going to implement a self-sizing UICollectionViewCell based on font size as shown in the screenshot on the left side.
5 | Second, we're going to build a dynamic height UICollectionViewCell based on the image aspect ratio in addition to font size the result will be like the right side of the screenshot.
6 |
7 | 
8 |
9 | ## Tutorial
10 | [The Article on Meduim](https://medium.com/post/bdd912acd5c8)
11 |
12 | ## Prerequisites
13 | * Swift 5.3
14 | * Xcode
15 | * CocoaPods
16 |
17 | ## Technology used
18 | * Xcode
19 | * Swift 5.3
20 |
21 | ## How to use ?
22 | 1. Download or clone the repository.
23 | 2. Open the project through Xcode.
24 | 3. Run the application in mobile or simulator running iOS 13
25 |
26 | ## Credits
27 | © Mohannad BakBouk | 2021
28 |
29 |
--------------------------------------------------------------------------------