NSCollectionViewDataSource method return different result in Objc and Swift ?

I have ported to Swift an existing ObjC code.


I have NSCollectionViewDataSource Methods which should be exactly doing the same :


In ObjC

- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath {
    // Message back to the collectionView, asking it to make a @"Slide" item associated with the given item indexPath.  The collectionView will first check whether an NSNib or item Class has been registered with that name (via -registerNib:forItemWithIdentifier: or -registerClass:forItemWithIdentifier:).  Failing that, the collectionView will search for a .nib file named "Slide".  Since our .nib file is named "Slide.nib", no registration is necessary.
    NSCollectionViewItem *item = [collectionView makeItemWithIdentifier:@"Slide" forIndexPath:indexPath];
    AAPLImageFile *imageFile = [self imageFileAtIndexPath:indexPath];
    item.representedObject = imageFile;
    return item;
}


In Swift

    func collectionView(collectionView: NSCollectionView, itemForRepresentedObjectAtIndexPath indexPath: NSIndexPath) -> NSCollectionViewItem {
        //
        let item = collectionView.makeItemWithIdentifier("Slide", forIndexPath: indexPath)
        let imageFile = self.imageFileAtIndexPath(indexPath)
        item.representedObject = imageFile;
        return item;
    }


I set a breakpoint at the return line. In ObjC, the slide.nib is displayed in the view, not in Swift.

I have checked all the nib files to make sure they are exactly identical in Swift and ObjC (notably the connections which define dataSource and delegates)

I do wonder why such a different behavior (in fact, nib never displayed in Swift)


item object appear different in ObjC and Swift. I wonder if it's just a different way to present in ObjC and Swift or a real problem.


ObjC (partial content)


item AAPLSlide * 0x618000120fa0

NSCollectionViewItem

NSViewController

NSResponder

_nibName id 0x0

_nibBundle NSBundle * @"/Users/me/Library/Developer/Xcode/DerivedData/CocoaSlideCollection ewnzbbfwoqqfsjgavhdwzvwhctyx/Build/Products/Debug/CocoaSlideCollection.app" 0x0000600000080af0

_representedObject AAPLImageFile * 0x61800008a230

_title id 0x0

view AAPLSlideCarrierView * 0x618000140f20

// ......

_collectionView NSCollectionView * 0x10050de20

NSView

_content id 0x0

_selectionIndexes NSMutableIndexSet * 0 indexes

_animationDuration double 0.25


_delegate AAPLBrowserWindowController * 0x6100000e0d00 n// in collectionView structure


Swift (partial content)


item NSCollectionViewItem 0x0000600000122300

_TtC20CocoaSlideCollection5Slide CocoaSlideCollection.Slide // aka bridge type ????

NSCollectionViewItem

NSViewController

NSResponder

_nibName NSIndexPath * 0x2000169

_nibBundle NSCollectionView * 0x10080fe80

NSView

_content id 0x0

// ....

_animationDuration double 0.25

_delegate CocoaSlideCollection.BrowserWindowController * 0x608000100120 // in nibBundle, which is also NSCollectionView

NSWindowController

NSResponder

_window NSWindow * 0x6100001e0200

I have tracked in parallel in debugger both Swift and ObjC.


They execute exactly the same code (assembler level) to the point where an object is drawn in the view. But in ObjC, the nib is drawn, nothing in Swift.


I have no more idea now of where to look for !

In my environment, and with my translated version of CocoaSlideCollection sample code, the `item` is an AAPLSlide object instantiated with Slide.xib .

As far as I checked, Slide.xib has two Custom Classes, one for Slide object, another for View. Both pointing to your Swift classes? I'm afraid the View's custom class is not well designated to your AAPLSlideCarrierView class (which you may have renamed).

In my Slide.xib, I have effectively :


a Slide Object, which is a collection view item, of Custom class Slide (type NSCollectionViewItem) ; a Shared User Defaults controller was created with it;

Could it be a problem to have the object and class share the same name ("Slide"), which is not the case in ObjC because the classes are prefixed by AAPL


a View, of custom class SlideCarrierView (type NSView)


So, they point to 2 classes by the definition of their Custom Class.


The file owner's has custom type (shows NSObject grayed) ; I have just corrected, as I had defined it by mistake as of custom class Slide as well


The item is created with

item = collectionView.makeItemWithIdentifier("Slide", forIndexPath: indexPath)

So, item is instanciated by Slide.xib ; how can it infer to be of type Slide (AAPLSLide) ?


In fact, I have recreated the Slide object, because it was of the wrong type (pure object, not Collection View Item, and User Defautl Controller was not "shared". I recreated the connections and did a cleaning ; but it still does not work.


When you say : I'm afraid the View's custom class is not well designated to your AAPLSlideCarrierView class

Do you mean that the Custom Class of View could be wrong or do you hint at sthing else ?

I tried to force the type of item to Slide:


let item = collectionView.makeItemWithIdentifier("Slide", forIndexPath: indexPath) as! Slide


It compiles, but crashes at run.


libsystem_kernel.dylib`mach_msg_trap:

0x7fff8ac4d37c <+0>: movq %rcx, %r10

0x7fff8ac4d37f <+3>: movl $0x100001f, %eax

0x7fff8ac4d384 <+8>: syscall

-> 0x7fff8ac4d386 <+10>: retq

0x7fff8ac4d387 <+11>: nop

I tried to rename SLide.xib as Slide2.xib and changed the collectionView.makeItemWithIdentifier


        let item = collectionView.makeItemWithIdentifier("Slide2", forIndexPath: indexPath)


No result

Seen under debugger :


in ObjC, item is directly a AAPLSlide Object.

item AAPLSlide * 0x618000120c80

NSCollectionViewItem

_kindTextField NSTextField * 0x6180001e1d00

_dimensionsTextField NSTextField * 0x6180001e1e00


In Swift, debugger shows :

item = NSCollectionViewItem 0x0000608000120960
     _TtC20CocoaSlideCollection5Slide(CocoaSlideCollection.Slide)
     NSCollectionViewItem
          NSViewController
          _collectionView = CocoaSlideCollection.BrowserWindowController * 0x608000101e60
          _cachedArchive = id 0x7fff83409aba
          _reserved2 = id 0x0
....


I do not understand what _TtC20CocoaSlideCollection5Slide means

I do not understand what _TtC20CocoaSlideCollection5Slide means

That is included in the output. `_TtC20CocoaSlideCollection5Slide` is just a linker name of CocoaSlideCollection.Slide .


By the way, aren't getting runtime warnings such as:

2016-01-07 07:24:40.528 CocoaSlideCollection[97293:7227577] Unknown class 'SlideCarrierView', using 'NSView' instead. Encountered in Interface Builder file at path /Users/dev/Library/Developer/Xcode/DerivedData/CocoaSlideCollection-drehyxipgvowzwbrysvohevpnejo/Build/Products/Debug/CocoaSlideCollection.app/Contents/Resources/English.lproj/Slide.nib.

No, I do not get this type of warning.


What is surprising is that the objects are partially displayed (title, size, kind) and even the image when I scroll the window. But never the slide "frame"


Would it be possible to post somewhere the complete project, just to be able to see what output I get ? I can send my email address.

To be sure, I deleted derived data and did a clean and ran again.No change.

What is surprising is that the objects are partially displayed (title, size, kind) and even the image when I scroll the window. But never the slide "frame"

The behaviour is nealy the same as what happens if I change the Custom Class settings of the View in Slider.xib (except that you cannot get runtime warnings.)

And it's not astonishing because NSView can have any sort of subview hierarchy, and `title`, `size` and `kind` are all declared as subviews in the Slide.xib, so nib loader can put them in a simple NSView.

And `image` is also declared in the nib file, but if it can be updated before scrolling or not depends on wheather you implemented KVO properties well or not.


You should better re-check (or triple or more) your Slide.xib's settings, especially around Custom Class settings of the View and the class header including @objc name of your class.


In my translated version, the Custom Class settings:

Class: AAPLSlideCarrierView

Module: None

and the class header of AAPLSlideCarrierView is:

@objc(AAPLSlideCarrierView)
class AAPLSlideCarrierView: NSView {

so, they match.

I did a comparison of the xib XML in Swift and ObjC.


What I noticed is that the custom class of the view, of the image and of the slide object in slide.xib both have also a custom module (greyed, I cannot modify)


  <customView id="Hz6-mo-xeY" userLabel="View" customClass="SlideCarrierView" customModule="CocoaSlideCollection" customModuleProvider="target">
  <imageView alphaValue="0.80000000000000004" translatesAutoresizingMaskIntoConstraints="NO" id="aTj-La-V3T" customClass="SlideImageView" customModule="CocoaSlideCollection" customModuleProvider="target">
  <collectionViewItem nibName="" identifier="slide" id="tkL-bc-9B8" customClass="Slide" customModule="CocoaSlideCollection" customModuleProvider="target">


In ObjC, it is none.


  <customView id="5" userLabel="View" customClass="AAPLSlideCarrierView">
  <imageView alphaValue="0.80000000000000004" translatesAutoresizingMaskIntoConstraints="NO" id="6" customClass="AAPLSlideImageView">  
  <collectionViewItem identifier="slide" id="RJz-wL-WeE" customClass="AAPLSlide">


Could I force it by changing the XML file directly (I fear to create side effects) ?


I remember I did change the name of the target, so that I could get the name CocoaSlideCollection in the menu bar. Did I messed something when doing so ? Where could I change it back ?

I tried a manual change (deleting customModule="CocoaSlideCollection" customModuleProvider="target").


I did not work, it is even worse, no more image display after scrolling.


So I guess, I need to work directly at the target definition, but where and how exactly ?

I tried the change @objc(SlideCarrierView)

class SlideCarrierView: NSView {


Does not change ; but when I scroll, it crashes with the following message :


2016-01-07 13:27:53.343 CocoaSlideCollection[3356:1672754] Unknown class '_TtC20CocoaSlideCollection16SlideCarrierView', using 'NSView' instead. Encountered in Interface Builder file at path /Users/claudericaud/Library/Developer/Xcode/DerivedData/Lesson42CocoaSlideCollection-clxfhuynficmqjfxtyqzbunmpfgv/Build/Products/Debug/CocoaSlideCollection.app/Contents/Resources/Slide.nib.

2016-01-07 13:27:53.384 CocoaSlideCollection[3356:1672754] Unknown class '_TtC20CocoaSlideCollection16SlideCarrierView', using 'NSView' instead. Encountered in Interface Builder file at path /Users/claudericaud/Library/Developer/Xcode/DerivedData/Lesson42CocoaSlideCollection-clxfhuynficmqjfxtyqzbunmpfgv/Build/Products/Debug/CocoaSlideCollection.app/Contents/Resources/Slide.nib.

BTW, why does it reference .nib and not .xib ? Is it because from time to time I modified the name of the file as slide.nib to see it in XML ? Or just the way to reference in ObjC ?

BTW, why does it reference .nib and not .xib ? Is it because from time to time I modified the name of the file as slide.nib to see it in XML ? Or just the way to reference in ObjC ?

The .xib files are compiles into .nib files, which are more effective using binary representation.


You need to match the class reference in .xib and the actually existing class.


I changed the Custom Class settings in the Identity Inpector like this: (-- this crashed Xcode, but thats another issue...)

Class: SlideCarrierView

Module: Current - CocoaSlideCollection


It's XML representation has become:

        <customView id="5" userLabel="View" customClass="SlideCarrierView" customModule="CocoaSlideCollection" customModuleProvider="target">

As you have experienced, it doesn't work.


So, I changed the class header like this:

//@objc(AAPLSlideCarrierView)
class SlideCarrierView: NSView {

Remember I removed the @objc annotation, so its dynamic name has become "CocoaSliderCollection.SliderCarrierView", which matches the class reference in the .xib , and then, of course, the app worked again as expected.

That was the original format of my class definition.


What about the custom module ?


I will try to rebuild completely the Slide class and its xib.

NSCollectionViewDataSource method return different result in Objc and Swift ?
 
 
Q