Incompatible pointer types assigning to 'id<AVAudioPlayerDelegate>' from 'Class' - warnings

I have a "Utility" class that implements the AVAudioPlayerDelegate protocol.
This is my Utility.h
#interface Utility : NSObject <AVAudioPlayerDelegate>
{
}
And this is its counterpart Utility.m
#implementation Utility
static AVAudioPlayer *audioPlayer;
+ (void)playAudioFromFileName:(NSString *)name ofType:(NSString *)type withPlayerFinishCallback:(SEL)callback onObject:(id)callbackObject
{
...
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: [self getResourceURLForName:name ofType:type] error: nil];
audioPlayer.delegate = self; // this is the line that causes the Warning
...
}
My iOS application works well, however after migrating to iOS 5 and Xcode 4.2 the compiler started throwing this warning, located at the audioPlayer.delegate = self; line:
Incompatible pointer types assigning to id <AVAudioPlayerDelegate> from 'Class'
How can I get rid of it?

You've declared your method as a class method, and you're trying to use the Class object as the delegate. But you can't add protocols to Class objects.
You need to change playAudioFromFileName:... to an instance method and create an instance of Utility to use as the delegate. Maybe you want to have a single instance of Utility shared by all callers. This is the Singleton pattern, and it's pretty common in Cocoa. You do something like this:
Utility.h
#interface Utility : NSObject <AVAudioPlayerDelegate>
+ (Utility *)sharedUtility;
#end
Utility.m
#implementation Utility
+ (Utility *)sharedUtility
{
static Utility *theUtility;
#synchronized(self) {
if (!theUtility)
theUtility = [[self alloc] init];
}
return theUtility;
}
- (void)playAudioFromFileName:(NSString *)name ofType:(NSString *)type withPlayerFinishCallback:(SEL)callback onObject:(id)callbackObject
{
...
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: [self getResourceURLForName:name ofType:type] error: nil];
audioPlayer.delegate = self;
...
}
#end
Usage
[[Utility sharedUtility] playAudioFromFileName:#"quack" ofType:"mp3" withPlayerFinishCallback:#selector(doneQuacking:) onObject:duck];

When you don't need an instance of a Class, just manually get ride of the warning:
audioPlayer.delegate = (id<AVAudioPlayerDelegate>)self;
On the other hand, please note that if you need a Delegate, it means you should have an instance of a Class as a good coding practice instead of a static Class. It can be made a singleton easily:
static id _sharedInstance = nil;
+(instancetype)sharedInstance
{
static dispatch_once_t p;
dispatch_once(&p, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}

Related

JSONModel not working with Swift arrays

I am having some trouble using JSONModel in Swift.
I am trying to create a ToDo list app that would persist a collection of items so that the ToDo items are preserved when the app is closed. This is the code I use:
class ToDoItem: JSONModel {
var name: String = ""
var isCompleted: Bool = false
var createdOn: NSDate = NSDate()
}
class ToDoList: JSONModel {
var items: [ToDoItem] = []
}
I can convert a ToDoItem to JSON by calling toJSONString() but the same method doesn't work with ToDoList, it returns nil. Any idea why is this happening?
JSONModel does not support Swift due to incompatibilities with the reflection supported by the Obj-C runtime. This reflection ability is currently required by JSONModel in order to resolve types correctly. We are looking into alternative methods of defining the type mappings though.
Specifically, JSONModel relies on the use of protocols to determine the type of items in collection types, such as dictionaries, arrays, etc. Protocols defined in Swift are not visible at runtime - preventing JSONModel from deserializing collection types correctly.
For the time being, you have two options:
switch from JSONModel to another JSON (de)serialization library with support for Swift
define your models in Objective-C
I know this isn't ideal, but I'm afraid a workaround is not possible with the current JSONModel behavior.
If your array is a member of some other class you can use a helper method.
Data class
#protocol Transaction
#end
#interface Transaction : JSONModel
...
#end
A "wrapper" class
#interface TransactionPage : JSONModel
#property (strong, nonatomic) NSNumber* pageNumber;
#property (strong, nonatomic) NSNumber* pageSize;
#property (strong, nonatomic) NSNumber* totalRecords;
#property (strong, nonatomic) NSNumber* totalPages;
#property (strong, nonatomic) NSArray<Transaction>* records;
- (NSArray<TphTransactionSummary*>*) recordsForSwift; // <<< Helper method
#end
Implementation on the helper method
- (NSArray<TphTransactionSummary*>*) recordsForSwift {
return self.records;
}

Delegate/Protocol doesn't work: pass Array from TableViewController to parent ViewController

I have a parent ViewController (SearchViewController) which segues to a TableViewController (FilterTableViewController) where the User can select persons in the TableView. The selections are stored in an NSMutableArray called selectedpersonArray, which works already fine. But now i need to pass them back to the parent ViewController. I tried to implement a protocol/delegate. Since I'm new to Objective-C I don't understand some parts properly and it doesn't work:
FilterTableViewController.h (Child Controller)
#protocol filterDelegate <NSObject>
-(void)addArraytoSearchViewController:(NSMutableArray *)array;
#end
#interface FilterTableViewController : UITableViewController
#property (nonatomic, assign) id <filterDelegate> selectedpersonDelegate;
#property (nonatomic, retain) NSMutableArray *selectedpersonArray;
#end
FilterTableViewController.m
#import "FilterTableViewController.h"
#interface FilterTableViewController ()
#end
#implementation FilterTableViewController
...
#synthesize selectedpersonArray;
#synthesize selectedpersonDelegate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[[self selectedpersonDelegate] addArraytoSearchViewController:selectedpersonArray];
NSLog(#"personarray: %#", selectedpersonDelegate);
}
Question 1: Can I show the delegate in NSLog? Here it returns nil, but selectedpersonArray contains values.
Question 2: Is there a better place to pass the Array than didSelectRowAtIndexPath, because multiple selections are possible and the Array could be passed only when the Back button is pushed. Can I use *- (void)prepareForSegue:(UIStoryboardSegue )segue sender:(id)sender?
SearchViewController.h: (Parent View)
#import "FilterTableViewController.h"
#interface SearchViewController: UIViewController <UITableViewDataSource, UITableViewDelegate, filterDelegate>
SearchViewController.m:
#implementation SearchViewController
...
- (void)viewDidLoad{
FilterTableViewController * FTC = [[FilterTableViewController alloc] init];
FTC.delegate = self;
- (void)addArraytoSearchViewController:(NSMutableArray *)array {
NSLog(#"%#", array);
}
Question 3: NSLog doesn't do anything here... Whats wrong?
Question 4: How can I pass more than one Array from the second ViewController?
thanks in advance!
i forgot to set the delegate as user firoze figured out. this solved my problem
It sounds as if you aren't actually setting the delegate on the FilterTableViewController that the segue is presenting for you. Just set the delegate in your prepareForSegue:sender: method where you are apparently pushing other data as well.
Right now in your -[SearchViewController viewDidLoad] method, you are creating some other instance called FTC, setting its delegate, and then promptly throwing that FTC instance away. That instance is unrelated to the one that will be pushed by the segue.
On your other questions:
1.) Yes, you should be able to see the delegate there.
2.) Yes, if you want to collect multiple selections, then it probably makes more sense to notify your delegate when the selections are complete.
3.) Likely this method is never called because you never set the delegate correctly.
4.) If you have two arrays, you might just include two parameters on your delegate method. If more than 2, I would think about a dictionary of arrays, or an array of arrays.

Xcode need help merging GPS project, Accelerometer project, Compass project and MySQL project

I have 4 Xcode projects ( GPS, Accelerometer, Compass and MySQL).
Each of them individually are compiling fine and are working fine.
I will like to combine all of them into one project so I can send the GPS, Accelerometer and Compass info to a mySQL database.
I have tried to copy the .h and the .m and the frameworks required from project to another.
Mainly the problem arises here :
- (IBAction)insert:(id)sender
{
// create string contains url address for php file, the file name is phpFile.php, it receives parameter :name
//NSString *strURL = [NSString stringWithFormat:#"http://localhost/phpFile.php?name=%#",txtName.text];
NSString *strURL = [NSString stringWithFormat:#"http://localhost/phpFile.php?name=%#",speedLabel.text]; ************< use of undefined identifier 'speedLabel'****
// to execute php code
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
// to receive the returend value
NSString *strResult = [[[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding]autorelease];
NSLog(#"%#", strResult);
}
Here is the structure which speedLabel is contained :
#interface CoreLocationDemoViewController : UIViewController <CoreLocationControllerDelegate> {
CoreLocationController *CLController;
IBOutlet UILabel *speedLabel;
IBOutlet UILabel *latitudeLabel;
IBOutlet UILabel *longitudeLabel;
IBOutlet UILabel *altitudeLabel;
IBOutlet UILabel *timeLabel;
}
Thanks for your help
Are you importing your .h file:
#import "CoreLocationDemoViewController.h"
I cannot see any flaws in your code whatsoever otherwise.
Is that code called inside the #implementation and #end scope? Are you declaring it as a property and do you then #synthesize it
In order to see the variable which come from the GPS Interface I did used the technique below that I did found somewhere in stackoverflow :
// Globals.h
#ifndef Globals_h
#define Globals_h
extern NSInteger globalVariable;
#endif
// main.m
NSInteger globalVariable;
int main(int argc, char *argv[])
{
globalVariable = <# initial value #>;
...
}
// Prefix.pch
#ifdef __OBJC__
#import
#import <Foundation/Foundation.h>
#import "Globals.h"
#endif
And I did used the technique :
NSString *strURL = [NSString stringWithFormat:#"http://localhost/phpFile.php?name=%#",speedLabel.text];
to send the info to mysql database.
But I still need a bit of help.
I have one interface for the GPS, another one for the accelerometer, another one for the compass. How can I invoke each of them so I can store the related data to each of them by clicking on one button on the Iphone ?
Many thanks
Regisma

To instance variable or not... problems with dealloc

So in my ARC project, whenever I assign my ViewController using an instance variable, it appears dealloc is never called when dismissing or popping the controller.
In my header:
ComposerView *composeView;
...
#property (nonatomic, retain) ComposerView *composeView;
...
#synthesize composeView;
then in my code:
if (composeView == nil)
composeView = [[ComposeView alloc] init];
[self.navigationController pushViewController: composeView];
Now, inside composeView, I have set all delegates to nil, but dealloc is never called and subsequently, viewDidLoad isn't called again when reloading the view controller.
If I don't use instance variables, and I just create it directly, everything is fine. Any help is appreciated, thanks!
If you are using ARC then you should be declaring your properties as strong/weak instead of retain/assign.
You probably want
#property (nonatomic, weak) ComposerView *composeView;
Check this link out for a description of strong/weak:
https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/_index.html#//apple_ref/doc/uid/TP40011226

iOS5 Storyboard UIViewController which init method is called by the storyboard?

Which init method is called by the storyboard for UIViewControllers added to the storyboard?
The initializer used is initWithCoder:
- (id)initWithCoder:(NSCoder *)decoder
Then afterwards you will also get an awakeFromNib message.
I believe it is awakeFromNib
It is the - (id)initWithCoder:(NSCoder *)decoder
So if you have to do a custom init, let's say using a custom Pager Controller you have to do there like
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
return [self initWithViewControllers:#[self.playerViewController, self.categoriesViewController]
andTitles:#[#"Player",#"Categories"]];
}