I have a bluetooth device from which I receive data through this
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)
block without connecting to the device. Is it possible to scan for this device in the background without connection ? If so, any help on implementation please ?
Post
Replies
Boosts
Views
Activity
I'm trying to use "searchText" as a parameter of a function to make an API call but after I type the name of the city and press search nothing happens. The API works fine with the initial value "Toronto" when the app first launches. Any suggestion ?
import SwiftUI
import UIKit
func fetchWeather(cityName: String) {
let urlString = "\(weatherURL)&query=\(cityName)"
getWeatherData(with: urlString)
}
@State private var searchText = "Toronto"
var body: some View {
VStack {
SearchBar(text: $searchText)
}.onAppear() {
self.fetchWeather(cityName: self.searchText)
}
}
}
struct SearchBar: UIViewRepresentable {
@Binding var text: String
class Coordinator: NSObject, UISearchBarDelegate {
@Binding var text: String
init(text: Binding<String>) {
_text = text
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
text = searchText
}
}
func makeCoordinator() -> SearchBar.Coordinator {
return Coordinator(text: $text)
}
func makeUIView(context: UIViewRepresentableContext<SearchBar>) -> UISearchBar {
let searchBar = UISearchBar(frame: .zero)
searchBar.delegate = context.coordinator
searchBar.searchBarStyle = .minimal
return searchBar
}
func updateUIView(_ uiView: UISearchBar, context: UIViewRepresentableContext<SearchBar>) {
uiView.text = text
}
}
Hi, any idea why I am getting an error in line "21" ?
Thank you.
final func chooseLastImage(_ sender: Any) {
let imgManager = PHImageManager.default()
let fetchOptions = PHFetchOptions()
let requestOptions = PHImageRequestOptions()
requestOptions.version = .original
10. requestOptions.isSynchronous = false
requestOptions.isNetworkAccessAllowed = false
let targetSize: CGSize? = CGSize(width: photoImageView.bounds.width, height: photoImageView.bounds.height)
fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)]
let fetchResult: PHFetchResult<PHAsset> = PHAsset.fetchAssets(with: .image, options: fetchOptions)
20.
21. imgManager.requestImage(for: fetchResult.lastObject!, targetSize: targetSize!, contentMode: .aspectFit, options: requestOptions) { (result, info) in
22.
23. guard let result = result else { return }
24.
25. DispatchQueue.main.async(execute: {
26.
27. self.pickedImage = result
28.
29. self.photoImageView.image = self.pickedImage
30.
31. })
32.
33. }
34.
35. }
36.
37. extension PhotoViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
38.
39. func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
40.
41. if let editedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
42.
43. photoImageView.image = updatedImage
44.
45. } else if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
46.
47. pickedImage = image
48.
49. photoImageView.image = pickedImage
50.
51. }
52.
53. dismiss(animated: true, completion: nil)
54.
55. }
56.
57. func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
58.
59. dismiss(animated: true, completion: nil)
60.
61. }
62.
63. }
Hello, I have been trying to show the activityIndicator I have set up before the segue to another viewController. When I tap the button for segue, the app gets into the inactive state for at least 5 seconds. I'm aiming to show the activityIndicator before the view freezes. There is no problem with the setup of the activityIndicator. The problem I'm having is the activityIndicator shows up after the segue on the other viewController. Thanks in advance.import UIKit
class StitchEffectViewController: UIViewController {
// @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
let stitchPhotoID = "StitchPhotoID"
@IBOutlet weak var tapAboveOutlet: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// activityIndicator.isHidden = true
// activityIndicator.hidesWhenStopped = true
}
// override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
// super.viewWillTransition(to: size, with: coordinator)
//
// if UIApplication.shared.applicationState == .inactive {
// Spinner.update()
// }
//
// }
@IBAction func tapAbove(_ sender: UIButton) {
Spinner.start(style: .large, backColor: UIColor.white, baseColor: UIColor.green)
spinnerSetup()
}
func spinnerSetup() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
self.performSegue(withIdentifier: self.stitchPhotoID, sender: nil)
})
}
}
Hello, I have set up 16 CIFilter effects and for each effect I have created methods with identical functionality and due to the repetition I've been going through performance issues. The build time takes around 10-13 seconds. I have created a method called "applyFilterTo" to integrate the CIFilters under this method but then the filters started not to work anymore. Could you please give me some insight about how I can increase the performance of the app ?func effectsSliderSepiaTone() {
sliderControl.addTarget(self, action: #selector(sliderSepiaToneDidChange(_:image:_:)), for: .allTouchEvents)
sliderControl.translatesAutoresizingMaskIntoConstraints = false
sliderControl.minimumValue = 0
sliderControl.maximumValue = 1
sliderControl.isContinuous = true
sliderControl.tintColor = UIColor.blue
view.addSubview(sliderControl)
NSLayoutConstraint.activate([
sliderControl.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30),
sliderControl.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30),
sliderControl.bottomAnchor.constraint(equalTo: resetConfirmCollectionView.topAnchor, constant: -50)])
}
func imageSepiaTone(imgView: UIImageView, sliderValue: CGFloat, image: UIImage){
let aCGImage = image.cgImage
let aCIImage = CIImage(cgImage: aCGImage!)
let sepiaToneFilter = CIFilter(name: "CISepiaTone")
sepiaToneFilter!.setDefaults()
sepiaToneFilter?.setValue(aCIImage, forKey: kCIInputImageKey)
sepiaToneFilter?.setValue(sliderValue - 0.5, forKey: kCIInputIntensityKey)
let outputImage = sepiaToneFilter?.outputImage!
let cgimg = context.createCGImage(outputImage!, from: outputImage!.extent)
let newUIImage = UIImage(cgImage: cgimg!, scale: image.scale, orientation: image.imageOrientation)
imgView.image = newUIImage
}
@objc private func sliderSepiaToneDidChange(_ sender: UISlider!, image: UIImage,_ event: UIEvent) {
if let touchEvent = event.allTouches?.first {
switch touchEvent.phase {
case .moved:
labelControl.text = String(displayInPercentage)
if updatedImage == nil {
photoImageView.image = pickedImage
imageSepiaTone(imgView: photoImageView, sliderValue: CGFloat(sender.value), image: pickedImage!)
} else {
photoImageView.image = updatedImage
imageSepiaTone(imgView: photoImageView, sliderValue: CGFloat(sender.value), image: updatedImage!)
}
case .ended:
updatedImage = photoImageView.image
UserDefaults.standard.setValue(sliderControl.value, forKey: "slider_sepiatone")
default:
break
}
}
labelControl.textAlignment = .center
labelControl.numberOfLines = 0
labelControl.textColor = UIColor.gray
labelControl.font = UIFont.systemFont(ofSize: 16)
labelControl.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(labelControl)
NSLayoutConstraint.activate([labelControl.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30),
labelControl.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30),
labelControl.bottomAnchor.constraint(equalTo: resetConfirmCollectionView.topAnchor, constant: -80)])
}class Effects {
var context: CIContext! = CIContext(options: [.workingColorSpace: NSNull(), .outputColorSpace: NSNull()])
var currentFilter: CIFilter!
struct Filter {
let filterName: String
var filterEffectValue: Any?
var filterEffectValueName: String?
init(filterName: String, filterEffectValue: Any?, filterEffectValueName: String?) {
self.filterName = filterName
self.filterEffectValue = filterEffectValue
self.filterEffectValueName = filterEffectValueName
}
func applyFilterTo(image: UIImage, filterEffect: Filter, sliderValue: CGFloat?) -> UIImage? {
guard let cgImage = image.cgImage else { return nil }
// let context = CIContext(options: nil)
let ciImage = CIImage(cgImage: cgImage)
currentFilter = CIFilter(name: filterEffect.filterName)
currentFilter!.setDefaults()
if currentFilter == CIFilter(name: "CIUnsharpMask") {
currentFilter?.setValue(ciImage, forKey: kCIInputImageKey)
currentFilter?.setValue(sliderValue! - 0.5, forKey: kCIInputIntensityKey)
}
else if currentFilter == CIFilter(name: "CIGaussianBlur") {
// currentFilter!.setDefaults()
currentFilter?.setValue(ciImage, forKey: kCIInputImageKey)
currentFilter?.setValue(sliderValue! - 0.5, forKey: kCIInputRadiusKey)
}
else if currentFilter == CIFilter(name: "CICMYKHalftone") {
// currentFilter!.setDefaults()
currentFilter?.setValue(ciImage, forKey: kCIInputImageKey)
currentFilter?.setValue(sliderValue! - 0.5, forKey: kCIInputWidthKey)
}
else {
currentFilter?.setValue(ciImage, forKey: kCIInputImageKey)
if let filterEffectValue = filterEffect.filterEffectValue, let filterEffectValueName = filterEffect.filterEffectValueName {
currentFilter?.setValue(filterEffectValue, forKey: filterEffectValueName)
}
}
var filteredImage: UIImage?
if let output = currentFilter?.value(forKey: kCIOutputImageKey) as? CIImage,
let cgiImageResult = context.createCGImage(output, from: output.extent) {
filteredImage = UIImage(cgImage: cgiImageResult, scale: image.scale, orientation: image.imageOrientation)
}
return filteredImage
}
}
Hi, I have 2 separate collectionViews and I've been trying to change the numberOfItemsInSection of "collectionViewA" according to the didSelectItemAt indexPath of "collectionViewB". Let's say I have 2 items already setup in "collectionViewA" but if I select "collectionViewB" indexPath.row = 1, I would like to have 3 items in "collectionViewA", and if I select "collectionViewB" indexPath.row = 2, I would like to have 4 items in "collectionViewA". As far as I can see, this is possible but I couldn't find the relevant info online. Any idea on this please ?
Hi, I have a UISegmentedControl implemented programmatically that I would like to remove from the screen when I select collectionView didSelect. I've tried many solutions but couldn't get success. Any advice on that please ? Sharing the relevant code;import Foundation
import UIKit
import Photos
class PhotoViewController: UIViewController, UIScrollViewDelegate {
func effectsSegmentedControl() {
let items = ["Brightness", "Contrast", "Saturation", "Noise"]
let segmentedControl = UISegmentedControl(items: items)
segmentedControl.addTarget(self, action: #selector(effectsDidChange(_:)), for: .valueChanged)
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(segmentedControl)
NSLayoutConstraint.activate([
segmentedControl.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30),
segmentedControl.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30),
segmentedControl.bottomAnchor.constraint(equalTo: resetConfirmCollectionView.topAnchor, constant: -10)])
}
@objc func effectsDidChange(_ segmentedControl: UISegmentedControl) {
switch segmentedControl.selectedSegmentIndex {
case 0:
effectsSliderBrightness()
case 1:
effectsSliderContrast()
// sliderLabel(myText: "")
case 2:
effectsSliderSaturation()
// sliderLabel(myText: "")
case 3:
effectsSliderNoise()
// sliderLabel(myText: "")
default:
break
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == resetConfirmCollectionView {
if indexPath.row == 0 {
// photoImageView.image = pickedImage
resetConfirmCollectionView.isHidden = true
menuStackView.isHidden = false
}
if indexPath.row == 1 {
// filteredImage = pickedImage
resetConfirmCollectionView.isHidden = true
menuStackView.isHidden = false
}
}
}
Hi, I've been trying to set the slider value in the same direction with finger drag movement on the screen. From right to left, decrease the slider value and vice versa. I have set up the slider outlet and the UIPanGestureRecognizer. I'm having trouble with assigning the slider thumbRect on "addPanGesture(slider: UISlider)" method when I call it. If I assign the slider, the whole slider starts moving. I'm aiming to move the thumbRect in accordance with the UIPanGestureRecognizer. I'm sharing the relevant code. In case, you need the whole code, I'd be more than happy to share it with you. Any suggestion please ?class PhotoViewController: UIViewController {
@IBOutlet weak var effectsSlider: UISlider!
var initialCenter: CGPoint!
override func viewDidLoad() {
super.viewDidLoad()
initialCenter = effectsSlider.frame.origin
}
func addPanGesture(slider: UISlider) {
let pan = UIPanGestureRecognizer(target: self, action: #selector(PhotoViewController.handlePan(sender:)))
view.addGestureRecognizer(pan)
}
@objc func handlePan(sender: UIPanGestureRecognizer) {
let panView = sender.view!
let translation = sender.translation(in: view)
switch sender.state {
case .began, .changed:
panView.center = CGPoint(x: panView.center.x + translation.x, y: panView.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: view)
case .ended:
return
default:
break
}
}
}
Hello, I have been having trouble with configuring the systemImage size. I took a number of approaches but couldn't manage to set a size to the systemImage within the collectionView cell. Because of this, the text which is supposed to be below the image, clashes with the image due to its large size within the cell. The last approach I took with the code I'm sharing, I get an empty cell. Otherwise, I can't find a way to change the systemImage size. Could you please advise me regarding the configuration of systemImage ?Many Thanks.func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == collectionViewEffects {
let cellEffects = collectionView.dequeueReusableCell(withReuseIdentifier: "EffectsCell", for: indexPath) as! CustomEffectsCell
collectionView.backgroundColor = .systemGray6
if indexPath.row == 0 {
cellEffects.effectsLabel = "A"
let config = UIImage.SymbolConfiguration(pointSize: 0, weight: .ultraLight)
let cellImage = UIImage(systemName: "slider.horizontal.3", withConfiguration: config)
let width = ((cellImage?.size.width)!)/4
let height = ((cellImage?.size.height)!)/4
guard let context = UIGraphicsGetCurrentContext() else {
print("could not get graphics context")
return cellEffects
}
context.setStrokeColor(UIColor.yellow.cgColor)
context.setLineWidth(2)
context.stroke(cellImage?.cgImage as! CGRect)
cellImage?.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
cellEffects.effectsImage = cellImage
self.view.addSubview(cellEffects)
}
Hi, I've been trying to set the "photoImageView.image" to the image "cell.bgImage" within the collectionView indexPath based on the selection. With a tap on the collectionView's image cells, I want the photoImageView.image to change according to the tapped image cell. I have tried many ways but couldn't get success. I believe the most feasible way is implementing this in "collectionView didSelectItemAt". Any help please ?Thank you.import Foundationimport UIKitimport Photosclass PhotoViewController: UIViewController { @IBOutlet weak var photoImageView: UIImageView! @IBOutlet var photoView: UIView! @IBOutlet weak var menuStackView: UIStackView! var imagePicker = UIImagePickerController() var effects = Effects() override func viewDidLoad() { super.viewDidLoad() imagePicker.delegate = self assignTap() view.addSubview(collectionView) collectionView.backgroundColor = .white collectionView.topAnchor.constraint(equalTo: photoImageView.bottomAnchor, constant: 110).isActive = true collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 10).isActive = true collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -103).isActive = true collectionView.clipsToBounds = true collectionView.dataSource = self collectionView.delegate = self collectionView.isHidden = false } @IBAction func previewTapped(_ sender: UIButton) { sender.pulsate() if collectionView.isHidden == true { collectionView.isHidden = false } else { collectionView.isHidden = true } } @IBAction func effectsTapped(_ sender: UIButton) { sender.flash() } @IBAction func exportTapped(_ sender: UIButton) { sender.shake() } func assignTap() { let tap = UITapGestureRecognizer(target: self, action: #selector(touchTapped(_:))) photoView.addGestureRecognizer(tap) } @objc func touchTapped(_ sender: UITapGestureRecognizer) { if collectionView.isTracking == false { if menuStackView.isHidden == false { collectionView.isHidden = true menuStackView.isHidden = true } else { menuStackView.isHidden = false collectionView.isHidden = false } } } func chooseImage(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) { imagePicker.sourceType = .photoLibrary imagePicker.allowsEditing = true self.present(imagePicker,animated: true, completion: nil) } } func accessVideo(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.camera) { imagePicker.sourceType = .camera self.present(imagePicker, animated: true, completion: nil) } else { print("Camera not available") } } public func chooseLastImage(_ sender: Any) { print("photoImageView", photoImageView!) print("photoImageView.bounds", photoImageView.bounds) let targetSize: CGSize? = CGSize(width: photoImageView.bounds.width, height: photoImageView.bounds.height) let options = PHImageRequestOptions() options.isNetworkAccessAllowed = true options.deliveryMode = .highQualityFormat let imgManager = PHImageManager.default() let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)] let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) print("targetSize for request", targetSize!) imgManager.requestImage(for: fetchResult.lastObject!, targetSize: targetSize!, contentMode: .default, options: options) { (result, info) in guard let result = result else { return } DispatchQueue.main.async(execute: { self.photoImageView.image = result self.collectionView.reloadData() }) } } fileprivate let collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.translatesAutoresizingMaskIntoConstraints = false cv.register(CustomCell.self, forCellWithReuseIdentifier: "PreviewCell") return cv }()}extension PhotoViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: collectionView.frame.width/5, height: collectionView.frame.width/4) } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 11 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PreviewCell", for: indexPath) as! CustomCell cell.bgImage = self.photoImageView.image if indexPath.row == 0 { cell.labelText = "A" } if indexPath.row == 1 { cell.labelText = "B" guard cell.bgImage != nil else { return cell } cell.bgImage = effects.applyFilterTo(image: photoImageView.image!, filterEffect: Effects.Filter(filterName: "CIPhotoEffectChrome", filterEffectValue: nil, filterEffectValueName: nil)) } if indexPath.row == 2 { cell.labelText = "C" guard cell.bgImage != nil else { return cell } cell.bgImage = effects.applyFilterTo(image: photoImageView.image!, filterEffect: Effects.Filter(filterName: "CIPhotoEffectInstant", filterEffectValue: nil, filterEffectValueName: nil)) } if indexPath.row == 3 { cell.labelText = "D" guard cell.bgImage != nil else { return cell } cell.bgImage = effects.applyFilterTo(image: photoImageView.image!, filterEffect: Effects.Filter(filterName: "CIPhotoEffectNoir", filterEffectValue: nil, filterEffectValueName: kCIInputImageKey)) } if indexPath.row == 4 { cell.labelText = "E" guard cell.bgImage != nil else { return cell } cell.bgImage = effects.applyFilterTo(image: photoImageView.image!, filterEffect: Effects.Filter(filterName: "CIPhotoEffectMono", filterEffectValue: nil, filterEffectValueName: kCIInputImageKey)) } if indexPath.row == 5 { cell.labelText = "F" guard cell.bgImage != nil else { return cell } cell.bgImage = effects.applyFilterTo(image: photoImageView.image!, filterEffect: Effects.Filter(filterName: "CIExposureAdjust", filterEffectValue: 1, filterEffectValueName: kCIInputEVKey)) } if indexPath.row == 6 { cell.labelText = "G" guard cell.bgImage != nil else { return cell } cell.bgImage = effects.applyFilterTo(image: photoImageView.image!, filterEffect: Effects.Filter(filterName: "CISRGBToneCurveToLinear", filterEffectValue: nil, filterEffectValueName: nil)) } if indexPath.row == 7 { cell.labelText = "H" guard cell.bgImage != nil else { return cell } cell.bgImage = effects.applyFilterTo(image: photoImageView.image!, filterEffect: Effects.Filter(filterName: "CIPhotoEffectTransfer", filterEffectValue: nil, filterEffectValueName: nil)) } if indexPath.row == 8 { cell.labelText = "I" guard cell.bgImage != nil else { return cell } cell.bgImage = effects.applyFilterTo(image: photoImageView.image!, filterEffect: Effects.Filter(filterName: "CIColorPosterize", filterEffectValue: nil, filterEffectValueName: nil)) } if indexPath.row == 9 { cell.labelText = "J" guard cell.bgImage != nil else { return cell } cell.bgImage = effects.applyFilterTo(image: photoImageView.image!, filterEffect: Effects.Filter(filterName: "CIPhotoEffectProcess", filterEffectValue: nil, filterEffectValueName: nil)) } if indexPath.row == 10 { cell.labelText = "K" guard cell.bgImage != nil else { return cell } cell.bgImage = effects.applyFilterTo(image: photoImageView.image!, filterEffect: Effects.Filter(filterName: "CIVignetteEffect", filterEffectValue: nil, filterEffectValueName: nil)) } return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: 10, left: 5, bottom: 10, right: 5) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 1 } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PreviewCell", for: indexPath) as! CustomCell // cell.bgImage = self.photoImageView.image let imgArr = [cell.bgImage] photoImageView.image = imgArr[indexPath.row] photoImageView.reloadInputViews() }}class CustomCell: UICollectionViewCell { fileprivate let bg: UIImageView = { let iv = UIImageView() iv.translatesAutoresizingMaskIntoConstraints = false iv.contentMode = .scaleAspectFit iv.clipsToBounds = true return iv }() var bgImage: UIImage? { get { bg.image } set { bg.image = newValue } } fileprivate let label: UILabel = { let il = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20)) il.translatesAutoresizingMaskIntoConstraints = false il.contentMode = .scaleAspectFit il.clipsToBounds = true return il }() var labelText: String? { // #### get { label.text } set { label.text = newValue } } override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(bg) contentView.addSubview(label) bg.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }}extension PhotoViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage { photoImageView.image = image } dismiss(animated: true, completion: nil) } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { dismiss(animated: true, completion: nil) }}
Hi, even though I have registered the footer with a reuseIdentifier and called it in viewForSupplementaryElementOfKind and set up it's referenceSizeForFooterInSection, I have been getting the error in the title. Could you please help ? fileprivate let collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.translatesAutoresizingMaskIntoConstraints = false cv.register(CustomCell.self, forCellWithReuseIdentifier: "PreviewCell") cv.register(CustomCell.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "FooterCell") return cv }() func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if kind == UICollectionView.elementKindSectionFooter { let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FooterCell", for: indexPath) as! CustomCell footer.backgroundColor = .blue return footer } else { assert(false, "Unexpected element kind") } } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: view.frame.width, height: 10) }
Hello, I've created a UITabBarController programmatically with 3 tabBar items. When I tap on another view, a new tabBarController is pushed on to the view with the tabBar items, as I want. How can I show only the tabBar items (not the rest of its' view) with a tap on the other view ? I would like to see only the tabBar items appear on the previous viewController with a tap. As, I don't have a viewcontroller to work with on the storyboard, is it possible to do this programmatically ?Thanks very much in advance.
The collectionView pictures only start appearing if I slide them horizontally to the left. I've tried numerous solutions but couldn't solve it. If I assign the collectionView cells a background color, it works perfectly. But assigning the image of the "photoImageView" causes the problem. I must be missing something. "collectionView.reloadData()" doesn't solve the problem. Any advice please ?import Foundationimport UIKitimport Photosclass PhotoViewController: UIViewController { @IBOutlet weak var photoImageView: UIImageView! @IBOutlet weak var peeTabBar: UITabBar! @IBOutlet var photoView: UIView! var imagePicker = UIImagePickerController() override func viewDidLoad() { super.viewDidLoad() imagePicker.delegate = self assignTap() view.addSubview(collectionView) collectionView.backgroundColor = .white collectionView.topAnchor.constraint(equalTo: photoImageView.bottomAnchor, constant: 110).isActive = true collectionView.clipsToBounds = true collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 10).isActive = true collectionView.bottomAnchor.constraint(equalTo: peeTabBar.topAnchor, constant: -20).isActive = true collectionView.dataSource = self collectionView.delegate = self } func assignTap() { let tap = UITapGestureRecognizer(target: self, action: #selector(touchTapped(_:))) photoView.addGestureRecognizer(tap) } @objc func touchTapped(_ sender: UITapGestureRecognizer) { peeTabBar.isHidden = !peeTabBar.isHidden } func chooseImage(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) { imagePicker.sourceType = .photoLibrary imagePicker.allowsEditing = true self.present(imagePicker,animated: true, completion: nil) } } func accessVideo(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.camera) { imagePicker.sourceType = .camera self.present(imagePicker, animated: true, completion: nil) } else { print("Camera not available") } } public func chooseLastImage(_ sender: Any) { print("photoImageView", photoImageView!) print("photoImageView.bounds", photoImageView.bounds) let targetSize: CGSize? = CGSize(width: photoImageView.bounds.width, height: photoImageView.bounds.height) let options = PHImageRequestOptions() options.isNetworkAccessAllowed = true options.deliveryMode = .highQualityFormat let imgManager = PHImageManager.default() let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)] let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) print("targetSize for request", targetSize!) //What is its value imgManager.requestImage(for: fetchResult.lastObject!, targetSize: targetSize!, contentMode: .default, options: options) { (result, info) in guard let result = result else { return } DispatchQueue.main.async(execute: { self.photoImageView.image = result }) } } fileprivate let collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.translatesAutoresizingMaskIntoConstraints = false cv.register(CustomCell.self, forCellWithReuseIdentifier: "PreviewCell") return cv }()}extension PhotoViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: collectionView.frame.width/5, height: collectionView.frame.width/4) } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 11 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PreviewCell", for: indexPath) as! CustomCell DispatchQueue.main.async { cell.bgImage = self.photoImageView.image } return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: 10, left: 5, bottom: 10, right: 5) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 5 }}class CustomCell: UICollectionViewCell { fileprivate let bg: UIImageView = { let iv = UIImageView() iv.translatesAutoresizingMaskIntoConstraints = false iv.contentMode = .scaleAspectFit iv.clipsToBounds = true return iv }() var bgImage: UIImage? { get { bg.image } set { bg.image = newValue } } override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(bg) bg.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }}extension PhotoViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage { photoImageView.image = image } dismiss(animated: true, completion: nil) } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { dismiss(animated: true, completion: nil) }}
I would like to access "photoImageView" outlet or the function "chooseLastImage" from the "CustomCell" class, "let iv = UIImageView()", in order to have the same picture on "photoImageView" ,and "let iv = UIImageView()" in the collectionView. Any advice please ? import Foundationimport UIKitimport Photosclass PhotoViewController: UIViewController { @IBOutlet weak var photoImageView: UIImageView! @IBOutlet weak var peeTabBar: UITabBar! @IBOutlet var photoView: UIView! var imagePicker = UIImagePickerController() override func viewDidLoad() { super.viewDidLoad() imagePicker.delegate = self assignTap() view.addSubview(collectionView) collectionView.backgroundColor = .white collectionView.topAnchor.constraint(equalTo: photoImageView.bottomAnchor, constant: 110).isActive = true collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true collectionView.bottomAnchor.constraint(equalTo: peeTabBar.topAnchor, constant: -20).isActive = true collectionView.delegate = self collectionView.dataSource = self } func assignTap() { let tap = UITapGestureRecognizer(target: self, action: #selector(touchTapped(_:))) photoView.addGestureRecognizer(tap) } @objc func touchTapped(_ sender: UITapGestureRecognizer) { peeTabBar.isHidden = !peeTabBar.isHidden } func chooseImage(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) { imagePicker.sourceType = .photoLibrary imagePicker.allowsEditing = true self.present(imagePicker,animated: true, completion: nil) } } func accessVideo(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.camera) { imagePicker.sourceType = .camera self.present(imagePicker, animated: true, completion: nil) } else { print("Camera not available") } } public func chooseLastImage(_ sender: Any) { print("photoImageView", photoImageView!) print("photoImageView.bounds", photoImageView.bounds) let targetSize: CGSize? = CGSize(width: photoImageView.bounds.width, height: photoImageView.bounds.height) let options = PHImageRequestOptions() options.isNetworkAccessAllowed = true options.deliveryMode = .highQualityFormat let imgManager = PHImageManager.default() let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)] let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) print("targetSize for request", targetSize!) //What is its value imgManager.requestImage(for: fetchResult.lastObject!, targetSize: targetSize!, contentMode: .default, options: options) { (result, info) in guard let result = result else { return } DispatchQueue.main.async(execute: { self.photoImageView.image = result }) } } fileprivate let collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.translatesAutoresizingMaskIntoConstraints = false cv.register(CustomCell.self, forCellWithReuseIdentifier: "PreviewCell") return cv }()}extension PhotoViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: collectionView.frame.width/5, height: collectionView.frame.width/5) } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 11 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PreviewCell", for: indexPath) as! CustomCell cell.backgroundColor = .red return cell }}class CustomCell: UICollectionViewCell { fileprivate let bg: UIImageView = { let iv = UIImageView() iv.translatesAutoresizingMaskIntoConstraints = false iv.contentMode = .scaleAspectFill iv.clipsToBounds = true return iv }() override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(bg) bg.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }}extension PhotoViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage { photoImageView.image = image } dismiss(animated: true, completion: nil) } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { dismiss(animated: true, completion: nil) }}
The function is called from the previous viewController, the code compiles succesfully. When I run it and click the tableView row that calls this function, I receive "Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value", underlining the "targetSize" causing the error. After I set a debug breakpoint on the "targetSize" and step over the error, it takes me back to the "photoImageView" outlet(which is properly connected to the storyboardy) then back to the "targetSize"Any help please ?public func chooseLastImage(_ sender: Any) { let scale = UIScreen.main.scale let targetSize: CGSize? = CGSize(width: photoImageView.bounds.width * scale, height: photoImageView.bounds.height * scale) let options = PHImageRequestOptions() options.isNetworkAccessAllowed = true options.deliveryMode = .highQualityFormat let imgManager = PHImageManager.default() let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key:"lastCreationDate", ascending: true)] let fetchResult: PHFetchResult<PHAsset> = PHAsset.fetchAssets(with: (.image), options: fetchOptions) imgManager.requestImage(for: fetchResult.lastObject!, targetSize: targetSize!, contentMode: .default, options: options) { (result, info) in guard let result = result else { return } DispatchQueue.main.async(execute: { self.photoImageView.image = result }) } }}