UITextKit and exclusionPaths: undependable indent when editing - xcode

I have a problem with UITextKit using exclusionPaths: when I place an image inside a TextView, that I’m editing, first everything looks fine:
But when the „Done“-Button is tapped, it will look like this, the ident is wrong:
This is the class to store the informations for the image
class ImageClass {
var image: UIImage!
var imageView: UIImageView
var imageName: String!
var active:Bool
var exclusivePath: UIBezierPath!
init(image: UIImage!, imageName: String!) {
self.image = image
imageView = UIImageView(image: image!)
self.imageName = imageName
self.active = false
self.exclusivePath = nil
}
}
The user chooses the image in a UICollectionView that fires a delegate, when the image was selected. (imageViewObjects is an array, where I can put objects of ImageClass, so I can use mutiple images)
// MARK: - SelectImageDelegate
func selectedImage(name:String) {
let image = UIImage(named: name)
let imageViewObject = ImageClass(image: image, imageName: name)
self.imageViewObjects.append(imageViewObject)
imageViewObject.imageView.frame = CGRectMake(4, 7, width!, height!)
// define the exlusionPaths
let bezierPath = self.exclusionPathForImageView(imageViewObject.imageView)
imageViewObject.exclusivePath = bezierPath
self.updateExclusionPaths()
self.textView.addSubview(imageViewObject.imageView)
}
// set UIBezierPath for the UIImageView
func exclusionPathForImageView(imageView: UIImageView) -> UIBezierPath {
let bezierPath = UIBezierPath(rect:
CGRectMake(imageView.frame.origin.x, imageView.frame.origin.y,
imageView.frame.width, imageView.frame.height))
return bezierPath
}
func updateExclusionPaths() {
textView.textContainer.exclusionPaths = []
for imageViewObject in self.imageViewObjects {
textView.textContainer.exclusionPaths.append(imageViewObject.exclusivePath)
}
}
The context of bezierPath is ok.
When „Done“ is tapped, I stop the editing
let doneBarButton = UIBarButtonItem(title: "Done", style: .Done, target: view, action: Selector("endEditing:"))
In textViewDidEndEditing() now I do nothing.
I also tried it with a UIButton for the image. Similar result.
Any tip for a solution? plz help me!!!!

found a workaround:
func textViewShouldEndEditing(textView: UITextView) -> Bool {
textView.editable = false
}
and I had to add to set textView.editable = true, i.e. in viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: "resetEditable")
tapGesture.numberOfTapsRequired = 1
self.textView.addGestureRecognizer(tapGesture)
func resetEditable() {
textView.editable = true
textView.becomeFirstResponder()
}

Related

How to get a custom tab bar to display a tab bar item's selected image set in Xcode?

I've created a custom tab bar that is displaying tab bar items correctly. When I select a tab / icon the tab bar item's view controller is displayed but the icon does not change to the 'Selected image' icon i.e. the icons don't change when their view controller is being shown.
What am I doing wrong? How can I get the icons to update to the images that I've set on IB as the selected images?
Here is some of my code:
class CustomTabBarController: UITabBarController, CustomTabBarDataSource, CustomTabBarDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.isHidden = true
let customTabBar = CustomTabBar(frame: self.tabBar.frame)
customTabBar.datasource = self
customTabBar.delegate = self
customTabBar.setup()
self.view.addSubview(customTabBar)
}
// MARK: - CustomTabBarDataSource
func tabBarItemsInCustomTabBar(_ tabBarView: CustomTabBar) -> [UITabBarItem] {
return tabBar.items!
}
// MARK: - CustomTabBarDelegate
func didSelectViewController(_ tabBarView: CustomTabBar, atIndex index: Int) {
self.selectedIndex = index
}
}
class CustomTabBar: UIView {
var tabBarItems: [UITabBarItem]!
var customTabBarItems: [CustomTabBarItem]!
var tabBarButtons: [UIButton]!
func setup() {
tabBarItems = datasource.tabBarItemsInCustomTabBar(self)
customTabBarItems = []
tabBarButtons = []
let containers = createTabBarItemContainers()
createTabBarItems(containers)
}
func createTabBarItems(_ containers: [CGRect]) {
var index = 0
for item in tabBarItems {
let container = containers[index]
let customTabBarItem = CustomTabBarItem(frame: container)
customTabBarItem.setup(item)
self.addSubview(customTabBarItem)
customTabBarItems.append(customTabBarItem)
let button = UIButton(frame: CGRect(x: 0, y: 0, width: container.width, height: container.height))
button.addTarget(self, action: #selector(CustomTabBar.barItemTapped(_:)), for: UIControlEvents.touchUpInside)
customTabBarItem.addSubview(button)
tabBarButtons.append(button)
index += 1
}
}
func barItemTapped(_ sender : UIButton) {
let index = tabBarButtons.index(of: sender)!
delegate.didSelectViewController(self, atIndex: index)
}
Change
class CustomTabBar: UIView {
to:
class CustomTabBar: UITabBar {
Then your custom tab bar will act like a tab bar!
Well I had a same kind of functionality and implemented with UITabBarController like this.
enum TabType:Int{
case viewController1 = 0
case viewController2 = 1
case viewController3 = 2
}
class CustomTabbarVC: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
convenience init(userType : UserType){
self.init()
addViewControllers()
setupOnInit()
let tabBar = self.tabBar
tabBar.selectionIndicatorImage = UIImage().createSelectionIndicator(UIColor(red: 22/255, green: 52/255, blue: 89/255, alpha: 1.0), size: CGSize(width: tabBar.frame.width/CGFloat(tabBar.items!.count), height: tabBar.frame.height), lineWidth: 3.0)
}
func setupOnInit(){
delegate = self
tabBar.barStyle = UIBarStyle.black
tabBar.isTranslucent = false
}
func addViewControllers(){
// We will add 3 controllers
let viewController1 = viewController1(nibName: “viewController1”, bundle: nil)
let viewController2 = viewController2(nibName: “viewController2”, bundle: nil)
let viewController3 = viewController3(nibName: “viewController3”, bundle: nil)
let viewController1Navigation = UINavigationController(rootViewController: viewController1)
viewController1Navigation.tabBarItem = getTabbarItem(.viewController1)
viewController1Navigation.tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)
let viewController2Navigation = UINavigationController(rootViewController: viewController2)
viewController2Navigation.tabBarItem = getTabbarItem(.viewController2)
viewController2Navigation.tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)
let viewController3Navigation = UINavigationController(rootViewController: viewController3)
viewController3Navigation.tabBarItem = getTabbarItem(.viewController3)
viewController3Navigation.tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)
viewControllers = [viewController1Navigation,viewController2Navigation,viewController3Navigation]
}
func getTabbarItem(_ tabType:TabType)->UITabBarItem{
// Fetch tab bar item and set image according to it.
var image = String()
var selectedImage = String()
if tabType == .viewController1{
image = “img_viewController1_tab_nonSelected”
selectedImage = “img_viewController1_tab_Selected”
}else if tabType == .viewController2{
image = “img_viewController2_tab_nonSelected”
selectedImage = “img_viewController2_tab_Selected”
}else if tabType == .viewController3{
image = “img_viewController3_tab_nonSelected”
selectedImage = “img_viewController3_tab_Selected”
}else{
print("Unknown tab type")
}
if let imageName:String = image,let selectedImageName:String = selectedImage{
return UITabBarItem(title: nil, image: UIImage(named: imageName)?.withRenderingMode(.alwaysOriginal), selectedImage: UIImage(named: selectedImageName)?.withRenderingMode(.alwaysOriginal))
}else{
return UITabBarItem()
}
}
}
extension UIImage {
func createSelectionIndicator(_ color: UIColor, size: CGSize, lineWidth: CGFloat) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(CGRect(x: 0, y: size.height - lineWidth, width: size.width, height: lineWidth))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
How to implement in App delegate
class AppDelegate: UIResponder, UIApplicationDelegate{
var window: UIWindow?
var customTabbarVC: CustomTabbarVC?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
customTabbarVC = customTabbarVC() // It will invoke init methods of customtabbarvc
window?.rootViewController = customTabbarVC // Here your tab bar controller will setup
return true
}
// Other APP DELEGATE METHODS
}
Let me know if you have any questions..
For Changing image in your custom tab bar button after you click the button you need to write the code to change image in below function
func barItemTapped(_ sender : UIButton) {
}
similarly
func barItemTapped(_ sender : UIButton)
{
if sender.tag == 1
{
tabBarButtons.setImage(UIImage(named:"FirstImage.png"), forState: .Normal)
}
else
{
tabBarButtons.setImage(UIImage(named:"SecImage.png"), forState: .Normal)
}
}

Swift - GLKit View CIFilter Image

I am trying to use a GLIKit View in order to modify an Image. The class I have so far is working well all the CIFilters except for the CILineOverlay it renders a black view. If I use any other effect it works well.
Why is the CILineOverlay not showing?
class ImageView: GLKView {
let clampFilter = CIFilter(name: "CIAffineClamp")!
let blurFilter = CIFilter(name: "CILineOverlay")!
let ciContext:CIContext
override init(frame: CGRect) {
let glContext = EAGLContext(API: .OpenGLES2)
ciContext = CIContext(
EAGLContext: glContext,
options: [
kCIContextWorkingColorSpace: NSNull()
]
)
super.init(frame: frame, context: glContext)
enableSetNeedsDisplay = true
}
required init(coder aDecoder: NSCoder) {
let glContext = EAGLContext(API: .OpenGLES2)
ciContext = CIContext(
EAGLContext: glContext,
options: [
kCIContextWorkingColorSpace: NSNull()
]
)
super.init(coder: aDecoder)!
context = glContext
enableSetNeedsDisplay = true
}
#IBInspectable var inputImage: UIImage? {
didSet {
inputCIImage = inputImage.map { CIImage(image: $0)! }
}
}
#IBInspectable var blurRadius: Float = 0 {
didSet {
//blurFilter.setValue(blurRadius, forKey: "inputIntensity")
setNeedsDisplay()
}
}
var inputCIImage: CIImage? {
didSet { setNeedsDisplay() }
}
override func drawRect(rect: CGRect) {
if let inputCIImage = inputCIImage {
clampFilter.setValue(inputCIImage, forKey: kCIInputImageKey)
blurFilter.setValue(clampFilter.outputImage!, forKey: kCIInputImageKey)
let rect = CGRect(x: 0, y: 0, width: drawableWidth, height: drawableHeight)
ciContext.drawImage(blurFilter.outputImage!, inRect: rect, fromRect: inputCIImage.extent)
}
}
}
The Apple docs states "The portions of the image that are not outlined are transparent." - this means you are drawing black lines over a black background. You can simply composite the output from the filter over a white background to make the lines appear:
let background = CIImage(color: CIColor(color: UIColor.whiteColor()))
.imageByCroppingToRect(inputCIImage.extent)
let finalImage = filter.outputImage!
.imageByCompositingOverImage(background)

UISwitch set on/off Image

I want to set my Switch like this:
But I try in ios9 , it does not work.
I saw in apple UISwitch Class Reference.
It says that :
Discussion
In iOS 7, this property has no effect.
How about iOS 9? Any one success?
My Code:
switch1 = UISwitch(frame:CGRectMake(self.view.frame.width/2 - 20, 400, 10, 100))
switch1.on = true
switch1.onTintColor = UIColor.lightGrayColor()
switch1.tintColor = UIColor.greenColor()
switch1.thumbTintColor = UIColor.blackColor()
//set on/off image
switch1.onImage = UIImage(named: "on-switch")
switch1.offImage = UIImage(named: "off-switch")
Use a UIButton instead.
let switchButton = UIButton(type: .Custom)
switchButton.selected = true
switchButton.setImage(UIImage(named: "on-switch"), forState: .Selected)
switchButton.setImage(UIImage(named: "off-switch"), forState: .Normal)
Use switchButton.isSelected instead of switch1.on. You'll have to toggle switchButton.isSelected when it is tapped, which you can do like this:
switchButton.isSelected.toggle()
For iOS 13, you could do this way:
let switcher = UISwitch()
switcher.addTarget(self, action: #selector(pressed), for: .valueChanged)
#objc func pressed(sender: UISwitch) {
let color = UIColor(patternImage: UIImage(named: sender.isOn ? "on.png": "off.png")!)
if sender.isOn {
sender.onTintColor = color
} else {
sender.tintColor = color
sender.subviews[0].subviews[0].backgroundColor = color
}
}
NOTE: your image should look like:
Then the final result is:
Not an exact answer to your question, but if you want a completely custom button switch programmatically (that you can add text to), this will work too:
import UIKit
class RDHiddenVisibleButton: UIButton {
// Hidden / Visible Button Function
var isOn = false
override init(frame: CGRect) {
super.init(frame: frame)
initButton()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initButton()
}
func initButton() {
layer.borderWidth = 2.0
layer.borderColor = Colors.radiusGreen.cgColor
layer.cornerRadius = frame.size.height/2
setTitleColor(Colors.radiusGreen, for: .normal)
addTarget(self, action: #selector(RDHiddenVisibleButton.buttonPressed), for: .touchUpInside)
}
#objc func buttonPressed() {
activateButton(bool: !isOn)
}
func activateButton(bool: Bool) {
isOn = bool
let color = bool ? Colors.radiusGreen : .clear
let title = bool ? "Hidden" : "Visible"
let titleColor = bool ? . white : Colors.radiusGreen
setTitle(title, for: .normal)
setTitleColor(titleColor, for: .normal)
backgroundColor = color
}
}

Xcode Swift image zoom gesture

Hope someone can help me. Im trying to make a zoom gesture, so when the image are presented the user can zoom the image with fingers.
My code to present the image are:
// MARK: Show image full screen
func imageTapped(img: AnyObject) {
self.navigationController?.navigationBarHidden = true
let imageView = productImage as UIImageView
let newImageView = UIImageView(image: imageView.image)
newImageView.frame = self.view.frame
newImageView.backgroundColor = .blackColor()
newImageView.contentMode = .ScaleToFill
newImageView.userInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: "dismissFullscreenImage:")
newImageView.addGestureRecognizer(tap)
self.view.addSubview(newImageView)
}
func dismissFullscreenImage(sender: UITapGestureRecognizer) {
sender.view?.removeFromSuperview()
self.navigationController?.navigationBarHidden = false
}
Use UIScrollView and add UIImgeView in scroll view
import UIKit
class ViewController: UIViewController,UIScrollViewDelegate
{
var scrollV : UIScrollView!
var imageView : UIImageView!
override func viewDidLoad()
{
super.viewDidLoad()
self.navigationController?.navigationBarHidden = true
scrollV=UIScrollView()
scrollV.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
scrollV.minimumZoomScale=1
scrollV.maximumZoomScale=3
scrollV.bounces=false
scrollV.delegate=self;
self.view.addSubview(scrollV)
imageView=UIImageView()
imageView.image = UIImage(imageLiteral: "neymar.jpg")
imageView.frame = CGRectMake(0, 0, scrollV.frame.width, scrollV.frame.height)
imageView.backgroundColor = .blackColor()
imageView.contentMode = .ScaleToFill
scrollV.addSubview(imageView)
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView?
{
return imageView
}
}
Take gesture programmatically and make its method and write down this code in the method.
pinchRecognizerOnView() is my method name. Take one view or image view inside view controller and add this new view in that.Now apply gesture method on this new view.
func pinchRecognizerOnView(sender: UIPinchGestureRecognizer!) {
sender.view?.transform = CGAffineTransformScale((sender.view?.transform)!, sender.scale, sender.scale)
sender.scale = 1
// its for zoom in out screen
}

Saving text labels on top of images

I'm building an app which takes Strings from the user and saves them using NSUserDefaults. Then I recover them and paste them on top of an image (a form or questionnaire) I'm currently saving the image with .write to file but when I check the image I've saved, I discovered that it doesn't save the full image and as a consequence the positions for the fields aren't right. I need to be able to send this image and later on print on a sheet of A4 paper.
The simulator :
http://postimg.org/image/5szujdgw3/
The saved image:
http://postimg.org/image/uq6mea6vb/
Why isn't it saving the full image?
Here's my code :
import UIKit
class StartMorgagesSave: UIViewController {
let rectangle = UIBezierPath(rect: CGRectMake(80, 166, 80, 05)) //x , y , width , height 240, 165
let shapeLayer = CAShapeLayer()
//let label = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
shapeLayer.path = rectangle.CGPath
shapeLayer.strokeColor = UIColor.blueColor().CGColor
shapeLayer.fillColor = UIColor.whiteColor().CGColor
view.layer.addSublayer(shapeLayer)
view.pdfData.writeToURL(NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!.URLByAppendingPathComponent("test53.pdf"), atomically: true) // what it is saved as
view.pdfData.writeToFile("fdfdlo", atomically: false)
print(NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!.path!)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension UIView {
var pdfData: NSData {
let result = NSMutableData()
UIGraphicsBeginPDFContextToData(result, frame, nil)
guard let context = UIGraphicsGetCurrentContext() else { return result }
UIGraphicsBeginPDFPage()
layer.renderInContext(context)
UIGraphicsEndPDFContext()
return result
}
}
Niall

Resources