I'm trying to add a TextEditor to my project with a different background color. I'd like to just use the simple extension that's found in this post: Transparent Background for TextEditor in SwiftUI
The problem is this--when I paste it in, I get the following errors as seen below:
extension NSTextView { // Cannot find type 'NSTextView' in scope.
open override var frame: CGRect {
didSet {
backgroundColor = .clear // Cannot find 'backgroundColor' in scope.
drawsBackground = true // Cannot find 'drawsBackground' in scope.
}
}
}
I assumed NSTextView was a built-in Swift type because there's documentation here (https://developer.apple.com/documentation/appkit/nstextview). I'm importing SwiftUI and Foundation at the top of the file. I'm trying to compile on an iPhone target set to iOS 14.4 so this shouldd definitely be working, right? What am I missing?
Related
Current Situtation
I work on an iOS SDK containing several UIViewControllers that can be customized through a delegate function passing a String as the identifier and getting a customized CALayer. With that, the host application can customize how the SDK looks.
This is an example:
extension ViewController: NINChatSessionDelegate {
func ninchat(_ session: NINChatSession, overrideLayer assetKey: CALayerConstant) -> CALayer? {
switch assetKey {
case .ninchatPrimaryButton:
let layer = CALayer()
layer.backgroundColor = UIColor.gray.cgColor
layer.masksToBounds = true
layer.cornerRadius = 20.0
return layer
default:
return nil
}
}
Problem
Nowadays, I'm trying to migrate the code to SwiftUI and Combine. But I cannot find a way to offer host applications to inject their own attributes. As far as I have understood, a ViewModifier struct is used to apply custom attributes to one or multiple View(s) in SwiftUI. However, I could not yet find a way to inject them to the SDK because a ViewModifier protocol has Self or associated type requirements
I appreciate any helps and guides.
I can't seem to figure out how to programmatically animate UIImages.
I've seen a code written in Objective-C, but looking for a solution in Swift.
The closest code I can find is:
imageView.startAnimatingWithImages(in: ???[NSRange] , duration: 1, repeatCount: 100)
but I'm not sure what to put in NSRange. Images is stored in my asset folder in a folder:
enter image description here
Code in swift(but not for Apple Watch): How to animate images in Swift?
Objective- C code: Programatically Set UIImage Animation with WatchKit
Found a swift solution: quiet simple, I just needed to add an image outlet and write the following two code items:
class InterfaceController: WKInterfaceController {
#IBOutlet weak var imageObject: WKInterfaceImage!
override func awake(withContext context: Any?) {
super.awake(withContext: context)
imageObject.setImageNamed("plank")
imageObject.startAnimating()
// Configure interface objects here.
}
}
tl;dr
Applying a code change to a commonly used struct causes very slow build times. Can this be avoided?
I have a rather large Swift project (Xcode 9.2) where I use a struct to hold all styling information (colors, spacings, etc.) used by in the app, something like:
struct Style {
var iconColor: UIColor = .darkGray
var lightTextColor: UIColor = .gray
// ... and many more properties ...
static var defaultStyle: Style {
return Style()
}
static var fancyStyle: Style {
var style = Style()
// ... override style props for more fancyness ...
return style
}
}
Every view controller (there are about 30 VCs in the project, all created in code -- no storyboards used) has a Style instance and uses it when rendering its UI:
class MyViewController: UIViewController {
var style = Style.defaultStyle // can be overridden by creator of the VC
override func viewDidLoad() {
super.viewDidLoad()
myLabel.textColor = style.lightTextColor
}
}
This works pretty nicely and allows to change settings in one place only, without polluting the namespace with global constants.
However, I noticed that when changing a property's default value inside the struct the compile time rises dramatically, Xcode basically performs a full rebuild. E.g. changing the above definition of Style.lightTextColor to var lightTextColor: UIColor = .green leads to a build time comparable to a full rebuild of the project. If, however, I change the value directly where it is used; e.g. in the view controller: myLabel.textColor = .green, the project builds very quickly.
Is there a solution for this, preferably by configuring the compiler to do ... less work in this case?
I use UIColor.named("myColor") throughout my app since Xcode 9 came out. While having a shot at a custom implementation of UITextField as an IBDesignable class, I kept getting the following error:
error: IB Designables: Failed to render and update auto layout status
for ViewController (): The agent crashed
Furthermore, my class has several IBInspectable properties, including of type UIColor, but in the Interface Builder dropdown for these properties I could only select the standard colors, my named colors would not show up as they do for standard class properties.
With that latter issue as a clue for the first one, the unsatisfactory and temporary solution has been to not use named colors in my IBDesignable class. Or alternatively, not use IBDesignable.
This is probably a bug, but I'm wondering if other people out there have experienced this issue, and if there are any fixes they've come up with.
[As of Xcode 9.2] This is an unfortunate workaround, but for now I'm using IB-specific stand-in colors. It's not perfect, but we can at least see something while designing in Interface Builder.
#IBDesignable
class MyView: UIView {
#IBInspectable
var addCoolSubview: Bool = false {
didSet {
if self.addCoolSubview {
let coolView = CoolView() // Some custom view with a `coolColor` property.
#if TARGET_INTERFACE_BUILDER
coolView.coolColor = UIColor.blue // An IB-only stand-in color.
#else
coolView.coolColor = UIColor(named: "myCoolBlue") // The run-time color we really want.
#endif
self.addSubview(coolView)
}
}
}
}
Every UIView also has a prepareForInterfaceBuilder() method, which runs only when building for Interface Builder, that could be overridden to similar effect.
#IBDesignable
class MyOtherView: UIView {
var myWarmColor: UIColor? = UIColor(named: "myWarmColor") // Will be `nil` in IB.
// ... view does something with `myWarmColor` that would be visible in IB ...
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
// Set some IB-only stand-in colors here:
self.myWarmColor = UIColor.orange
}
}
With regard to choosing named colors in #IBInspectable properties in Interface Builder, it's only half-broken. As a workaround, you can choose a named color from the Recently Used Colors section, if you can pick it out of the group by sight. When you pick a named color, it will properly display the name, but append (missing) for whatever reason. Just ignore the (missing); it will display properly in IB and at run-time.
One other point of note is that Xcode (as of 9.2) might try to add the named color again to your Storyboard file, so you'll have to check the XML to see if the color is defined there multiple times (color definitions are near the bottom). Or you could just roll with, and eventually Xcode will notice and fix it by itself, blaming the duplicate color definition on SCM.
You just have to specify the bundle.
UIColor(named: "myColor", in: Bundle(for: AppDelegate.self), compatibleWith: nil)!
I found it in another question and works for me on XCode 14.2.
i am trying to implement an iMessage style keyboard input with a textview that sits at the bottom of the screen then slides up with the keyboard when you touch the textView, then is docked to the top of the keyboard.
I found MessageComposerView which is exactly what I want. Unfortunately I cannot get it working ( I am using swift).
below is my code:
import UIKit
class CommentsViewController: UIViewController, MessageComposerViewDelegate {
var messageComposerView: MessageComposerView!
override func viewDidLoad() {
super.viewDidLoad()
let defaultWidth = view.frame.size.width
let defaultHeight = CGFloat(54.0)
let subviewFrame = CGRect(x: 0, y: view.frame.height - defaultHeight, width: defaultWidth, height: defaultHeight)
messageComposerView = MessageComposerView(frame: subviewFrame) as MessageComposerView
view.addSubview(messageComposerView)
}
func messageComposerSendMessageClickedWithMessage(message: String!) {
}
}
however it does not show up. Ive printed the view and its frame is correct, its just that there is nothing there for some reason. Everything looks like it should be working. Does anyone see anything wrong with my current implementation?
Try PHFComposeBarView Library (https://github.com/fphilipe/PHFComposeBarView), it's a exact copy of the iMessage composer bar that can be used in C & Swift from storyboard or code
Code Example : https://github.com/liveminds/SwiftPHFComposeBarTest
Storyboard Example : https://github.com/liveminds/SwiftPHFComposeBarTest/tree/storyboard-managed
To add the bar to your view:
drag a new UIView on your UIViewcontroller, assign "PHFComposeBarView" class to UIView
Add an outlet of the UIView to your Viewcontroller's class
add "PHFComposeBarViewDelegate" to your Viewcontroller's class
assign UIView Delegate in viewdidload() : self.composerBarOutlet.delegate = self
Set the composer bar to appear as inputAccessoryView above the keyboard:
override var inputAccessoryView: UIView {
composerBar.removeFromSuperview()
return composerBar
}
Style your Bar(example):
composerBar.utilityButtonImage = UIImage(named: "fullStar")!
composerBar.buttonTitle = "Submit"
composerBar.maxCharCount = 200
composerBar.maxLinesCount = 5
composerBar.alpha = 1.0
composerBar.buttonTintColor = AppConfig.BLUECOLOR
composerBar.placeholder = "What do you think about this product?"
Try following this example by Andrew Bancroft Send Text Message In-App – Using MFMessageComposeViewController with Swift. His example provides a nice walkthrough using Swift and includes sample code on GitHub.
Just going from the code snippet included in your post, it looks like you need to import Foundation, import MessageUI, conform to the MFMessageComposeViewControllerDelegate protocol, and implement the messageComposeViewController protocol method. All of this is covered in Andrew's blog post. This should give you what you're looking for.
Have you find the answer yet?
I use the same Framework however I believe you need to set up the delegate to self. IN my case it fails though I dont know why but it is written down in the readme github.