NSURL fail able initialiser initWithString: does not return nil on empty String in Swift
After i filled a Radar for this i got the following answer:
Apple Developer Relations
An empty string is a valid URL string. It has no scheme, no authority (user/password/host/port), an empty path, no query and no fragment.
So it seems to be working as expected.
UIDocumentInteractionController nil string parameter
as crash stated, there might be some cases in the logic which are returning nil urlString,
To avoid the crash please add following condition:
if(nil != urlString)
{
NSURL *URL = [[NSURL alloc] initWithString:urlString];
}
or find the root cause which is returning invalid urlString.
Objective-C NSURL With Non-Alphabetical Characters
Problem Description
From the documentation of [NSURL initWithString]
Initializes an NSURL object with a provided URL string.
- (id)initWithString:(NSString *)URLString
Parameters - URLString
The URL string with which to initialize the NSURL object. This URL
string must conform to URL format as described in RFC 2396, and must
not be nil. This method parses URLString according to RFCs 1738 and
1808.Return Value
An NSURL object initialized with URLString. If the URL string was
malformed, returns nil.Discussion
This method expects URLString to contain only characters that are
allowed in a properly formed URL. All other characters must be
properly percent escaped. Any percent-escaped characters are
interpreted using UTF-8 encoding.
Solution
You need to encode the string as url first. One of the solutions for this is to use
[NSString stringByAddingPercentEscapesUsingEncoding:][1]
There are other discussion on Stackoverflow about encoding strings to urls:
- iOS : How to do proper URL encoding?
- How do I URL encode a string
Swift. URL returning nil
Don't force unwrap it with (!). When you use (!) and the value of the variable is nil, your program crashes and you get that error. Instead, you want to safely unwrap the optional with either a "guard let" or an "if let" statement.
guard let name = element.Name as? String else {
print("something went wrong, element.Name can not be cast to String")
return
}
if let url = URL(string: "http://en.wikipedia.org/wiki/\(name)") {
UIApplication.shared.openURL(url)
} else {
print("could not open url, it was nil")
}
If that doesn't do the trick, you may have an issue with element.Name. So I would check to see if that's an optional next if you're still having issues.
Update
I added a possible way to check the element.Name property to see if you can cast it as a String and create the desired url you're looking to create. You can see the code above the code I previously posted.
Method Swizzling with Swift 5.5
That's because
@objc internal func log_initWithString(string URLString: String)
is exposed to Objective-C as log_initWithStringWithString:
and not as log_initWithString:
.
Obvious fix is:
...
let swizzled = Selector("log_initWithStringWithString:")
...
To have better compile time checks on that you can use this syntax:
let original = #selector(NSURL.init(string:))
let swizzled = #selector(NSURL.log_initWithString(string:))
This will compile, but there is at least one thing left to fix - swizzled method return value. In your example:
@objc internal func log_initWithString(string URLString: String) {
NSLog("Hello from initWithString")
return log_initWithString(string: URLString)
}
returns nothing, while NSURL
's init is supposed to return NSURL
, so the fix is:
@objc internal func log_initWithString(string URLString: String) -> NSURL {
...
How can I make a clickable link in an NSAttributedString?
I found this really useful but I needed to do it in quite a few places so I've wrapped my approach up in a simple extension to NSMutableAttributedString
:
Swift 3
extension NSMutableAttributedString {
public func setAsLink(textToFind:String, linkURL:String) -> Bool {
let foundRange = self.mutableString.range(of: textToFind)
if foundRange.location != NSNotFound {
self.addAttribute(.link, value: linkURL, range: foundRange)
return true
}
return false
}
}
Swift 2
import Foundation
extension NSMutableAttributedString {
public func setAsLink(textToFind:String, linkURL:String) -> Bool {
let foundRange = self.mutableString.rangeOfString(textToFind)
if foundRange.location != NSNotFound {
self.addAttribute(NSLinkAttributeName, value: linkURL, range: foundRange)
return true
}
return false
}
}
Example usage:
let attributedString = NSMutableAttributedString(string:"I love stackoverflow!")
let linkWasSet = attributedString.setAsLink("stackoverflow", linkURL: "http://stackoverflow.com")
if linkWasSet {
// adjust more attributedString properties
}
Objective-C
I've just hit a requirement to do the same in a pure Objective-C project, so here's the Objective-C category.
@interface NSMutableAttributedString (SetAsLinkSupport)
- (BOOL)setAsLink:(NSString*)textToFind linkURL:(NSString*)linkURL;
@end
@implementation NSMutableAttributedString (SetAsLinkSupport)
- (BOOL)setAsLink:(NSString*)textToFind linkURL:(NSString*)linkURL {
NSRange foundRange = [self.mutableString rangeOfString:textToFind];
if (foundRange.location != NSNotFound) {
[self addAttribute:NSLinkAttributeName value:linkURL range:foundRange];
return YES;
}
return NO;
}
@end
Example usage:
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:"I love stackoverflow!"];
BOOL linkWasSet = [attributedString setAsLink:@"stackoverflow" linkURL:@"http://stackoverflow.com"];
if (linkWasSet) {
// adjust more attributedString properties
}
Make Sure that the NSTextField's Behavior attribute is set as Selectable.
Related Topics
Requestaccessformediatype Doesn't Ask for Permission
Empty Class in Swift Playground Gives _Lldb_Expr_ Error
Tests for Custom Uitableviewcell, Cellforrowatindexpath Crashes with Nil Outlets
Why Is My Sound Making My Game Lag in Swift Spritekit
Swift: How to Get Information for an Application Which Is Not Running
Update Firebase Multi-Location with Error: Path Is an Ancestor of Path. Swift
Swift: How to Invalidate a Timer If the Timer Starts from a Function
Why Does Function Has Multiple Return Types in Swift
How Assistant Model Works in Swift
How to Create an Operator to Implement Error Chaining
How to Reset a Subview in Swiftui
Swift Accessing Response from Function
Why Does the Completion Handler Does Not Return Anything
Resizing Large Resolution Images Producing 1000X1000 Pixels Size When Size Is Set to 500X500 Pixels
How to Get String from Ascii Code in Swift