@property NSString *Id
の名前でプロパティーを定義していたところ、Swift化するにあたって名前を var id: String?
に直したら、他のまだSwift化されてないObj-Cファイルからの呼び出しで .id
でアクセスできます?それともSwift化するときに var Id: String?
で宣言しないとダメです?id
にしても大丈夫か?って話ですか?(予約語?だからid
にしても大丈夫かですね@property NSString *Id
で定義したものをSwiftで呼び出すときは .id
に直されてるからね…var id
で定義したものをObj-Cで .Id
で呼び出せない、当然ですが (edited)@objc
使って@objc([ALT_NAME])
って感じで別名つけられるように、プロパティも別名をつけられるんじゃないでしょうか。@objc(Id) var id: String?
で無事ビルド通りました!ありがとうございます!!Id
で見せるのか。UIViewController<HogeProtocol>
で表現できていた型をswiftにブリッジするとUIViewController & HogeProtocol
ってなると思うんですけど、これswift3以前はどういう風にブリッジされてたんですかね&
で型を複合するのって、プロトコル&プロトコルは前からできたけど型&プロトコルっていつからできたんだっけobjective-c - (NSObject *)something:(NSError **)error { return nil; }
NSError * __autoreleasing *
が作法だったような-(NSObject *)func1WithError:(NSError **)error; func func1() throws -> NSObject
do { let a: AAA = AAA() let b: NSObject = try a.func1() } catch { print(error) print("--") print(type(of: error)) print("--") dump(error) }
nilError -- _GenericObjCError -- - Foundation._GenericObjCError.nilError
-(NSObject * _Nullable)func1WithError:(NSError * _Nullable * _Nullable)error;
これで全く同じだったよ-(NSObject *)func2; -(NSObject * _Nullable)func3; -(NSObject * _Nonnull)func4;
func func2() -> NSObject! func func3() -> NSObject? func func4() -> NSObject
-(NSObject * _Nonnull)func5WithError:(NSError * _Nullable * _Nullable)error;
func func5WithError(_ error: NSErrorPointer) -> NSObject
typealias NSErrorPointer = AutoreleasingUnsafeMutablePointer<NSError?>?
-(NSObject * _Nonnull)func6WithError:(NSError * __strong _Nullable * _Nullable)error;
func func6WithError(_ error: UnsafeMutablePointer<NSError?>?) -> NSObject
UIApplicationMain
で EXC_BREAKPOINT
で落ちちゃうけど、普通ならZombie Object使うとかExceptionのブレーカーポイント置くとかで原因特定できるはずだけど、今回だけ何をやっても原因特定できない&iOS 14だけで発生するバグに直面している…もうお手上げ状態 (edited)performSelectorOnMainThread
ですね…retain
が抜けてたことによって発生した問題だったとは…wrelease
呼び出すときちゃんとその release
で止まってたはずだけどな… あとiOS 13だとこの現象が発生しないのも気になります…viewDidLoad
のコメントが見えますけど @property
の方が全く見えませんです 何か足りないことや、間違ってることをしているのでしょうかself.signInButton
は [self signInButton];
のシンタックスシュガーなので、 self.signInButton.frame = CGRectMake(20, self.view.frame.size.height - 50 - self.view.safeAreaInsets.bottom, self.view.frame.size.width * 0.9, 50); self.signInButton.layer.cornerRadius = self.signInButton.frame.size.height / 2; [self.signInButton addTarget:self action:@selector(handlePress:) forControlEvents:UIControlEventTouchUpInside];
^ の行の self.signInButton
は全部 [self signInButton];
となるので、毎回新しいボタンが生成されてそれに対して設定しているので、全部無駄になっています。 Swiftのコードと同等にするにはまずヘッダファイルにプロパティの定義がなければ次のように追加してください。 @interface WelcomeViewController () @property (nonatomic) UIButton *signInButton; @end
自動的に _signInButton
という変数が追加されるので、 getterメソッドを次のように書き換えてください。 - (UIButton *)signInButton { if (!_signInButton) { UIButton *button = [[UIButton alloc] init]; button.backgroundColor = [UIColor systemRedColor]; button.layer.borderWidth = 2; button.clipsToBounds = YES; [button setTitle:@"Apple IDでログイン" forState:UIControlStateNormal]; [button setTitleColor:[UIColor systemBackgroundColor] forState:UIControlStateNormal]; _signInButton = button; } return _signInButton; }
@interface WelcomeViewController : UIViewController @property (nonatomic) UIButton *signInButton; @end @implementation WelcomeViewController - (UIButton *)signInButton { if (!_signInButton) { UIButton *button = [[UIButton alloc] init]; button.backgroundColor = [UIColor systemRedColor]; button.layer.borderWidth = 2; button.clipsToBounds = YES; [button setTitle:@"Apple IDでログイン" forState:UIControlStateNormal]; [button setTitleColor:[UIColor systemBackgroundColor] forState:UIControlStateNormal]; _signInButton = button; } return _signInButton; } - (void)viewDidLoad { [super viewDidLoad]; self.title = @"タイトル"; self.view.backgroundColor = [UIColor systemGreenColor]; [self.view addSubview:self.signInButton]; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.signInButton.frame = CGRectMake(20, self.view.frame.size.height - 50 - self.view.safeAreaInsets.bottom, self.view.frame.size.width * 0.9, 50); self.signInButton.layer.cornerRadius = self.signInButton.frame.size.height / 2; [self.signInButton addTarget:self action:@selector(handlePress:) forControlEvents:UIControlEventTouchUpInside]; } - (void)handlePress: (UIButton *) sender { printf("Button pressed!"); } @end
int property
numberを作成する場合 そのgetter/setterの中は新しいvariable _number
が使うことができますね // header @property int number;
// objc file - (int)number { return _number; } // これがgetter - (void)numberSetter:(int)newNumber { _number = newNumber; } // これがsetter
ということなんですね めっちゃわかりやすく説明をしてくれてありがとうございます!int n = self.number;
<= は - (int)number { return _number; }
ですが、setterの self.number = 100;
は - setNumber:(int)newNumber { _number = newNumber; }
と、 setXxx
という規則になります。 https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html ^ たぶんOfficialのDocumentはこれだと思います。(もっと新しいのがあるかも)@optional
なメソッドがある Objective-C のプロトコルにコンフォームした Objective-C のクラスを Swift で extend した場合、その @optional
なメソッドが?
で呼べない... (edited)@protocol P <NSObject> @optional - (void)optionalMethod; @end @interface C : NSObject <P> @end class S: C { override func optionalMethod() { super.optionalMethod?() // できない } }
(edited)super.responds(to: #selector()
で守るしかないかもfunc takeP<X: P>(_ x: X) { x.optionalMethod?() } takeP(self)
Method does not override any method from its superclass
といわれた@objc protocol P { @objc optional func optionalMethod() } class C: P { } class C2: C { override func optionalMethod() { super.optionalMethod?() } }
super.responds(to: #selector()
で想定通り動きますか?Argument of '#selector' does not refer to an '@objc' method, property, or initializer
え...()
いらないのか。 (edited)[[self superclass] instancesRespondsToSelector
これ使えるのかな。@protocol P <NSObject> @optional - (void)optionalMethod; @end @interface C : NSObject <P> @end
import MyFW C().optionalMethod?() // コンパイル通らない C().optionalMethod() // 実行時エラー
なので、overrideの問題というよりは、やっぱり super を P として解釈する手段がない問題の気がする (edited)