iOS How to make user-resizable uiview like below? - ios

I make CAShapeLayer, and create four uiview at all corner of that Layer.
And add pan gesture to all these 4 UIView. when anyone of them moves it Layer update its frame according to it.
Any idea? Efforts would be appreciated.
topLeftControl = addControl(tl, pos: 1)
topRightControl = addControl(tr, pos: 2)
bottomLeftControl = addControl(bl, pos: 3)
bottomRightControl = addControl(br, pos: 4)
func addControl(p : CGPoint,pos : Int) -> (UIView)
{
var r : CGRect = CGRectZero
r.origin = p
r.size = CGSizeMake(15, 15)
if(DeviceType.iPad)
{
r.size = CGSizeMake(55, 55)
}
let v = UIView.init(frame: r)
v.layer.cornerRadius = v.frame.size.width / 2
v.clipsToBounds = true
v.backgroundColor = UIColor.whiteColor()
v.userInteractionEnabled = true
self.mainView.addSubview(v)
let pan = UIPanGestureRecognizer.init(target: self, action: #selector(ViewController.dragMaker(_:)))
v.addGestureRecognizer(pan)
return v
}

Related

Swift Scale Animation is not animating view

I would simply like to have a pulsating UIView. For that I have set up this:
let highlightView: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .lightBlueCustom
v.alpha = 0.9
return v
}()
let scaleAnimation: CABasicAnimation = {
let v = CABasicAnimation(keyPath: "transform.scale")
v.duration = 0.5
v.repeatCount = .infinity
v.autoreverses = true
v.fromValue = 1.0
v.toValue = 1.4
return v
}()
And this is how I call it:
func showHighlightView(viewToHighlight: UIView, height: CGFloat) {
self.view.addSubview(highlightView)
highlightView.heightAnchor.constraint(equalTo: viewToHighlight.heightAnchor).isActive = true
highlightView.widthAnchor.constraint(equalTo: highlightView.heightAnchor).isActive = true
highlightView.centerXAnchor.constraint(equalTo: viewToHighlight.centerXAnchor).isActive = true
highlightView.centerYAnchor.constraint(equalTo: viewToHighlight.centerYAnchor).isActive = true
highlightView.layer.cornerRadius = height/2
highlightView.layer.add(self.scaleAnimation, forKey: "scale")
self.view.bringSubviewToFront(viewToHighlight)
self.view.bringSubviewToFront(highlightView)
}
func showWishIntro() {
showHighlightView(viewToHighlight: self.addWishButton, height: 60)
}
But this is not working. It shows the highlightView correctly but there is no animation. What am I missing here?
ok so I fixed it... it was just a lucky guess but I am calling showWishIntro now in viewDidLayoutSubviews and not it is working as expected. I have no idea why, so if anyone would care to explain just let me know :D I'm happy that it works.

Programmatically center UIImage inside parent view vertically

I am on Swift 5.
The goal is to center a UIImageView vertically inside a view. Currently it looks like
Note all the image bubbles are running off of the cell.
This is the code that lead to this:
let imageView = UIImageView()
let width = self.frame.width
let height = self.frame.height
let img_width = height //* 0.8
let img_height = height
let y = (height - img_height)/2
let x = width*0.05
imageView.frame = CGRect(
x: x
, y: CGFloat(y)
, width: img_width
, height: img_height
)
let rounded = imageView
.makeRounded()
.border(width:1.0, color:Color.white.cgColor)
self.addSubview(rounded)
The imageView extension functions are:
func makeRounded() -> UIImageView {
self.layer.borderWidth = 0.5
self.layer.masksToBounds = false
self.layer.borderColor = Color.white.cgColor
self.layer.cornerRadius = self.frame.width/2
self.clipsToBounds = true
// see https://developer.apple.com/documentation/uikit/uiview/contentmode
self.contentMode = .scaleAspectFill
return self
}
func border( width: CGFloat, color: CGColor ) -> UIImageView{
self.layer.borderWidth = width
self.layer.borderColor = color
return self
}
Which is very vanilla.
This is odd because I laid out the textview vertically in the exact same way, that is: (parentHeight - childHeight)/2, and it is centered. You can see it in the blue text boxes in cell two and three.
____ EDIT _______
This is how I laid out the cell
let data = dataSource[ row - self._data_source_off_set ]
let cell = tableView.dequeueReusableCell(withIdentifier: "OneUserCell", for: indexPath) as! OneUserCell
// give uuid and set delegate
cell.uuid = data.uuid
cell.delegate = self
// render style: this must be set
cell.hasFooter = false //true
cell.imageSource = data
cell.headerTextSource = data
cell.footerTextSource = data
// color schemes
cell.backgroundColor = Color.offWhiteLight
cell.selectionColor = Color.graySecondary
Add these constraints to you imageView and remove frame and its calculations
self.contentView.addSubview(rounded)
self.mimageView.translatesAutoresizingMaskIntoConstraints = false
self.mimageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,constant: 20).isActive = true
self.mimageView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
self.mimageView.heightAnchor.constraint(equalTo: contentView.heightAnchor).isActive = true
self.mimageView.widthAnchor.constraint(equalTo: contentView.heightAnchor).isActive = true

SpriteKit: suggestions for rounding corners of unconventional grid?

The goal is to round the corners of an unconventional grid similar to the following:
https://s-media-cache-ak0.pinimg.com/564x/50/bc/e0/50bce0cb908913ebc2cf630d635331ef.jpg
https://s-media-cache-ak0.pinimg.com/564x/7e/29/ee/7e29ee80e957ec22bbba630ccefbfaa2.jpg
Instead of a grid with four corners like a conventional grid, these grids have multiple corners in need of rounding.
The brute force approach would be to identify tiles with corners exposed then round those corners either with a different background image or by clipping the corners in code.
Is there a cleaner approach?
The grid is rendered for an iOS app in a SpriteKit SKScene.
This is a really interesting question.You can build your matrix with different approaches but surely you must resolve everytime the changes about the 4 corners in background for each tiles.
Suppose you start with a GameViewController like this (without load SKS files and with anchorPoint equal to zero):
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
guard let view = self.view as! SKView? else { return }
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
let scene = GameScene(size:view.bounds.size)
scene.scaleMode = .resizeFill
scene.anchorPoint = CGPoint.zero
view.presentScene(scene)
}
}
My idea is to build a matrix like this:
import SpriteKit
class GameScene: SKScene {
private var sideTile:CGFloat = 40
private var gridWidthTiles:Int = 5
private var gridHeightTiles:Int = 6
override func didMove(to view: SKView) {
self.drawMatrix()
}
func drawMatrix(){
var index = 1
let matrixPos = CGPoint(x:50,y:150)
for i in 0..<gridHeightTiles {
for j in 0..<gridWidthTiles {
let tile = getTile()
tile.name = "tile\(index)"
addChild(tile)
tile.position = CGPoint(x:matrixPos.x+(sideTile*CGFloat(j)),y:matrixPos.y+(sideTile*CGFloat(i)))
let label = SKLabelNode.init(text: "\(index)")
label.fontSize = 12
label.fontColor = .white
tile.addChild(label)
label.position = CGPoint(x:tile.frame.size.width/2,y:tile.frame.size.height/2)
index += 1
}
}
}
func getTile()->SKShapeNode {
let tile = SKShapeNode(rect: CGRect(x: 0, y: 0, width: sideTile, height: sideTile), cornerRadius: 10)
tile.fillColor = .gray
tile.strokeColor = .gray
return tile
}
}
Output:
Now we can construct a background for each tile of our matrix.
We can made the same tile node but with a different color (maybe more clear than the tile color) and without corner radius. If we split this background in 4 parts we have:
left - bottom background tile
left - top background tile
right - bottom background tile
right - top background tile
Code for a typical background tile:
func getBgTileCorner()->SKShapeNode {
let bgTileCorner = SKShapeNode(rect: CGRect(x: 0, y: 0, width: sideTile/2, height: sideTile/2))
bgTileCorner.fillColor = .lightGray
bgTileCorner.strokeColor = .lightGray
bgTileCorner.lineJoin = .round
bgTileCorner.isAntialiased = false
return bgTileCorner
}
Now with the SKSCropNode we can obtain only the corner using the background tile and the tile:
func getCorner(at angle:String)->SKCropNode {
let cropNode = SKCropNode()
let tile = getTile()
let bgTile = getBgTileCorner()
cropNode.addChild(bgTile)
tile.position = CGPoint.zero
let tileFrame = CGRect(x: 0, y: 0, width: sideTile, height: sideTile)
switch angle {
case "leftBottom": bgTile.position = CGPoint(x:tile.position.x,y:tile.position.y)
case "rightBottom": bgTile.position = CGPoint(x:tile.position.x+tileFrame.size.width/2,y:tile.position.y)
case "leftTop": bgTile.position = CGPoint(x:tile.position.x,y:tile.position.y+tileFrame.size.height/2)
case "rightTop": bgTile.position = CGPoint(x:tile.position.x+tileFrame.size.width/2,y:tile.position.y+tileFrame.size.height/2)
default:break
}
tile.fillColor = self.backgroundColor
tile.strokeColor = self.backgroundColor
tile.lineWidth = 0.0
bgTile.lineWidth = 0.0
tile.blendMode = .replace
cropNode.position = CGPoint.zero
cropNode.addChild(tile)
cropNode.maskNode = bgTile
return cropNode
}
Output for a typical corner:
let corner = getCorner(at: "leftBottom")
addChild(corner)
corner.position = CGPoint(x:50,y:50)
Now we can rebuild the drawMatrix function with the corners for each tile:
func drawMatrix(){
var index = 1
let matrixPos = CGPoint(x:50,y:150)
for i in 0..<gridHeightTiles {
for j in 0..<gridWidthTiles {
let tile = getTile()
tile.name = "tile\(index)"
let bgTileLB = getCorner(at:"leftBottom")
let bgTileRB = getCorner(at:"rightBottom")
let bgTileLT = getCorner(at:"leftTop")
let bgTileRT = getCorner(at:"rightTop")
bgTileLB.name = "bgTileLB\(index)"
bgTileRB.name = "bgTileRB\(index)"
bgTileLT.name = "bgTileLT\(index)"
bgTileRT.name = "bgTileRT\(index)"
addChild(bgTileLB)
addChild(bgTileRB)
addChild(bgTileLT)
addChild(bgTileRT)
addChild(tile)
tile.position = CGPoint(x:matrixPos.x+(sideTile*CGFloat(j)),y:matrixPos.y+(sideTile*CGFloat(i)))
let label = SKLabelNode.init(text: "\(index)")
label.fontSize = 12
label.fontColor = .white
tile.addChild(label)
label.position = CGPoint(x:tile.frame.size.width/2,y:tile.frame.size.height/2)
bgTileLB.position = CGPoint(x:tile.position.x,y:tile.position.y)
bgTileRB.position = CGPoint(x:tile.position.x,y:tile.position.y)
bgTileLT.position = CGPoint(x:tile.position.x,y:tile.position.y)
bgTileRT.position = CGPoint(x:tile.position.x,y:tile.position.y)
index += 1
}
}
}
Output:
Very similar to your screenshots (these are two tile example:)
Now when you want to remove a tile, you can decide what corner you want to remove or leave because for each tile you have also the relative 4 corners :
Output:
Okay, the grid creation process isn't really relative to this. You just need some way of differentiating between a blank spot in the grid and a filled spot. In my example I have a Tile object with a type of .blank or .regular. You need to have all 15 images (you can change the style to whatever you like, although they have to be in the same order and they have to be prefixed with 1..15). It uses bit calculation to figure out which image to use as a background and offsets the background image by 1/2 tile size for x and y. Other than that it is pretty self explanitory. Those background images were my tester images I created when developing this, so feel free to use them.
struct GridPosition {
var col: Int = 0
var row: Int = 0
}
class GameScene: SKScene {
private var backgroundLayer = SKNode()
private var tileLayer = SKNode()
private var gridSize: CGSize = CGSize.zero
private var gridRows: Int = 0
private var gridCols: Int = 0
private var gridBlanks = [Int]()
private var tiles = [[Tile]]()
var tileSize: CGFloat = 150
override func didMove(to view: SKView) {
backgroundLayer.zPosition = 1
addChild(backgroundLayer)
tileLayer.zPosition = 2
addChild(tileLayer)
gridRows = 8
gridCols = 11
gridBlanks = [0,1,3,4,5,6,7,9,10,11,12,13,15,16,17,19,20,21,22,23,31,32,33,36,40,43,56,64,67,69,70,71,72,73,75,77,78,79,82,85,86,87]
createGrid()
createBackgroundTiles()
}
func createGrid() {
for row in 0 ..< gridRows {
var rowContent = [Tile]()
for col in 0 ..< gridCols {
let currentTileLocation: Int = row * gridCols + col
var tile: Tile
if gridBlanks.contains(currentTileLocation) {
tile = Tile(row: row, col: col, type: .blank, tileSize: tileSize)
}
else {
tile = Tile(row: row, col: col, type: .regular, tileSize: tileSize)
}
tile.position = positionInGrid(column: col, row: row)
tile.zPosition = CGFloat(100 + gridRows - row)
tileLayer.addChild(tile)
rowContent.append(tile)
}
tiles.append(rowContent)
}
}
func tileByGridPosition(_ gridPos: GridPosition) -> Tile {
return (tiles[Int(gridPos.row)][Int(gridPos.col)])
}
func positionInGrid(column: Int, row: Int) -> CGPoint {
let startX = 0 - CGFloat(gridCols / 2) * tileSize
let startY = 0 - CGFloat(gridRows / 2) * tileSize + tileSize / 2
return CGPoint(
x: startX + CGFloat(column) * tileSize,
y: startY + CGFloat(row) * tileSize)
}
func createBackgroundTiles() {
for row in 0...gridRows {
for col in 0...gridCols {
let topLeft = (col > 0) && (row < gridRows) && tileByGridPosition(GridPosition(col: col - 1, row: row)).type == .regular
let bottomLeft = (col > 0) && (row > 0) && tileByGridPosition(GridPosition(col: col - 1, row: row - 1)).type == .regular
let topRight = (col < gridCols) && (row < gridRows) && tileByGridPosition(GridPosition(col: col, row: row)).type == .regular
let bottomRight = (col < gridCols) && (row > 0) && tileByGridPosition(GridPosition(col: col, row: row - 1)).type == .regular
// The tiles are named from 0 to 15, according to the bitmask that is made by combining these four values.
let value = Int(NSNumber(value: topLeft)) | Int(NSNumber(value: topRight)) << 1 | Int(NSNumber(value: bottomLeft)) << 2 | Int(NSNumber(value: bottomRight)) << 3
// Values 0 (no tiles)
if value != 0 {
var gridPosition = positionInGrid(column: col, row: row)
gridPosition.x -= tileSize / 2
gridPosition.y -= tileSize / 2
let backgroundNode = SKSpriteNode(imageNamed: ("background_tile_\(value)"))
backgroundNode.size = CGSize(width: tileSize, height: tileSize)
backgroundNode.alpha = 0.8
backgroundNode.position = gridPosition
backgroundNode.zPosition = 1
backgroundLayer.addChild(backgroundNode)
}
}
}
}
}
class Tile: SKSpriteNode {
private var row = 0
private var col = 0
var type: TileType = .blank
init(row: Int, col: Int, type: TileType, tileSize: CGFloat) {
super.init(texture: nil ,color: .clear, size:CGSize(width: tileSize, height: tileSize))
self.type = type
size = self.size
let square = SKSpriteNode(color: type.color, size: size)
square.zPosition = 1
addChild(square)
}
}
Only thing that comes to mind is when one node touches another node, at that moment in time evaluate the display of said node, as well as change the neighbors that are affected by it.
What we did was lay out the tiles then call this function to round the nodes of exposed tiles.
// Rounds corners of exposed tiles. UIKit inverts coordinates so top is bottom and vice-versa.
fileprivate func roundTileCorners() {
// Get all tiles
var tiles = [TileClass]()
tileLayer.enumerateChildNodes(withName: ".//*") { node, stop in
if node is TileClass {
tiles.append(node as! TileClass)
}
}
// Round corners for each exposed tile
for t in tiles {
// Convert tile's position to root coordinates
let convertedPos = convert(t.position, from: t.parent!)
// Set neighbor positions
var leftNeighborPos = convertedPos
leftNeighborPos.x -= tileWidth
var rightNeighborPos = convertedPos
rightNeighborPos.x += tileWidth
var topNeighborPos = convertedPos
topNeighborPos.y += tileHeight
var bottomNeighborPos = convertedPos
bottomNeighborPos.y -= tileHeight
// Set default value for rounding
var cornersToRound : UIRectCorner?
// No neighbor below & to left? Round bottom left.
if !isTileAtPoint(point: bottomNeighborPos) && !isTileAtPoint(point: leftNeighborPos) {
cornersToRound = cornersToRound?.union(.topLeft) ?? .topLeft
}
// No neighbor below & to right? Round bottom right.
if !isTileAtPoint(point: bottomNeighborPos) && !isTileAtPoint(point: rightNeighborPos) {
cornersToRound = cornersToRound?.union(.topRight) ?? .topRight
}
// No neightbor above & to left? Round top left.
if !isTileAtPoint(point: topNeighborPos) && !isTileAtPoint(point: leftNeighborPos) {
cornersToRound = cornersToRound?.union(.bottomLeft) ?? .bottomLeft
}
// No neighbor above & to right? Round top right.
if !isTileAtPoint(point: topNeighborPos) && !isTileAtPoint(point: rightNeighborPos) {
cornersToRound = cornersToRound?.union(.bottomRight) ?? .bottomRight
}
// Any corners to round?
if cornersToRound != nil {
t.roundCorners(cornersToRound: cornersToRound!)
}
}
}
// Returns true if a tile exists at <point>. Assumes <point> is in root node's coordinates.
fileprivate func isTileAtPoint(point: CGPoint) -> Bool {
return nodes(at: point).contains(where: {$0 is BoardTileNode })
}

iOS swift move my location button to top right corner

Currently when I set the button to appear using the GMSMapView api, it appears on the bottom right corner.
There is another question on SO about this but this is for swift as opposed to objective-c (and it's for a different location on the screen.)
Just adapt the solution in this post
From the top of my head it would look something like this:
let myLocationButton = mapView.subviews.last! as! UIButton
myLocationButton.autoresizingMask = UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleTopMargin
let frame = myLocationButton.frame
frame.origin.y = 10
myLocationButton.frame = frame
Create your own myLocationButton and just update your camera target to current position when tap.
Here Is a full implementation. Tried and tested:
class MyViewController : UIViewController {
var userTracker : MKUserTrackingButton? //strong reference
var compass : MKCompassButton? //strong reference
override func viewLayoutMarginsDidChange() { //when device is rotated
setUpUserLocationButton()
}
func setUpUserLocationButton() {
let buttonMargins : CGFloat = 12
if userTracker == nil {
userTracker = MKUserTrackingButton(mapView: self.mapView)
userTracker!.backgroundColor = .white
view.addSubview(userTracker!)
userTracker!.autoresizingMask = [.flexibleTopMargin, .flexibleLeftMargin]
setGenericShadow(subView: userTracker!)
self.mapView.showsCompass = false
compass = MKCompassButton(mapView: mapView)
compass!.compassVisibility = .visible
compass!.autoresizingMask = [.flexibleTopMargin, .flexibleLeftMargin]
view.addSubview(compass!)
}
compass!.frame.origin.x = (self.view.frame.width) - (compass!.frame.size.width) - (self.view.safeAreaInsets.right == 0 ? buttonMargins : self.view.safeAreaInsets.right )
compass!.frame.origin.y = self.view.safeAreaInsets.top + buttonMargins
userTracker!.frame.origin.x = (self.view.frame.width) - (userTracker!.frame.size.width) - (self.view.safeAreaInsets.right == 0 ? buttonMargins : self.view.safeAreaInsets.right )
userTracker!.frame.origin.y = self.view.safeAreaInsets.top + buttonMargins + compass!.frame.height + buttonMargins
}
func setGenericShadow(subView:UIView) {
subView.layer.shadowPath = UIBezierPath(rect: subView.bounds).cgPath
subView.layer.shadowOpacity = 0.2
subView.layer.shadowColor = UIColor.black.cgColor
subView.layer.shadowOffset = CGSize(width: 0, height: 0)
subView.layer.shadowRadius = 4
subView.layer.cornerRadius = 5
subView.layer.masksToBounds = false
}
}

UILabel takes long to load swift

I'm trying to create a view of a "match" image and the "match price" label in the top right corner of the match image. So far everything works fine- I create the image in the container view, I create a UIImageView for the background of my price label, but when I create the actual label and customize it, it takes forever to load in my app (that is to say, everything loads- the match image, the price label background image, but not the actual label detailing the price). Can anyone spot where in my code I'm going wrong?
func setupMiniContentScroll(contentScroll: UIScrollView) {
let scalar:Double = 6/19
let contentViewDimension = contentScroll.frame.width * CGFloat(scalar)
let contentScrollWidth = CGFloat(LocalUser.matches.count) * (contentViewDimension + CGFloat(12)) - CGFloat(12)
contentScroll.backgroundColor = UIColorFromHex(0x34495e)
for index in 0..<LocalUser.matches.count {
let match = LocalUser.matches[index]
MatchesManager.globalManager.retrieveMatchThumbnail(match) { img, error in
if let img = img {
//create the mini matches views
let xOrigin = index == 0 ? 12 : CGFloat(index) * contentViewDimension + (CGFloat(12) * CGFloat(index) + CGFloat(12))
let contentFrame = CGRectMake(xOrigin, 10, contentViewDimension, contentViewDimension)
let contentView = self.makeMiniContentView(contentFrame, image: img, matchedPrice: match.matchedPrice)
contentView.match = match
let tap = UITapGestureRecognizer(target: self, action: #selector(BrowseViewController.toggleItemInfo(_:)))
contentView.addGestureRecognizer(tap)
//update the contentScrollView
dispatch_async(dispatch_get_main_queue()) {
contentScroll.addSubview(contentView)
contentScroll.contentSize = CGSizeMake(contentScrollWidth + CGFloat(16), contentScroll.frame.height)
}
}
}
}
}
//functions to create labels and imgViews for MiniMyMatches
func makeMiniContentView(frame: CGRect, image: UIImage, matchedPrice: Int) -> ItemContainer {
let containerView = ItemContainer(frame: frame)
//create the item image
let imgView = UIImageView(frame: CGRect(x: 0, y: 0, width: containerView.frame.width, height: containerView.frame.height))
imgView.image = image
imgView.layer.cornerRadius = 5
imgView.layer.masksToBounds = true
imgView.userInteractionEnabled = true
//create the price label
dispatch_async(dispatch_get_main_queue()) {
let priceLabel = self.makeMiniPriceLabel(containerView, matchedPrice: matchedPrice)
containerView.addSubview(imgView)
containerView.addSubview(priceLabel)
}
return containerView
}
func makeMiniPriceLabel(containerView: ItemContainer, matchedPrice: Int) -> UIView {
//price label var
let priceLabelFrame = CGRectMake(containerView.frame.size.width - 35, -7, containerView.frame.size.width * 0.50, containerView.frame.size.height * 0.35)
//create the price container
let priceContainer = UIImageView(frame: priceLabelFrame)
priceContainer.image = UIImage(named: "venn.png")
//create the price label
let priceLabel = UILabel(frame: CGRect(x: 3, y:0, width: priceContainer.frame.width, height: priceContainer.frame.height))
priceLabel.text = "$\(matchedPrice)"
priceLabel.numberOfLines = 1
priceLabel.textColor = UIColor.whiteColor()
priceLabel.font = priceLabel.font.fontWithSize(20)
priceContainer.addSubview(priceLabel)
return priceContainer
}
My guess is that the closure for your retrieveMatchThumbnail function is being called on a background thread. You have code in that closure that is manipulating UI objects. I would move ALL the UI code inside your call to dispatch_async():
MatchesManager.globalManager.retrieveMatchThumbnail(match) { img, error in
if let img = img {
//create the mini matches views
let xOrigin = index == 0 ? 12 : CGFloat(index) * contentViewDimension + (CGFloat(12) * CGFloat(index) + CGFloat(12))
let contentFrame = CGRectMake(xOrigin, 10, contentViewDimension, contentViewDimension)
//update the contentScrollView
dispatch_async(dispatch_get_main_queue()) {
let contentView = self.makeMiniContentView(contentFrame, image: img, matchedPrice: match.matchedPrice)
contentView.match = match
let tap = UITapGestureRecognizer(target: self, action: #selector(BrowseViewController.toggleItemInfo(_:)))
contentView.addGestureRecognizer(tap)
contentScroll.addSubview(contentView)
contentScroll.contentSize = CGSizeMake(contentScrollWidth + CGFloat(16), contentScroll.frame.height)
}
}
}

Resources