[Obj-C] 04 Objective-C 2.0学習 “オブジェクトの型と動的結合” 04-01

[Mac M2 Pro 12CPU, Ventura 13.6, clang 15.0.0]
教本:『詳解 Objective-C 2.0 第3版』(2011年) chap.04-01

動的バインディングとポリモーフィズムについて学びました。

コードの簡素化に寄与する反面、実行速度が遅くなるようです。

プログラミングをミスった場合、静的バインディングであればコンパイルエラーになり、動的バインディングであれば実行時エラーになります。

これは実務レベルで体感してみないとメリット・デメリットを深く理解できないように思いました。

取りあえず先に進みます。

#import <Foundation/NSObject.h>
#import <stdio.h>

@interface A : NSObject
- (void)whoAreYou;
@end

@implementation A
- (void)whoAreYou { printf("I'm A\n"); }
@end

@interface B : NSObject
- (void)whoAreYou;
@end

@implementation B
- (void)whoAreYou { printf("I'm B\n"); }
@end

int main(void)
{
    id obj;
    int n;

    scanf("%d", &n);
    switch (n) {
    case 0:  obj = [[A alloc] init]; break;
    case 1:  obj = [[B alloc] init]; break;
    case 2:  obj = [[NSObject alloc] init]; break;
    }
    [obj whoAreYou];
    return 0;
}
1
I'm B
2
2023-10-16 10:28:08.551 dyna[12438:464557] -[NSObject whoAreYou]: unrecognized selector sent to instance 0x600002a70000
2023-10-16 10:28:08.552 dyna[12438:464557] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSObject whoAreYou]: unrecognized selector sent to instance 0x600002a70000'
*** First throw call stack:
(
	0   CoreFoundation                      0x00000001aac0b104 __exceptionPreprocess + 176
	1   libobjc.A.dylib                     0x00000001aa729fd0 objc_exception_throw + 60
	2   CoreFoundation                      0x00000001aacb210c -[NSObject(NSObject) __retain_OA] + 0
	3   CoreFoundation                      0x00000001aab73030 ___forwarding___ + 1600
	4   CoreFoundation                      0x00000001aab72930 _CF_forwarding_prep_0 + 96
	5   dyna                                0x00000001026efefc main + 176
	6   dyld                                0x00000001aa75bf28 start + 2236
)
libc++abi: terminating due to uncaught exception of type NSException
Abort trap: 6

[Obj-C] 03 Objective-C 2.0学習 “継承とクラス”

[Mac M2 Pro 12CPU, Ventura 13.6, clang 15.0.0]
教本:『詳解 Objective-C 2.0 第3版』(2011年) chap.3

Objective-Cのクラス継承について学びました。

下記のコードでは[y method2]のところで循環するのではないかと思いましたが、superを呼び出した時点でスーパークラスはclass Aに固定されるようです。

今さらですが、@interfaceはヘッダファイル、@implementationはソースファイルに分割可能でしたね。Objective-Cアプリは昨年6月に初めて書いたきりなので、すっかり忘れていました。

#import <Foundation/NSObject.h>
#import <stdio.h>

@interface A: NSObject
- (void)method1;
- (void)method2;
@end

@implementation A
- (void)method1 { printf("method1 of Class A\n"); }
- (void)method2 { printf("method2 of Class A\n"); }
@end

@interface B: A
- (void)method2;
@end

@implementation B
- (void)method2 {
    printf("method2 of Class B\n");
    printf("self --> ");
    [self method1];
    printf("super--> ");
    [super method2];
}
@end

@interface C: B
- (void)method1;
@end

@implementation C
- (void)method1 { printf("method1 of Class C\n"); }
@end

int main(void)
{
    id x = [[B alloc] init];
    id y = [[C alloc] init];
    printf("--- instance of B ---\n");
    [x method1];
    [x method2];
    printf("--- instance of C ---\n");
    [y method1];
    [y method2];
    return 0;
}
--- instance of B ---
method1 of Class A
method2 of Class B
self --> method1 of Class A
super--> method2 of Class A
--- instance of C ---
method1 of Class C
method2 of Class B
self --> method1 of Class C
super--> method2 of Class A // 循環にならない

[Obj-C] 02 Objective-C 2.0学習 “Objective-Cのプログラム”

[Mac M2 Pro 12CPU, Ventura 13.6, clang 15.0.0]

しばらくObjective-CやSwiftを集中的に学んでいきます。教本は『詳解 Objective-C 2.0 第3版』(2011年)です。

CHAPTER02まで読みました。サンプルコードはXcodeではなくmakefileでコンパイルします。

メソッドの第1引数に変数名がない、そもそも引数そのものを変数名にしていない、というルールにVisual Basicに対する違和感と同様のものを覚えます。単に仕様が古いということでしょうか。

まあ細かいことは気にせず淡々と読み進めます。

#import "Volume.h"

@implementation Volume
- (id)initWithMin:(int)a max:(int)b step:(int)s
{
    self = [super init];
    if (self != nil) {
        val = min = a;
        max = b;
        step = s;
    }
    return self;
}

- (int)value
{
    return val;
}

- (id)up
{
    if ((val += step) > max)
        val = max;
    return self;
}

- (id)down
{
    if ((val -= step) < min)
        val = min;
    return self;
}
@end

[Obj-C] 01 UIKit iOS 3のコードを動かす

[Mac M2 Pro 12CPU, Ventura 13.6, iOS 17, Xcode 15.0]

昨年22年6月に気まぐれで購入したUIKitの本を通読していきます。『iPhoneプログラミングUIKit詳解リファレンス』(2010年)という本です。300円で買えました。

まずは出版社サイトにあるサンプルコードを以下の手順で動くようにしました。

1.プロジェクトファイル内にあるpbxprojファイルをエディタで開き、iphoneos3.1の3.1を削除するか最近のiOSバージョン番号にする。

2.Interface Builderの右にあるiOSバージョン番号設定を1と同じにする。

3.AppDelegateファイルに以下のように追記する。

#import "HelloWorldAppDelegate.h"

@implementation HelloWorldAppDelegate

@synthesize window;

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after application launch
    window.rootViewController = [UIViewController new]; // この行を追加
    [window makeKeyAndVisible];
}

- (void)dealloc {
    [window release];
    [super dealloc];
}

@end

[Obj-C++] Drag & Drop 実装 01 : mouseDownメソッド

Drag & Dropの実装はApple公式ドキュメントのコードが古くなっていることもあり一筋縄ではいきません。一つ一つ解決していきます。

NSString *filePath1, *filePath2; // Assume these exist
 
- (void)mouseDown:(NSEvent *)theEvent
{
    NSImage *dragImage;
    NSPoint dragPosition;
 
    // Write data to the pasteboard
    NSArray *fileList = [NSArray arrayWithObjects:filePath1, filePath2, nil];
    NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
    [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
            owner:nil];
    [pboard setPropertyList:fileList forType:NSFilenamesPboardType];
 
    // Start the drag operation
    dragImage = [[NSWorkspace sharedWorkspace] iconForFile:filePath1];
    dragPosition = [self convertPoint:[theEvent locationInWindow]
                        fromView:nil];
    dragPosition.x -= 16;
    dragPosition.y -= 16;
    [self dragImage:dragImage
            at:dragPosition
            offset:NSZeroSize
            event:theEvent
            pasteboard:pboard
            source:self
            slideBack:YES];
}
警告1
/XlsxConvertor.mm:292:61: warning: 
'NSDragPboard' is deprecated: first deprecated in macOS 10.13 
[-Wdeprecated-declarations]
    NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
                                                            ^~~~~~~~~~~~
                                                            NSPasteboardNameDrag
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSPasteboard.h:338:32: note: 'NSDragPboard' has been explicitly marked deprecated here
APPKIT_EXTERN NSPasteboardName NSDragPboard API_DEPRECATED_WITH_REPLACEMENT("NSPasteboardNameDrag", macos(10.0,10.13));
                               ^
警告2
/XlsxConvertor.mm:293:51: warning: 'NSFilenamesPboardType' is deprecated: first deprecated in macOS 10.14 - Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead [-Wdeprecated-declarations]
    [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
                                                  ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSPasteboard.h:312:32: note:
'NSFilenamesPboardType' has been explicitly marked deprecated here
APPKIT_EXTERN NSPasteboardType NSFilenamesPboardType API_DEPRECATED("Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead", macos(10.0,10.14));
                               ^
警告3
/XlsxConvertor.mm:295:46: warning: 
'NSFilenamesPboardType' is deprecated: first deprecated in macOS 10.14 
- Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead [-Wdeprecated-declarations]
    [pboard setPropertyList:fileList forType:NSFilenamesPboardType];
                                             ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSPasteboard.h:312:32: note: 
'NSFilenamesPboardType' has been explicitly marked deprecated here
APPKIT_EXTERN NSPasteboardType NSFilenamesPboardType API_DEPRECATED("Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead", macos(10.0,10.14));
                               ^
警告4
/XlsxConvertor.mm:299:26: warning: instance method '-convertPoint:fromView:' not found (return type defaults to 'id') [-Wobjc-method-access]
    dragPosition = [self convertPoint:[theEvent locationInWindow]
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
注意1
/XlsxConvertor.mm:7:12: note: receiver is instance of class declared here
@interface Window : NSWindow {
           ^
エラー1
/XlsxConvertor.mm:299:18: error: no viable overloaded '='
    dragPosition = [self convertPoint:[theEvent locationInWindow]
    ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/CoreGraphics.framework/Headers/CGGeometry.h:20:1: note: 
candidate function (the implicit copy assignment operator) not viable: no known conversion from 'id' to 'const CGPoint' for 1st argument
CGPoint {
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/CoreGraphics.framework/Headers/CGGeometry.h:20:1: note: 
candidate function (the implicit move assignment operator) not viable: no known conversion from 'id' to 'CGPoint' for 1st argument
4 warnings and 1 error generated.

Drag and Drop Programming Topics
Dragging Files