Objective-C warning: Class 'ViewController' does not conform to protocol 'CBPeripheralManagerDelegate' - objective-c

I'm trying to create an Obj-C, CoreBluetooth virtual peripheral app and get this warning.
//
// ViewController.h
// sim_backend_empty3
//
//
#import <UIKit/UIKit.h>
#import <CoreBluetooth/CoreBluetooth.h>
#interface ViewController : UIViewController <CBPeripheralManagerDelegate>
#property (nonatomic, strong) CBPeripheralManager *peripheralManager;
#end
//
// ViewController.m
// sim_backend_empty3
//
//
#import "ViewController.h"
#implementation ViewController >>>>>>>>>> WARNING >>>>>>>>>> Class 'ViewController' does not conform to protocol 'CBPeripheralManagerDelegate'
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)start_BLE_advertisements
{
[[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil];
}
#end

You need to implement the required CBPeripheralManagerDelegate protocol method:
peripheralManagerDidUpdateState:
as mentioned in the documentation here: https://developer.apple.com/documentation/corebluetooth/cbperipheralmanagerdelegate?language=objc
The protocol’s required one method, peripheralManagerDidUpdateState:, which Core Bluetooth calls whenever the peripheral manager’s state updates to indicate whether the peripheral manager is available.

You can check out an Objective-C example of how to setup CoreBluetooth using this repo:
https://github.com/LGBluetooth/LGBluetooth
Back when I still coded in ObjC, it was the library I used - and it was pretty great.
At the very least, it will give you some ideas on how you should be implementing the interfaces.
Here is a Swift implementation of what it sounds like you're trying to do (based on your other question asked a few days ago). Maybe you can backport it to ObjC (disclaimer: I'm the author).
https://github.com/RobotPajamas/SwiftyTeeth/blob/master/Sources/SwiftyTooth/SwiftyTooth.swift

Related

Delegate from Obj-C into Swift - method is never executed

Before I was using NSNotificationEvents, but as I know I should be using delegate because of 1:1 relations (it will be used only in one place in code).
Basically Im new to objective-C and swift (Im JavaScript guy) and the code that I created after a few hours of reading and checking - it just doesnt work, because self.delegate in not defined.
Im trying to delegate "an event" from objective-C code to swift code. NSNotificationEvents works like charm, but I want to make it with protocols / delegate.
I guess, I just missing how to exactly initialize the delegate protocol.
ProtocolDelegate.h
#import <Foundation/Foundation.h>
#protocol ProtocolDelegate <NSObject>
- (void) delegateMethod: (id)data;
#end
Event.h
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "ProtocolDelegate.h"
#interface Event : NSObject <RCTBridgeModule, ProtocolDelegate>
#property(nonatomic, weak)id <ProtocolDelegate> delegate;
#end
Event.m
(someMethod is executed from JavaScript React-native code, but it shouldn't be any difference from what I know)
#import "Event.h"
#implementation Event
RCT_EXPORT_MODULE(Events);
RCT_EXPORT_METHOD(someMethod: (NSString*)parameter) {
NSDictionary* data = #{#"parameter": parameter};
NSLog(#"This I can see");
if ([self.delegate respondsToSelector:#selector(delegateMethod:)]) {
NSLog(#"This I can not see");
[self.delegate delegateMethod:data];
}
}
ViewController.swift
class ViewController: UIViewController, ProtocolDelegate {
// Xcode has automatically created this method
func delegateMethod(_ data: Any!) {
os_log("ON AUCTION");
}
}
I want delegateMethod inside ViewController to be executed.
Or maybe I get the whole idea wrong? Objective-C is a bit confising to me.

No access to global instance (build by factory) on iOS

this is a follow-up question to my last one here: iOS: Initialise object at start of application for all controllers to use .
I have set my application up as follows (ignore the DB Prefix):
DBFactoryClass // Built a DataManaging Object for later use in the app
DBDataModel // Is created by the factory, holds all data & access methods
DBViewControllerA // Will show some of the data that DBDataModel holds
moreViewControllers that will need access to the same DBDataModel Object
i will go step by step through the application, and then post the problem in the end
AppDelegate.h
#import "DBFactoryClass.h"
AppDelegate.m
- (BOOL)...didFinishLaunching...
{
DBFactoryClass *FACTORY = [[DBFactoryClass alloc ]init ];
return YES;
}
DBFactoryClass.h
#import <Foundation/Foundation.h>
#import "DBDataModel.h"
#interface DBFactoryClass : NSObject
#property (strong) DBDataModel *DATAMODEL;
#end
DBFactoryClass.m
#import "DBFactoryClass.h"
#implementation DBFactoryClass
#synthesize DATAMODEL;
-(id)init{
self = [super init];
[self setDATAMODEL:[[DBDataModel alloc]init ]];
return self;
}
#end
ViewControllerA.h
#import <UIKit/UIKit.h>
#import "DBDataModel.h"
#class DBDataModel;
#interface todayViewController : UIViewController
#property (strong)DBDataModel *DATAMODEL;
#property (weak, nonatomic) IBOutlet UILabel *testLabel;
#end
ViewControllerA.m
#import "todayViewController.h"
#implementation todayViewController
#synthesize testLabel;
#synthesize DATAMODEL;
- (void)viewDidLoad
{
todaySpentLabel.text = [[DATAMODEL test]stringValue]; // read testdata
}
#end
DBDataModel.h
#import <Foundation/Foundation.h>
#interface DBDataModel : NSObject
#property (nonatomic, retain) NSNumber* test;
#end
DBDataModel.m
#import "DBDataModel.h"
#implementation DBDataModel
#synthesize test;
-(id)init{
test = [[NSNumber alloc]initWithInt:4]; // only a testvalue
return self;
}
#end
the app builds fine, and starts up but the label stays blank. so either the object does not exist (but i guess this would result in an error message), or something else is wrong with my setup. any thoughts?
Two notes:
Your have a shotgun approach to asking questions: everytime you hit a stumbling block, you ask a question and if the answer does not work immediately, you ask another one. You have to spend some energy in between the questions debugging and poking into the code on your own, otherwise you will depend on the external help forever.
Use the common coding style please. CAPS are reserved for macros.
Now to the code:
- (BOOL) …didFinishLaunching…
{
DBFactoryClass *factory = [[DBFactoryClass alloc] init];
return YES;
}
This simply creates an instance of the DBFactoryClass and then throws it away. In other words, it’s essentially a no-op. Judging by the comments in the previous answer you create the controllers using the Storyboard feature. How are they supposed to receive the reference to the data model? The reference isn’t going to show up by magic, you have to assign it somewhere.
I’m not familiar with the Storyboard feature. The way I would do it is to create the view controllers using separate XIB files, then you can create the controller instances in the Factory class and pass them the needed reference to the model. In the end the application delegate would create the factory, ask it to assemble the main controller and then set it as the root view controller for the window. Just like in my sample project. It’s possible that there’s a way to make it work with storyboards, but as I said, I am not familiar with them.

Problems implementing a protocol

I am developing a game and I have a settings view that is pushed modally. I want if I turn music off in that view, stop the background music. I'm using a protocol (I am using automatic reference counting):
game.h
#import <UIKit/UIKit.h>
#import "AVFoundation/AVFoundation.h"
#import "stackButton.h"
#import "tvr_AppDelegate.h"
#protocol settingsChanger <NSObject>
-(void)changeSettings:(int)soundVal musicSetting:(int)musicVal;
#end
#interface game : UIViewController <UIAlertViewDelegate, settingsChanger>{
...
}
game.m
-(void)changeSettings:(int)soundVal musicSetting:(int)musicVal{
if (musicVal == 1) {
[self playMusic];
}else{
[audioPlayer stop];
}
settings.h
#import <UIKit/UIKit.h>
#protocol settingsChanger;
#interface settings : UIViewController{
id<settingsChanger> settingsDelegate;
}
#property (nonatomic, strong) id<settingsChanger> settingsDelegate;
-(IBAction)updateMusicSetting;
#end
settings.m
-(IBAction)updateMusicSetting{
tvr_AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
if (swMusic.on) {
[delegate updateMusicSetting:1];
[settingsDelegate changeSettings:0 musicSetting:1];
}
else {
[delegate updateMusicSetting:0];
[settingsDelegate changeSettings:0 musicSetting:0];
}
}
My IBAction is triggered by a UISwitch. All goes fine, except that id settingsDelegate references to memory 0x0 and I think that's the my method changeSettings is never called in game.h. What am I missing?.
I would suggest as a good programming practice to name your classes with an uppercase, that is: "Game" instead of "game" and your protocols as well: "SettingsChanger" instead of "settingsChanger". Your method naming conventions seem also to need some improvement, just take 30 minutes time and read Apples "Cocoa Guidelines For Cocoa" link to the "Cocoa Guidelines For Cocoa document"

Cannot use respondsToSelector using ARC on Mac

When I call respondsToSelector in an ARC environment, I get the following error message Automatic Reference Counting Issue No known instance method for selector respondsToSelector:
This is the header
#import <AppKit/AppKit.h>
#class MTScrollView;
#protocol MTScrollViewDelegate
-(void)scrollViewDidScroll:(MTScrollView *)scrollView;
#end
#interface MTScrollView : NSScrollView
{
}
#property(nonatomic, weak) id<MTScrollViewDelegate>delegate;
#end
This is the implementation file
#import "MTScrollView.h"
#implementation MTScrollView
#synthesize delegate;
- (void)reflectScrolledClipView:(NSClipView *)aClipView
{
[super reflectScrolledClipView:aClipView];
if([delegate respondsToSelector:#selector(scrollViewDidScroll:)])
{
[delegate scrollViewDidScroll:self];
}
}
#end
Any suggestions on why I am getting this error?
Make the protocol conform to NSObject
#protocol MTScrollViewDelegate <NSObject>
Otherwise the compiler doesn't think that the object will respond to NSObject messages like respondsToSelector, and will generate a warning. It will succeed at runtime without issues either way.
For Swift this becomes:
#objc protocol MTScrollViewDelegate: NSObjectProtocol
The NSObject protocol groups methods that are fundamental to all Objective-C objects.
For more information on what NSObjectProtocol is: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/index.html

Making class conform to protocol with category for existing methods

I have a protocol named MyProtocol.
MyProtocol has an required method:
- (NSUInteger)length;
And some other methods.
Now i want to make the NSString class conform to MyProtocol with a category. Like so:
#interface NSString (NSStringWithMyProtocol) <MyProtocol>
#end
In this category i implement all methods excluding the 'length' method, because i want the original NSString implementation.
I do not want to override it in this particular class.
Now i get a warning because of an incomplete implementation of MyProtocol in the category.
I know there are a few solutions to solve this.
Make the method optional
Pointer Swizzling
Adding subclass to class which is conform to the protocol. Then leave out the implementation.
I do not want to use these options because they result in a bad design for the rest of my code.
Option 3 is bad, because of existing direct subclasses will not be conform to the protocol.
Does anybody know how to remove the warning without implementing the length method?
NOTE: The class, category and protocol are just examples. I did encounter this problem with other classes which i could not post about.
Thanks
EDIT: Added the third option.
Full Code:
The protocol:
#protocol MyProtocol <NSObject>
- (void) myMethod;
- (NSInteger) length;
#end
The category header:
#import <Foundation/Foundation.h>
#import "MyProtocol.h"
#interface NSString (MyProtocol) <MyProtocol>
#end
The category implementation:
#implementation NSString (MyProtocol)
- (void)myMethod {
}
#end
This results in the following warnings.
Incomplete implementation
Method in protocol not implemented
In this screenshot you can see my warning:
I tried compiling with LLVM GCC 4.2 and the Apple LLVM 3.0 compiler.
I also compiled on xcode 4.0.2 and Xcode 4.2.
I'm on OS X 10.6.8.
I cannot reproduce this issue. Can you post code that demonstrates it? The following compiles without warnings on 10.7.
#import <Foundation/Foundation.h>
#protocol MyProtocol <NSObject>
- (NSUInteger)length;
#end
#interface NSString (NSStringWithMyProtocol) <MyProtocol>
#end
int main (int argc, const char * argv[]) {
#autoreleasepool {
id<MyProtocol> foo = #"foo";
NSLog(#"%#", foo);
}
return 0;
}
You might consider this a bit of a hack, and I don't know if it will even work, but how about declaring it as a read only property
#property (readonly, assign) NSUInteger length;
and then in the implementation of your category, make it #dynamic