Slide 1

Slide 1 text

題: 発表者: 場所: 日付: (/6TUFQͱ$PDPUSPO KQ NBD04OBUJWF4ZNQPTJVN

Slide 2

Slide 2 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp ࣗݾ঺հ KQ ͸ NBD04 ΞϓϦέʔγϣϯઐ໳ͷϗϏʔ։ൃऀɻ 044 ϓϩδΣΫτӡӦ͔ΒϓϩάϥϛϯάɺΞΠίϯͷσ βΠϯ·ͰɺNBD04 ͷΞϓϦέʔγϣϯ։ൃʹؔΘΔ͜ ͱͳΒશ෦΍ΔϚϯͰ͋Δɻ ͤΜʹ͡Ύ͏ΑΜ
 ͐͡ʔͽʔ 本業ではないよ try! Swift 2019 で初日に話しました。 10:00-10:25ʮnative macOS applicationɺ·ͨ͸AppKitͷੈքʯ

Slide 3

Slide 3 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp USZ4XJGU5PLZP cf. https://speakerdeck.com/1024jp/native-macos-application-or-the-world-of-appkit VKVNG RTGUGPVGT RNCEG FCVG Native macOS application, or the world of AppKit try! Swift 2019 2019-03-21 1024jp ʢnative macOS applicationɺ·ͨ͸AppKitͷੈքʣ

Slide 4

Slide 4 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp ࣗݾ঺հ CotEditor Gapplin BathyScaphe Qli application work plain-text editor SVG viewer 5ch browser movie player 2014年に
 正式引き継ぎ サポーtメンバー
 (主にデザイン・UI) 新作

Slide 5

Slide 5 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp 今日の主役 GNUstep Cocotron

Slide 6

Slide 6 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp ࠓ೔ͷτϐοΫ ѻ͏࿩ – macOS ͷྺ࢙ – GNUstep ͱ Cocotron ͱ͸ – GNUstep/Cocotron ͷ׆༻ ѻΘͳ͍࿩ – macOS ΞϓϦέʔγϣϯͷ࡞๏ – Human Interface Guidelines

Slide 7

Slide 7 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp .BD04NBD04ͷྺ࢙ NeXTSTEP Mac OS X Ϋϩʔϯ Windows, Unix-like, etc macOS OS X Cocoa (Foundation+AppKit) Mac OS 1989-1997 1984-1999 2001-present 2006-2015? 1994 1994-present ΧʔωϧΛআ͘
 ্ҐϨΠϠʔͷΦʔϓϯԽ OSͷϕʔεͱͯ͠࠾༻ OSͷ࡮৽ Ϋϩʔϯ MacApp OPENSTEP GNUstep Cocotron (classic) NeXTSTEP Solaris, HP-UX, 
 Windows NT ( ) Rhapsody

Slide 8

Slide 8 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp ֤ϑϨʔϜϫʔΫͷൺֱ Apple Inc. NeXT, Inc. NeXT, Inc.,
 Sun Microsystems The GNUstep Project MacApp Cocoa NeXTSTEP OPENSTEP
 (OpenStep) GNUstep Cocotron platform Mac OS macOS
 (Mac OS X) NeXTStep Solaris, Windows NT, Unix-likes Windows, Unix-likes, etc. Windows 2000, XP, Vista,
 Linux, Darwin, Solaris framework – Foundation,
 AppKit,
 CoreData – Foundation Kit,
 Application Kit,
 PostScript Base Library,
 GUI Library Foundation,
 AppKit* language Pascal 
 → C++ Objective-C
 → Swift Objective-C Objective-C Objective-C Objective-C development closed closed closed closed OSS
 github.com/ gnustep OSS
 github.com/ cjwl/cocotron year 1984-1999 2001-present 1989-1997 1994 1994-present 2006-2015? *AppKit͸WindowsͷΈ

Slide 9

Slide 9 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp (/6TUFQWT$PDPUSPO GNUstep Cocotron – OPENSTEP Ϋϩʔϯ – ઌൃ (1994-) – υΩϡϝϯτ๛෋ – ։ൃܧଓ – Cocoa Ϋϩʔϯ – ޙൃ (2006-) – ࠷৽ʢ౰࣌ʣͷCocoaΛ࠶࣮૷͠ɺ
 WindowsͰͷಈ࡞Λॏࢹ – υΩϡϝϯτগ – ։ൃఀ଺

Slide 10

Slide 10 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp 01&/45&1 cite: “Today in Apple history: NeXT customers get early taste of OS X”, Cult of Mac, 2017-09
 https://www.cultofmac.com/503084/today-apple-history-next-customers-get-early-taste-os-x/ NeXTSTEP

Slide 11

Slide 11 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp 01&/45&14QFDJpDBUJPO OPENSTEP SPECIFICATION October 19, 1994 ™ Figure 1. Major Components of OpenStep Application Application Kit Foundation Kit Display PostScript System Device-Dependent Windowing Extensions Operating System OpenStep – OPENSTEPͷެ։࢓༷ॻ – ܭ518ท Copyright © 1994 NeXT Computer, Inc. GNUstepの素

Slide 12

Slide 12 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp 0QFO4UFQ4QFDJpDBUJPOr/47JFX OpenStep Specification—10/19/94 1-218 Chapter 1: Application Kit NSView Inherits From: NSResponder : NSObject Conforms To: NSCoding (NSResponder) NSObject (NSObject) Declared In: AppKit/NSView.h AppKit/NSClipView.h Class Description NSView is an abstract class that provides its subclasses with a structure for drawing and for handling events. Any application that needs to display, print, or receive events must use NSView objects. To be displayed, a view must be placed in a window (represented by an NSWindow object). All the views within a window are arranged in a hierarchy, with each view having a single superview and zero or more subviews. Each view has its own area to draw in and its own coordinate system, expressed as a transformation of its superview’s coordinate system. An NSView object can scale, translate, or rotate its coordinates, or flip the polarity of its y-axis. An NSView keeps track of its size and location in two ways: as a frame rectangle (expressed in its superview’s coordinate system) and as a bounds rectangle (expressed in its own coordinate system). Both are represented by NSRect structures. Subclasses of NSView typically override drawRect: to implement an object’s distinctive appearance. They also frequently override one or more of NSView’s or NSResponder’s event-handling methods, to react to the user’s manipulations of the mouse and keyboard. Initializing NSView Objects – (id)initWithFrame:(NSRect)frameRect Initializes a new NSView object to the location and dimensions of frameRect. Managing the NSView Hierarchy – (void)addSubview:(NSView *)aView Makes aView a subview of the receiving view object. – (void)addSubview:(NSView *)aView Makes aView a subview of the receiving view object. positioned:(NSWindowOrderingMode)place It is positioned relative to otherView according to relativeTo:(NSView *)otherView place. OpenStep Specification—10/19/94 1-220 Chapter 1: Application Kit – (void)setFrameRotation:(float)angle Rotates the view’s frame to angle. This method posts the NSViewFocusChangedNotification notification with the receiving object to the default notification center. – (void)setFrameSize:(NSSize)newSize Resizes the view’s frame to newSize. This method posts the NSViewFrameChangedNotification and NSViewFocusChangedNotification notifications with the receiving object to the default notification center. Modifying the Coordinate System – (float)boundsRotation Returns the rotation of the view’s coordinate system. – (NSRect)bounds Gets the view’s bounds rectangle. – (BOOL)isFlipped Returns whether the view is flipped. – (BOOL)isRotatedFromBase Returns whether the view is rotated. – (BOOL)isRotatedOrScaledFromBase Returns whether the view is rotated or scaled. – (void)scaleUnitSquareToSize:(NSSize)newSize Scales the NSView’s coordinate system unit size to newSize. This method posts the notification NSViewFocusChangedNotification with the receiving object to the default notification center. – (void)setBounds:(NSRect)aRect Sets the NSView’s bounds rectangle to aRect. – (void)setBoundsOrigin:(NSPoint)newOrigin Sets the NSView’s drawing origin to newOrigin. This method posts the NSViewFocusChangedNotification notification with the receiving object to the default notification center. – (void)setBoundsRotation:(float)angle Rotates the NSView’s coordinate system to angle. This method posts the NSViewFocusChangedNotification notification with the receiving object to the default notification center. – (void)setBoundsSize:(NSSize)newSize Resizes the NSView’s coordinate system to newSize. This method posts the NSViewFocusChangedNotification notification with the receiving object to the default notification center. – (void)translateOriginToPoint:(NSPoint)point Shifts the NSView’s coordinate system to point. This method posts the NSViewFocusChangedNotification notification with the receiving object to the default notification center.

Slide 13

Slide 13 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp %FWFMPQFS%PDVNFOUBUJPO http://www.gnustep.org/developers/documentation.html

Slide 14

Slide 14 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp 'PVOEBUJPO,JU 0QFO4UFQ NSAssertionHandler NSObject NSAutoreleasePool NSArray NSBTreeBlock NSBundle NSByteStore NSCharacterSet NSCoder NSConditionLock NSConnection NSData NSDate NSDeserializer NSDictionary NSEnumerator NSException NSInvocation NSLock NSMethodSignature NSNotification NSNotificationCenter NSNotificationQueue NSMutableArray NSCalendarDate NSProxy NSDistantObject NSArchiver NSUnarchiver NSByteStoreFile NSMutableCharacterSet NSMutableData NSMutableDictionary NSProcessInfo NSRecursiveLock NSRunLoop NSScanner NSSerializer NSSet NSString NSThread NSTimeZone NSTimer NSUserDefaults NSValue NSMutableString NSMutableSet NSCountedSet NSTimeZoneDetail NSNumber

Slide 15

Slide 15 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp 'PVOEBUJPO,JU (/6TUFQ௥Ճ෼ NSAttributedString NSAffineTransform NSClassDescription NSCondition NSDateFormatter NSDecimalNumber NSDecimalNumberHandler NSDirectoryEnumerator NSDistributedLock NSDistributedNotificationCenter NSError NSException NSFileHandler NSFileManager NSFormatter NSHashTable NSIndexSet NSInputStream NSIndexPath NSKeyedArchiver NSKeyedUnarchiver NSMapTable NSMutableAttributedString NSMutableIndexSet NSNull NSNumberFormatter NSOutputStream NSPipe NSPointerArray NSPointerFunctions NSPropertyListSerialization NSStream NSTask NSUndoManager NSValueTransformer NSConstantString

Slide 16

Slide 16 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp 'PVOEBUJPO,JU (/6TUFQ௥Ճ෼ NSCachedURLResponse NSHTTPCookie NSHTTPCookieStorage NSHTTPURLResponse NSHost NSMessagePort NSMessagePortNameServer NSMutableURLRequest NSNetService NSNetServiceBrowser NSPort NSPortCoder NSPortMessage NSPortNameServer NSURL NSURLAuthenticationChallenge NSURLCache NSURLConnection NSURLCredential NSURLDownload NSURLProtectionSpace NSURLProtocol NSURLRequest NSURLResponce NSXMLDTD NSXMLDTDNode NSXMLDocument NSXMLElement NSXMLNode NSXMLParser NSSocketPort NSSocketPortNameServer NSProtocolChecker

Slide 17

Slide 17 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp "QQMJDBUJPO,JU 0QFO4UFQ NSColorList NSObject NSColor NSCell NSColorPicker NSCursor NSDataLink NSDataLinkManager NSEvent NSFont NSFontManager NSImage NSImageRep NSPasteboard NSPrintInfo NSPrintOperation NSPrinter NSResponder NSScreen NSSelection NSSpellChecker NSSpellServer NSWorkspace NSActionCell NSBrowserCell NSBitmapImageRep NSEPSImageRep NSCachedImageRep NSCustomImageRep NSWindow NSApplication NSView NSButtonCell NSFormCell NSSliderCell NSTextFieldCell NSMenuCell NSPanel NSText NSCStringText NSSplitView NSScrollView NSControl NSBox NSClipView NSColorPanel NSDataLinkPanel NSFontPanel NSHelpPanel NSMenu NSPageLayout NSPrintPanel NSSavePanel NSOpenPanel NSTextField NSBrowser NSButton NSColorWell NSMatrix NSScroller NSSlider NSPopUpButton NSForm

Slide 18

Slide 18 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp "QQMJDBUJPO,JU (/6TUFQ௥Ճ෼ NSDocument NSBezierPath NSComboBox NSComboBoxCell NSDocumentController NSDrawer NSDrawerDelegate NSFileWrapper NSGraphicsContext NSHelpManager NSImageCell NSImageView NSInputManager NSInputServer NSLayoutManager NSMenuItem NSMenuItemCell NSMenuView NSNib NSOpenGLContext NSOpenGLPixelFormat NSOpenGLView NSOutlineView NSProgressIndicator NSRulerMarker NSRulerView NSSecureTextField NSSecureTextFieldCell NSSound NSStepper NSStepperCell NSTabView NSTabViewItem NSTableColumn NSTableHeaderCell NSTableHeaderView NSTextContainer NSTableView NSTextView NSToolbar NSToolbarItem NSWindowController

Slide 19

Slide 19 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp (/6TUFQ$PDPUSPOͷ࢖͍ํ GNUstep/CocotronΛ࢖ͬͯ
 ଞϓϥοτϑΥʔϜ޲͚CocoaΞϓϦέʔγϣϯΛ࡞Ζ͏ʂ Foundation/AppKitͷίʔυϨϕϧ࣮૷͕ಡΊΔ

Slide 20

Slide 20 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp $PDPBͱ(/6TUFQͷࠩҟ ͋͘·Ͱ࢓༷ॻϕʔεͷ࠶࣮૷Ͱ͋ΓɺຊՈͱίʔυϨϕϧͰಉ͜͡ͱ͸
 ظ଴Ͱ͖ͳ͍ Մೳੑ – ࢓༷ॻ → GNUstepͷ࣮૷͕ޡ͍ͬͯͨ – ࣮૷͸߹͍͕ͬͯͨɺͦͷޙCocoaͷ࢓༷͕มߋ͞Εͨ – GNUstep͕࣮૷ΛఘΊͯΔ – GNUstepͷػೳ௥ՃͨΊʹOPENSTEP/Cocoaͷ࢓༷͔Βဃ཭ͨ͠ あるかな?

Slide 21

Slide 21 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp (/6TUFQ$PDPUSPOͷ׆༻ ドキュメントとAppleの実装の差異に関して
 メモが残ってたりする。 NSTextView_actions.m /* TODO: find out what affinity is supposed to mean My current assumption: Affinity deals with which direction we are selecting in, ie. which end of the selected range is the moving end, and which is the anchor. NSSelectionAffinityUpstream means that the minimum index of the selected range is moving (ie. _selected_range.location). NSSelectionAffinityDownstream means that the maximum index of the selected range is moving (ie. _selected_range.location+_selected_range.length). Thus, when moving and selecting, we use the affinity to find out which end of the selected range to move, and after moving, we compare the character index we moved to with the anchor and set the range and affinity. The affinity is important when making keyboard selection have sensible behavior. Example: If, in the string "abcd", the insertion point is between the "c" and the "d" (selected range is (3,0)), and the user hits shift-left twice, we select the "c" and "b" (1,2) and set the affinity to NSSelectionAffinityUpstream. If the user hits shift-right, only the "c" will be selected (2,1). If the insertion point is between the "a" and the "b" (1,0) and the user hits shift-right twice, we again select the "b" and "c" (1,2), but the affinity is NSSelectionAffinityDownstream. If the user hits shift-right, the "d" is added to the selection (1,3). */ - (unsigned int) _movementOrigin { NSRange range = [self selectedRange];

Slide 22

Slide 22 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp (/6TUFQ׆༻ྫ layoutManager.removeTemporaryAttribute(.foregroundColor, forCharacterRange: wholeRange) for (range, color) in highlights { layoutManager.addTemporaryAttribute(.foregroundColor, value: color, forCharacterRange: range) } Swift めちゃ時間かかる... γϯλοΫεϋΠϥΠτͰϝΠϯεϨουͰ΍Βͳ͍ͱ͍͚ͳ͍࡞ۀ Reference NSLayoutManager.addTemporaryAttributes(_:forCharacterRange:) Discussion Temporary attributes are used only for onscreen drawing and are not persistent in any way. NSTextView uses them to color misspelled words when continuous spell checking is enabled. Currently the only temporary attributes recognized are those that do not affect layout (colors, underlines, and so on). ಺෦తͳattributeσʔλΛมߋ͢Δ͚ͩͰԿ΋͠ͳ͍ͷͰ͸…?

Slide 23

Slide 23 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp (/6TUFQ׆༻ྫ @implementation NSLayoutManager - (void) addTemporaryAttribute: (NSString *)attr value: (id)value forCharacterRange: (NSRange)range { [[self _temporaryAttributes] addAttribute: attr value: value range: range]; [self invalidateDisplayForCharacterRange: range]; } @end ObjC layoutManager.removeTemporaryAttribute(.foregroundColor, forCharacterRange: wholeRange) for (range, color) in highlights { layoutManager.addTemporaryAttribute(.foregroundColor, value: color, forCharacterRange: range) } Swift γϯλοΫεϋΠϥΠτͰϝΠϯεϨουͰ΍Βͳ͍ͱ͍͚ͳ͍࡞ۀ GNUstepͰͷ࣮૷ お前...!! めちゃ時間かかる...

Slide 24

Slide 24 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp (/6TUFQ׆༻ྫ class LayoutManager: NSLayoutManager { var ignoresDisplayValidation = false override func invalidateDisplay(forCharacterRange charRange: NSRange) { if self.ignoresDisplayValidation { return } super.invalidateDisplay(forCharacterRange: charRange) } } layoutManager.ignoresDisplayValidation = true layoutManager.removeTemporaryAttribute(.foregroundColor, 
 forCharacterRange: wholeRange) for (range, color) in highlights { layoutManager.addTemporaryAttribute(.foregroundColor, value: color, forCharacterRange: range) } layoutManager.ignoresDisplayValidation = false layoutManager.invalidateDisplay(forCharacterRange: wholeRange) Swift

Slide 25

Slide 25 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp ݁Ռ

Slide 26

Slide 26 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp (/6TUFQ׆༻ྫ ૒ํ޲ςΩετ (bidi-text) ͰͷΧʔιϧͷಈ͖Λ஌Γ͍ͨ Loem ispum dolor sit amet, consectetur adipiscing … ૒ํ޲ͷ઀఺ͰͷંΓฦ͠

Slide 27

Slide 27 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp ·ͱΊ – Cocoa͸NeXT༝དྷͰ͋Δ – Foundation+AppKitΫϩʔϯͷGNUstep / Cocotron͕ଘࡏ͢Δ – ιʔεϨϕϧͰ࣮૷͕ಡΊΔ – ͋͘·Ͱ࢓༷ॻϕʔεͷ࠶࣮૷Ͱ͋ΓɺຊՈͱίʔυϨϕϧͰಉ͜͡ͱ͸ظ଴Ͱ͖ͳ͍ – 2019ݱࡏɺ૒ํ։ൃ͸ΞΫςΟϒͰ͸ͳ͍ → ຊՈAppKitͱͷဃ཭͸ਐΉҰํ – ઌਓͷ஌ܙͱͯ͠࢖͑Δ – Ұհͷ։ൃऀ͕1ਓͰߟ͑ΔΑΓ΋ਅ࣮ʹ͍ۙظ଴஋͕ߴ͍ とはいえGNUstepは動きがあるが

Slide 28

Slide 28 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp ͓ Θ Γ

Slide 29

Slide 29 text

macOS native (/6TUFQͱ$PDPUSPO © 2019 1024jp ࢀߟจݙ – GNUstep, the open source OpenStep http://www.linuxfocus.org/English/March2001/article195.shtml – Core GNUstep developers interview http://www.roard.com/docs/interview/ – Developer Documentation –GNUstep http://www.gnustep.org/developers/documentation.html