How to use headerView completion block using SDWebImage in Swift 4.2? - swift4.2

I'm trying to figure out a way to push images that are loaded via SDWebImage on the headerView, to a view where the image can be viewed in headerView.
I tried this closure method
sd_setImageWithURL(NSURL(string: urlString), completed: {
(image, error, cacheType, url) in
but i am getting this error //Value of type 'UIView?' has no member 'sd_setImage'
//code line where the error happen
self.headerView.sd_setImage(with: URL(string: flowerImageURL), completed: { (image, error, cache, url) in

SDWebImage used to display the image in UIImageView, UIButton, MKAnnotationView and not for UIView. It clearly describe in README.md
https://github.com/SDWebImage/SDWebImage
This library provides an async image downloader with cache support. For convenience, we added categories for UI elements like UIImageView, UIButton, MKAnnotationView.
Categories for UIImageView, UIButton, MKAnnotationView adding web image and cache management
So, you can create imageView inside the headerView and use the "sd_setImage" from that imageview
imageView.sd_setImage(with: URL(string: urlString), placeholderImage: UIImage(named: "placeholder.png"))
Link to: HowToUse

Related

Why doesn't SwiftUI's Kingfisher KFImage.Placeholder(UIImage(named: "logo")) accept UIImage as acceptable?

I add the following code to a VStack in SwiftUI:
KFImage.url(url)
.placeholder(UIImage(named: "logo"))
.setProcessor(processor)
.loadDiskFileSynchronously()
But XCode doesn't like it and says "Cannot convert value of type UIImage? to expected argument type '() -> Content'"
Kingfisher's cheatsheet indicates that the placeholder line should work:
.placeholder(UIImage(named: "logo"))
When I remove the placeholder line (line2 above), it works properly. But, of course, there is no placeholder.
Using SwiftUI, how can I set the placeholder for KFImage?
I've only been coding with Swift/SwiftUI for a month now so I'm quite new.
Thankyou.
Swift Version 5.0
Kingfisher Version 6.1.0
The error that you are getting is telling that placeholder wants a SwiftUI View (eg () -> Content) and you're trying to provide it a UIKit UIImage instead.
Instead, you should give it a SwiftUI Image.
You could easily initialize Image with a UIImage, but keep in mind that UIImage(named:) returns an Optional (which your error hinted at as well), so if you want to use it without checking it for nil first, you'll need to force unwrap it:
Image(uiImage: UIImage(named: "logo")!)
Even better, just initialize your SwiftUI Image with the name and skip UIImage altogether unless you need it for some other reason:
Image("logo")
.placeholder { Image("logo") }

Reuse identifier in nib does not match the identifier used to register the nib

I have a Framework/Module written in Swift which provides some custom controls with IBDesignable functionality.
Currently I am working on a control based on a CollectionView. The CollectionView and the custom CollectionViewCell are build in Nib files. To load the CollectionViewNib and add the Designable funcionality I use this NibDesignable class. After initalising the CollectionView I register the CollectionViewCell as following:
let cellIdentifier = "collectionViewCell"
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}
private func setup() {
let bundle = NSBundle(forClass: self.dynamicType)
self.collectionView.registerNib(UINib(nibName: "CollectionViewCell", bundle: bundle), forCellWithReuseIdentifier: self.cellIdentifier)
}
After adding my Framework as Embedded Binary to another app I can use my new custom CollectionView as expected, but unfortunately the Designable functionality isn´t working well, instead I get the following error message:
IB Designables: Failed to update auto layout status:
The agent raised a "NSInternalInconsistencyException" exception:
view reuse identifier in nib (ibCollectionViewCell) does not match the identifier used to register the nib (collectionViewCell)
As describe above my Control works in the Simulator and on my Phone, so no I don´t use different identifiers. I don´t know where XCode gets this
ibCollectionViewCell identifier, but when I use it as identifier for my CollectionViewCell every thing works like a charm.
Any ideas where this identifier comes from and why XCode can´t load my custom CollectionViewCell with my own identifier?
After updating from XCode 7 Beta 4 to Beta 5 the error was gone. So I assume there was something buggy in the previous version

How to embed a storyboard view controller in an NSScrollView OS X (10.10) to make a complex inspector view?

I'm looking at WWDC 2014 video, "212: Storyboards and controllers on OS X". In this video they claim that Pages UI does/could be arranged using Storyboards on OS X (see below).
However, in Pages UI the inspector view is very long and is embedded in a scroll view (you can verify this my two-finger scrolling in Page.app inspector view), also some inspector items are themselves contained in (some type of custom) disclosure view. It doesn't seem to be possible to embed a storyboard view controller in scroll view because there is no corresponding to "scroll view controller" class. Is that right?
How can a storyboard view controller's view be embedded in a scroll view on a storyboard?
I have tried direct embedding at run time, however, this is very hackish and does't work reliably (problems with auto-layout). This route still might be possible, but I wanted to get advice before going too far. For real UI it might be the case of falling back to XIBs.
- (void)viewDidLoad {
[super viewDidLoad];
// Swap the view controllers' view for a scroll view
NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:self.view.frame];
scrollView.documentView = self.view;
scrollView.drawsBackground = NO;
self.view = scrollView;
}
I think this answer is not really solving your problem but maybe helps understanding what is up with storyboards and scrollviews. I think Apple still has to fix some storyboard issues. I tried to use a collection view with storyboards, but it's impossible to connect the collectionViewItem in interface builder (which is happening automatically with xibs).
Here is an example with collection views:
Drag and Drop the collection view to a viewController. You will see a collection view and a collectionViewItem appearing. But the collection view item is NOT connected to the collection view. If you try this using IB, nothing happens.
In Identity inspector of IB assign a Soryboard ID. It's a random name which will be used in the code later. Here I am using "MyCollectionView"
If using swift, select your projects name in Module. The code is mostly the same for objC
Connect the collection view to the ViewController, containing the collection view
Do some coding to connect the Collection View item
class IVMyCollectionViewController: NSViewController, NSCollectionViewDelegate {
// manual connections to collection view (which is not working in IB)
#IBOutlet weak var collectionView: NSCollectionView!
class var sharedInstance : IVMyCollectionViewController {
struct Static {
static var instance:IVMyCollectionViewController? = nil
}
if Static.instance != nil {
return Static.instance!
} else {
let bundle = NSBundle.mainBundle()
let infoDict = bundle.infoDictionary!
let sbName = infoDict["NSMainStoryboardFile"] as String
let storyboard = NSStoryboard(name:sbName, bundle:bundle)!
let vcName = "MyCollectionView"
let sbInstance = storyboard.instantiateControllerWithIdentifier(vcName) as IVMyCollectionViewController
Static.instance = sbInstance
return sbInstance
}
}
// implement your controller
}
That means that some UI elements are not properly implemented yet. I would send a bug report to apple. There is still lots of things missing in interface builder.
Right now I would use a mixture of storyboard and xibs to abuse the storyboard in a way like above, by instantiating the connection in the constructor of the controller. You can use the storyboardID to launch views and other views or load from xibs. You can place viewControllers inside a storyboard without connections (segues) to create a pool of views that can be used like xibs. (A viewController is more or less the same like a xib)
// objC
DetailViewController* controller = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
or instantiate using the storyboardID like above.
Try to create a scroll view in storyboard. Create the views which you like to be shown in viewControllers for each view. Your scrollviews view controller should have a connection to the scroll view itself. In the following example the scroll view's outlet is named "self.contentView":
// instantiate a view controller for your scrolling view
self.scrollingViewController = [[ScrollingViewController alloc] initWithNibName:#"ScrollingView" bundle:nil];
// or do the same with storyboards by instantiating view controllers by ID
self.scrollingViewController = [myStoryboard instantiateControllerWithIdentifier:#"MyScrollingViewID"];
// Then set the view from the controller as content view
[self.contentView setDocumentView:self.scrollingViewController.view];
[self.contentView.contentView scrollPoint:NSMakePoint(0., self.scrollingViewController.view.frame.size.height)];
It's exactly like mixing up objective C and swift code. Apple seems to have entered a transition path which was not walked to the end.
In general you should think of View- or WindowControllers in storyboards is the same like a complete xib file. If you would like to use more views, use container views in storyboards. The FilesOwner in xibs is the viewController in storyboards. Container views offer you the ability to create a couple of views attached to a view controller. The segue mechanism is available for containers. I think the scroll view mechanism of OS X is not elegant. I struggled a lot with it, too.
Good luck!
Create the view that will be the document view of the scroll view.
Select that view
Go to Editor > Embed In > Scroll View
Based on this page of Scroll View Programming Guide for Mac.

Disable user interaction for NSImageView

I have 2 sets of images. One set contains draggable ones and other is a static set. I have implemented drag-drop functionality for the draggable images. This is because the images needs to be dragged to static ones which contains matches. Now after placing the dragged image on the static one, there is nothing to do with it, hence I want to disable user interaction for image (since it's still draggable).
I have explored several solutions and SO questions here and there , but none of the solutions helped!
Can some one please help me how to remove dragging or user interaction for NSImageView?
Thanks everyone in advance :)
Create custom class of NSImageView and implement mouse entered and mouse exit method with empty definition
The easiest solution in my opinion is subclassing NSView. Your custom view should just contain an image variable you want to draw inside. After that you can use your custom view instead of default NSImageView, it will pass mouse events through.
Example:
class ImageView: NSView {
var image: NSImage?
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
if let image = image {
image.draw(in: bounds)
}
}
}
Be noted that the target image will be scaled non-proportionally to your ImageView instance size.

IKImageBrowserView does not refresh unless user scrolls

We've got an IKImageBrowserView that displays a bunch of images. We asynchronously download those images in the background and cache them to disk. We then notify the IKImageBrowserView that the imageRepresentation has changed using KVC. e.g. didSetValueForKey:#"ImageRepresentation". However, it looks like IKImageBrowserView will only refresh itself to load the recently downloaded images if user scrolls the view (We embedded IKImageBrowserView inside an NSScrollView). Why is this the case? Is there anyway to force IKImageBrowserView to redraw a certain cell or all visible cells without waiting for user to scroll the view?
Try using the reloadData method.
[browser reloadData];
I've got a similar situation in which I am using a IKImageBrowserView to view images that are downloading. In my case, I create the initial set of images with a placeholder image and then download the image. As each comes in, I update the data source entry with a different image, increase the image version number, then use the reloadData method on the browser. I also turn off animations so that the user doesn't see the entire browser redraw, only the images that have been updated.
- (void) setImage: (NSImage *) image
{
[img release];
img = image;
[img retain];
imageVersion++;
}
The above is a setter method for my data item that implements the informal protocol.
https://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/IKImageBrowserItem_Protocol/IKImageBrowserItem_Reference.html

Resources