Passing Image from View Controller to UIview in swift - objective-c

I want to pass the image from view controller to uiview that added as subview.here I put my code that how I added the subview from view controller.
let subviewArray = NSBundle.mainBundle().loadNibNamed("AddVisitorView", owner: self, options: nil)
let filtersView : AddVisitorView = subviewArray[0] as AddVisitorView
filtersView.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2.5);
self.view.addSubview(filtersView)
Here is the image that I want to pass to UIview. UIview class should have some implementation to retrieve that image.So how to pass the image between them
var finalImage :UIImage = UIImage(CIImage: outputImage)!

you need to have a property on your subview class and listen to changes on that property
Have a look at this code
class View: UIView {
var image: UIImage? {
didSet {
// do something with image
}
}
}
class ViewController: UIViewController {
let subview: View = View()
override func viewDidLoad() {
super.viewDidLoad()
}
func getTheImage() {
let finalImage = UIImage(...)
subview.image = finalImage
}
}

Related

Xib not showing up in view

I have a Xib file trying to set it up with my storyboard. Everything in the Xib file is fine, but for some reason, it's not showing. I imported a file from GitHub which is set to my Xib, it's in Objective-C and I set the bridging, no errors. But when I run it nothing shows its blank. Did I not set something in the View Controller? Everything is done programmatically and I just set the class in storyboard.
Screenshot of storyboard:
What the simulator gives me when I push to the ViewController:
This is what I'm supposed to see:
What I am trying to implement -
https://github.com/jberlana/JBCroppableView
My XIB class
import UIKit
class CropViewXIB: UIView {
#IBOutlet weak var ImageView: JBCroppableImageView!
#IBAction func SubAction(_ sender: Any) {
ImageView.removePoint()
}
#IBAction func AddAction(_ sender: Any) {
ImageView.addPoint()
}
#IBAction func UndoAction(_ sender: Any) {
ImageView.reverseCrop()
}
#IBAction func CropAction(_ sender: Any) {
ImageView.crop()
}
override init(frame: CGRect) {
super.init(frame: frame)
commomInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commomInit()
}
private func commomInit(){
Bundle.main.loadNibNamed("CropViewXIB", owner: self, options: nil)
self.addSubview(ImageView)
ImageView.frame = self.bounds
ImageView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
}
my view controller
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var cropView: CropViewXIB!
override func viewDidLoad() {
super.viewDidLoad()
}
}
The issue is that you didn't actually get the parent view for your UINib object.
Bundle.main.loadNibNamed("CropViewXIB", owner: self, options: nil)
The line above returns an [Any] in your case you aren't even using the view that it is returning. so the idea is to get the first object from it and cast it as UIView such as:
Bundle.main.loadNibNamed("CropViewXIB", owner: self, options: nil)?.first as? UIView
Personally this is how I interact with a Nib. I create a view property of type UIView that can be referred as the parent view for the nib, and all subviews get added to it instead of self.
Something like this:
final class SomeNibView: UIView {
public var view: UIView!
private func setup() { // called to the initializer
// grab the views from loadNibNamed
guard let _view = Bundle.main.loadNibNamed("name", owner: self, options: nil)?.first as? UIView else { return }
// set it to our view property
view = _view
// add this property to the nib subview aka self
addSubview(view)
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
private func addMulitpleSubviews() {
// instead of doing self.addSubview(....) when it comes to add other subviews
// you'll do this view.addSubview(....)
}
}
Try to load xib using programming not using storyboard.
override func viewDidLoad()
{
super.viewDidLoad()
guard let yourXIB = Bundle.main.loadNibNamed("CropViewXIB", owner: self, options: nil)?.first as? CropViewXIB else { return}
self.view.addSubview(yourXIB)
}

Communication between view controllers, not able to pass on the data to the outlet of second view controller

Two view controllers:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (sender as! cell1).name.text == "ww"{
let s = segue.destination as! DetailViewController
s.detail?.text = "wwwwwwwwwww"
}
}
I am new to coding. What I am trying here is to communicate between view controllers. For some reason, I am not able to show the wwwwwwwwwww in the label of the second view controller
At the prepare function the view hasn't been loaded yet from storyboard, so the outlets of the DetailViewController are still nil.
Create a public variable in the DetailViewController which will be available at prepare, then in the viewDidLoad method of DetailViewController you can set the label's text to be the content of that variable.
class DetailViewController: UIViewController {
var text: String?
override function viewDidLoad() {
super.viewDidLoad()
label.text = text
}
}
Then in your list viewcontroller set the text property of detail vc:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard (sender as! cell1).name.text == "ww",
let detailVc = segue.destination as? DetailViewController
else { return }
detailVc.text = "wwwwwwwwwww"
}

How to refer UICollectionView from UICollectionViewCell?

Can I refer UICollectionView from UICollectionViewCell?
I finally want to refer ViewController from UICollectionViewCell.
Following codes are in my CustomCollectionViewCell Class.
I want to archive tweet support in this class.
#IBAction func tweetBtnTapped(_ sender: Any) {
let cvc = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
if let c = cvc {
c.setInitialText("test tweet from iOS App")
### How can I refer ViewController??
viewController = ???????
if let vc = viewController {
vc.present(c, animated: true, completion: nil)
}
}
}
Please provide the code sample or what you are trying to achieve. What I understand is that you want some action back in your view controller when you perform some action on your cell. Am I correct?
So As per the comments, Custom collection view cell :
class CustomeCell: UICollectionViewCell {
#IBAction func tweetButtonPressed() {
let cvc = SLComposeViewController(forServiceType:SLServiceTypeTwitter)
if let c = cvc {
c.setInitialText("test tweet from iOS App")
self.parentViewController?.presentViewController(c, animated: true, completion: nil)
}
}
}
Create a Extension.Swift file :
import UIKit
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.nextResponder()
if let viewController = parentResponder as? UIViewController {
return viewController
}
}
return nil
}
}
This is working for me. All the best!

Transitioning between view controller, OS X

I am trying to write a single window timer application, where when the user presses the start button I want it to show another view controller with countdown etc. I'm also using story board in Xcode, where I have got a segue which connects the start button and the second view controller. However, there are only three different styles i.e. modal, sheet, and pop-over. I want to replace the first view controller the second one in the window. I cannot find a way to do that. I tried using a custom style for the segue, and in that use presentViewController: animator: method but I cannot figure out what to send as the argument for the animator:.
What is the simplest/proper way to transition from one view controller to the other in one window and vice versa?
Also in the storyboard when I select a view controller it shows an attribute called "Presentation" which can be multiple and single, what do those represent?
I think the simplest way is that swapping contentViewController of NSWindow.
// in NSViewController's subclass
#IBAction func someAction(sender: AnyObject) {
let nextViewController = ... // instantiate from storyboard or elsewhere
if let window = view.window where window.styleMask & NSFullScreenWindowMask > 0 {
// adjust view size to current window
nextViewController.view.frame = CGRectMake(0, 0, window.frame.width, window.frame.height)
}
view.window?.contentViewController = nextViewController
}
This is option #1.
If you want to use segue, create custom one and set it to segue class with identifier in IB.
class ReplaceSegue: NSStoryboardSegue {
override func perform() {
if let fromViewController = sourceController as? NSViewController {
if let toViewController = destinationController as? NSViewController {
// no animation.
fromViewController.view.window?.contentViewController = toViewController
}
}
}
}
This is option #2.
Last option is using presentViewController:animator: of NSViewController. The code below is custom NSViewControllerPresentationAnimator for dissolve animation.
class ReplacePresentationAnimator: NSObject, NSViewControllerPresentationAnimator {
func animatePresentationOfViewController(viewController: NSViewController, fromViewController: NSViewController) {
if let window = fromViewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
fromViewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
viewController.view.alphaValue = 0
window.contentViewController = viewController
viewController.view.animator().alphaValue = 1.0
})
}
}
func animateDismissalOfViewController(viewController: NSViewController, fromViewController: NSViewController) {
if let window = viewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
viewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
fromViewController.view.alphaValue = 0
window.contentViewController = fromViewController
fromViewController.view.animator().alphaValue = 1.0
})
}
}
}
Then present VC like this.
#IBAction func replaceAction(sender: AnyObject) {
let nextViewController = ... // instantiate from storyboard or elsewhere
presentViewController(nextViewController, animator: ReplacePresentationAnimator())
}
For dismissal, call presentingViewController's dismissViewController: in the presented VC.
#IBAction func dismissAction(sender: AnyObject) {
presentingViewController?.dismissViewController(self)
}
Swift4 Version
class ReplacePresentationAnimator: NSObject, NSViewControllerPresentationAnimator {
func animatePresentation(of viewController: NSViewController, from fromViewController: NSViewController) {
if let window = fromViewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
fromViewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
viewController.view.alphaValue = 0
window.contentViewController = viewController
viewController.view.animator().alphaValue = 1.0
})
}
}
func animateDismissal(of viewController: NSViewController, from fromViewController: NSViewController) {
if let window = viewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
viewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
fromViewController.view.alphaValue = 0
window.contentViewController = fromViewController
fromViewController.view.animator().alphaValue = 1.0
})
}
}
}
Hope this help.
If you have one parent view controller, you can assign child view controllers to it, and use the transition method. Example code, to be placed in viewDidLoad of the parent view controller:
if let firstController = self.storyboard?.instantiateController(withIdentifier: "firstController") as? NSViewController {
firstController.view.autoresizingMask = [.width, .height]
firstController.view.frame = self.view.bounds
self.addChild(firstController)
self.view.addSubview(firstController.view)
}
if let secondController = self.storyboard?.instantiateController(withIdentifier: "secondController") as? NSViewController {
self.addChild(secondController)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
if let firstController = self.children.first, let secondController = self.children.last {
self.transition(from: firstController, to: secondController, options: .crossfade, completionHandler: nil)
}
}
It's essential that the view of the first child controller is being added as sub view to the view of the parent controller, otherwise the transition method doesn't work.
In the example above, a storyboard is used with one main view controller (= self), one child view controller with storyboard ID "firstController', and another child view controller with storyboard ID "secondController'

UIPopoverPresentationController on iOS 8 iPhone

Does anyone know if UIPopoverPresentationController can be used to present popovers on iPhones? Wondering if Apple added this feature on iOS 8 in their attempt to create a more unified presentation controllers for iPad and iPhone.
Not sure if its OK to ask/answer questions from Beta. I will remove it in that case.
You can override the default adaptive behaviour (UIModalPresentationFullScreen in compact horizontal environment, i.e. iPhone) using the
adaptivePresentationStyleForPresentationController: method available through UIPopoverPresentationController.delegate.
UIPresentationController uses this method to ask the new presentation style to use, which in your case, simply returning UIModalPresentationNone will cause the UIPopoverPresentationController to render as a popover instead of fullscreen.
Here's an example of the popover using a segue setup in storyboard from a UIBarButtonItem to "present modally" a UIViewController
class SomeViewController: UIViewController, UIPopoverPresentationControllerDelegate {
// override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) { // swift < 3.0
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "PopoverSegue" {
if let controller = segue.destinationViewController as? UIViewController {
controller.popoverPresentationController.delegate = self
controller.preferredContentSize = CGSize(width: 320, height: 186)
}
}
}
// MARK: UIPopoverPresentationControllerDelegate
//func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!) -> UIModalPresentationStyle { // swift < 3.0
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
// Return no adaptive presentation style, use default presentation behaviour
return .None
}
}
This trick was mentioned in WWDC 2014 session 214 "View Controller Advancement in iOS8" (36:30)
If anybody wants to present a popover with code only, you can use the following approach.
OBJECTIVE - C
Declare a property of UIPopoverPresentationController:
#property(nonatomic,retain)UIPopoverPresentationController *dateTimePopover8;
Use the following method to present the popover from UIButton:
- (IBAction)btnSelectDatePressed:(id)sender
{
UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
dateVC.preferredContentSize = CGSizeMake(280,200);
destNav.modalPresentationStyle = UIModalPresentationPopover;
_dateTimePopover8 = destNav.popoverPresentationController;
_dateTimePopover8.delegate = self;
_dateTimePopover8.sourceView = self.view;
_dateTimePopover8.sourceRect = sender.frame;
destNav.navigationBarHidden = YES;
[self presentViewController:destNav animated:YES completion:nil];
}
Use the following method to present the popover from UIBarButtonItem:
- (IBAction)btnSelectDatePressed:(id)sender
{
UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
dateVC.preferredContentSize = CGSizeMake(280,200);
destNav.modalPresentationStyle = UIModalPresentationPopover;
_dateTimePopover8 = destNav.popoverPresentationController;
_dateTimePopover8.delegate = self;
_dateTimePopover8.sourceView = self.view;
CGRect frame = [[sender valueForKey:#"view"] frame];
frame.origin.y = frame.origin.y+20;
_dateTimePopover8.sourceRect = frame;
destNav.navigationBarHidden = YES;
[self presentViewController:destNav animated:YES completion:nil];
}
Implement this delegate method too in your view controller:
- (UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller {
return UIModalPresentationNone;
}
To dismiss this popover, simply dismiss the view controller. Below is the code to dismiss the view controller:
-(void)hideIOS8PopOver
{
[self dismissViewControllerAnimated:YES completion:nil];
}
SWIFT
Use the following method to present the popover from UIButon:
func filterBooks(sender: UIButon)
{
let filterVC = FilterDistanceViewController(nibName: "FilterDistanceViewController", bundle: nil)
var filterDistanceViewController = UINavigationController(rootViewController: filterVC)
filterDistanceViewController.preferredContentSize = CGSizeMake(300, 205)
let popoverPresentationViewController = filterDistanceViewController.popoverPresentationController
popoverPresentationViewController?.permittedArrowDirections = .Any
popoverPresentationViewController?.delegate = self
popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
popoverPresentationViewController!.sourceView = self.view;
popoverPresentationViewController!.sourceRect = sender.frame
filterDistanceViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
filterDistanceViewController.navigationBarHidden = true
self.presentViewController(filterDistanceViewController, animated: true, completion: nil)
}
Use the following method to present the popover from UIBarButtonItem:
func filterBooks(sender: UIBarButtonItem)
{
let filterVC = FilterDistanceViewController(nibName: "FilterDistanceViewController", bundle: nil)
var filterDistanceViewController = UINavigationController(rootViewController: filterVC)
filterDistanceViewController.preferredContentSize = CGSizeMake(300, 205)
let popoverPresentationViewController = filterDistanceViewController.popoverPresentationController
popoverPresentationViewController?.permittedArrowDirections = .Any
popoverPresentationViewController?.delegate = self
popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
popoverPresentationViewController!.sourceView = self.view;
var frame:CGRect = sender.valueForKey("view")!.frame
frame.origin.y = frame.origin.y+20
popoverPresentationViewController!.sourceRect = frame
filterDistanceViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
filterDistanceViewController.navigationBarHidden = true
self.presentViewController(filterDistanceViewController, animated: true, completion: nil)
}
Implement this delegate method too in your view controller:
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle{
return .None
}
Please make sure to add delegate UIPopoverPresentationControllerDelegate in .h/.m/.swift file
PROBLEM: iPhone popover displays fullscreen and does not respect preferredContentSize value.
SOLUTION: Contrary to what Apple suggests in the UIPopoverPresentationController Class reference, presenting the view controller after getting a reference to the popover presentation controller and configuring it.
// Get the popover presentation controller and configure it.
//...
// Present the view controller using the popover style.
[self presentViewController:myPopoverViewController animated: YES completion: nil];
Make sure to implement UIAdaptivePresentationControllerDelegate
like this:
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
If you don't want full-screen popovers
I've found some workaround.
On Xcode6.1, use presentationController.delegate instead of popoverPresentationController.delegate.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier compare:#"showPopOver"] == NSOrderedSame) {
UINavigationController * nvc = segue.destinationViewController;
UIPresentationController * pc = nvc.presentationController;
pc.delegate = self;
}
}
#pragma mark == UIPopoverPresentationControllerDelegate ==
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
{
return UIModalPresentationNone;
}
In WWDC 2014 "View Controller Advancements in iOS8", below codes can show popover on iPhone.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UINavigationController * nvc = segue.destinationViewController;
UIPopoverPresentationController * pvc = nvc.popoverPresentationController;
pvc.delegate = self;
}
#pragma mark == UIPopoverPresentationControllerDelegate ==
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
{
return UIModalPresentationNone;
}
But On Xcode 6.1, these codes shows FullScreen presentation...
(nvc.popoverPresentationController is nil)
I doubt it might be an Apple's bug.
In iOS 8.3 and later, use the following syntax in the UIPopoverPresentationControllerDelegate protocol to override your popup's UIModalPresentationStyle.
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
You can extend the UIPopoverPresentationControllerDelegate like this:
protocol PopoverPresentationSourceView {}
extension UIBarButtonItem : PopoverPresentationSourceView {}
extension UIView : PopoverPresentationSourceView {}
extension UIPopoverPresentationControllerDelegate where Self : UIViewController {
func present(popover: UIViewController,
from sourceView: PopoverPresentationSourceView,
size: CGSize, arrowDirection: UIPopoverArrowDirection) {
popover.modalPresentationStyle = .popover
popover.preferredContentSize = size
let popoverController = popover.popoverPresentationController
popoverController?.delegate = self
if let aView = sourceView as? UIView {
popoverController?.sourceView = aView
popoverController?.sourceRect = CGRect(x: aView.bounds.midX, y: aView.bounds.midY, width: 0, height: 0)
} else if let barButtonItem = sourceView as? UIBarButtonItem {
popoverController?.barButtonItem = barButtonItem
}
popoverController?.permittedArrowDirections = arrowDirection
present(popover, animated: true, completion: nil)
}
}
You can now call present(popover: from: size: arrowDirection: ) from any view controller that implements UIPopoverPresentationControllerDelegate eg.
class YourViewController : UIViewController {
#IBAction func someButtonPressed(_ sender: UIButton) {
let popover = SomeViewController()
present(popover: popover, from: sender, size: CGSize(width: 280, height: 400), arrowDirection: .right)
}
}
extension YourViewController : UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
}
add these two methods in your WEBVIEW class. and add
-(void) prepareForSegue: (UIStoryboardSegue * ) segue sender: (id) sender {
// Assuming you've hooked this all up in a Storyboard with a popover presentation style
if ([segue.identifier isEqualToString: #"showPopover"]) {
UINavigationController * destNav = segue.destinationViewController;
pop = destNav.viewControllers.firstObject;
// This is the important part
UIPopoverPresentationController * popPC = destNav.popoverPresentationController;
popPC.delegate = self;
}
}
- (UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller {
return UIModalPresentationNone;
}
In the UIAdaptivePresentationControllerDelegate you must use this method:
func adaptivePresentationStyle(for: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle
instead of this:
func adaptivePresentationStyle(for: UIPresentationController) -> UIModalPresentationStyle