I am having an this error come up:
No visible #interface for 'BinaryFileReader' declares the selector 'initWithLocation:'
for every method called on BinaryFileReader in the method below.
+ (Item*)loadItem:(NSString*)filepath {
Item* newItem = [[Item alloc] init];
BinaryFileReader* input = [[BinaryFileReader alloc] initWithLocation:filepath];
[newItem setName:[input readNSString]];
[newItem setOtherNames:[input readNSMutableArrayOfNSString]];
[newItem setDescription:[input readNSString]];
[newItem setXactCode:[input readNSString]];
[newItem setSymbilityCode:[input readNSString]];
[newItem setAverageLowPrice:[input readInt]];
[newItem setAverageHighPrice:[input readInt]];
[newItem setAverageLifeExpectancy:[input readInt]];
return newItem;
}
Here is my BinaryFileReader.m:
#import "BinaryFileReader.h"
#implementation BinaryFileReader
- (id)init {
self = [super init];
return self;
}
- (id)initWithLocation:(NSString*)filepath {
if ((self = [super init])) {
_file = [NSFileHandle fileHandleForReadingAtPath:filepath];
_fileOffset = 0;
if (_file == nil)
NSLog(#"%#%#",#"Failed to open file at path:",filepath);
}
return self;
}
- (void)close {
[_file closeFile];
}
- (int)readInt {
[_file seekToFileOffset:_fileOffset];
_databuffer = [_file readDataOfLength:4];
_fileOffset+=4;
return (*(int*)([_databuffer bytes]));
}
- (NSString*)readNSString {
int length = [self readInt];
[_file seekToFileOffset:_fileOffset];
_databuffer = [_file readDataOfLength:length];
_fileOffset+=length;
return [[NSString alloc] initWithData:_databuffer encoding:NSUTF8StringEncoding];
}
- (NSMutableArray*)readNSMutableArrayOfNSString {
NSMutableArray* array = [[NSMutableArray alloc] init];
int arrayLength = [self readInt];
int length;
for (int i=0; i<arrayLength; i++) {
length = [self readInt];
[_file seekToFileOffset:_fileOffset];
_databuffer = [_file readDataOfLength:length];
_fileOffset+=length;
[array addObject:[[NSString alloc] initWithData:_databuffer encoding:NSUTF8StringEncoding]];
}
return array;
}
#end
And BinaryFileReader.h:
#interface BinaryFileReader : NSObject
#property (nonatomic) int fileOffset;
#property (nonatomic, retain) NSData* databuffer;
#property (nonatomic, retain) NSFileHandle* file;
- (id)init;
- (id)initWithLocation:(NSString*)filepath;
- (void)close;
- (int)readInt;
- (NSString*)readNSString;
- (NSMutableArray*)readNSMutableArrayOfNSString;
#end
I don't understand why I am having this issue. Any help to clear this up would be much appreciated.
I copy&pasted the code from your question into a project of mine. Expected result: Everything compiles fine. So it's definitely not your code that is the problem.
Coming back to the idea of a different BinaryFileReader.h polluting your #imports: Do you use any third party libraries in your project? If yes, one of those might unexpectedly provide a BinaryFileReader.h file.
Try this: Rename BinaryFileReader.h to something else, e.g. Foo.h. Also change the #import in BinaryFileReader.m to use Foo.h, but leave the #import in the file where your loadItem: method is located so that it still uses BinaryFileReader.h. Now compile again. The compiler should now complain that it can't find BinaryFileReader.h. If the error is still about the missing selector then you know that somewhere you have an unexpected BinaryFileReader.h messing up your project.
Related
Hello I'm junior in Objective-C and Swift programming.
I have NSMutableArray in ExampleMenuViewController.m or(and) SomeClass.m declared as vcTabs.
NSMutableArray *vcTabs;
When I have two declares 'vcTabs' Xcode returns duplicate symbol '_vcTabs' (...)
How to add objects to an existing NSMutableArray init in other class (ExampleMenuViewController.m)?
I need append new objects from another class (SomeClass.m) to vcTabs (NSMutableArray).
I wrote in SomeClass.m this code:
if ([Tools isNonullValueForKey:[dictionary valueForKey:#"additional_tabs"]]) {
additional_tabs = [dictionary valueForKey:#"additional_tabs"];
NSLog(#"additionalTabs count: %lu", [additional_tabs count]);
for (int i = 0; i < [additional_tabs count]; i++) {
if ([Tools isNonullValueForKey:[additional_tabs valueForKey:#"_id"]]) {
additional_tab_id = [[additional_tabs valueForKey:#"_id"] objectAtIndex:i];
}
if ([Tools isNonullValueForKey:[additional_tabs valueForKey:#"names"]]) {
NSDictionary *dic = [[additional_tabs valueForKey:#"names"] objectAtIndex:i];
_en_additional_tab_name = [dic valueForKey:#"en"];
_pl_additional_tab_name = [dic valueForKey:#"pl"];
}
if ([Tools isNonullValueForKey:[additional_tabs valueForKey:#"url"]]) {
additional_tab_url = [[additional_tabs valueForKey:#"url"] objectAtIndex:i];
//NSLog(#"additional_tab_url: %#", _additional_tab_url);
}
[vcTabs addObject:[[VCTab alloc] initWithIdAndTypeAndUrl:additional_tab_id :VCTabAdditional :additional_tab_url]];
NSLog(#"%# %d %# %# %# %#", #"pos", i, #"id: ", additional_tab_id, #"url: ", additional_tab_url);
}
}
ExampleMenuViewController method with initVCTabs
- (void)initVCTabs {
vcTabs = [[NSMutableArray alloc] init];
[vcTabs removeAllObjects];
if ([Tools getBooleanUserDefault:#"example_visible_tab_attendees" :YES]) {
[vcTabs addObject:[[VCTab alloc] initWithType:VCTabAttendees]];
}
(...)
if ([Tools getBooleanUserDefault:#"example_visible_tab_user_info" :YES]) {
[vcTabs addObject:[[VCTab alloc] initWithType:VCTabUserInfo]];
}
if ([Tools getStringUserDefault:#"example_additional_tab_id" :#""]) {
NSString *additionalTabId = [Tools getStringUserDefault:#"conference_additional_tab_id" :#""];
NSString *additionalTabUrl = [Tools getStringUserDefault:#"conference_additional_tab_url" :#""];
NSLog(#"additionalTabId %#", additionalTabId);
NSLog(#"additionalTabUrl %#", additionalTabUrl);
[vcTabs addObject:[[VCTab alloc] initWithIdAndTypeAndUrl:additionalTabId :VCTabAdditional :additionalTabUrl]];
}
}
PS. If I use from ExampleMenuViewController I have only one tab with last object properties... but additional_tabs array have 17 objects.
Do you have any ideas or advices?
All the best for you everyone!
When are you calling initVCTabs?
When / how is the code in SomeClass.m running?
For being a "junior in Objective-C and Swift programming" you seem to have a lot going on that you don't understand yet. Try creating a new project and learn how things work -- then implement that in your full project.
Here is a very, very simple example. With the information you provided in your question, this may or may not relate directly - but it should give you an idea of where to go:
SomeClass.h
// SomeClass.h
// Created by Don Mag on 8/30/20.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#interface SomeClass : NSObject
- (void)moreTabs:(NSMutableArray *)a;
#end
NS_ASSUME_NONNULL_END
SomeClass.m
// SomeClass.m
// Created by Don Mag on 8/30/20.
#import "SomeClass.h"
#interface SomeClass()
#end
#implementation SomeClass
- (void)moreTabs:(NSMutableArray *)a {
[a addObject:#"B"];
[a addObject:#"C"];
[a addObject:#"D"];
[a addObject:#"E"];
}
#end
ExampleMenuViewController.h
// ExampleMenuViewController.h
// Created by Don Mag on 8/30/20.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
#interface ExampleMenuViewController : UIViewController
#end
NS_ASSUME_NONNULL_END
ExampleMenuViewController.m
// ExampleMenuViewController.m
// Created by Don Mag on 8/30/20.
#import "ExampleMenuViewController.h"
#import "SomeClass.h"
#interface ExampleMenuViewController ()
{
NSMutableArray *vcTabs;
}
#end
#implementation ExampleMenuViewController
- (void)viewDidLoad {
[super viewDidLoad];
// add a button to the view
//UIButton *b = [UIButton new];
UIButton *b = [UIButton buttonWithType:UIButtonTypeSystem];
[b setTitle:#"Tap Me" forState:UIControlStateNormal];
b.frame = CGRectMake(0, 0, 200, 50);
b.center = self.view.center;
[self.view addSubview:b];
[b addTarget:self action:#selector(btnTapped) forControlEvents:UIControlEventTouchUpInside];
[self initVCTabs];
[self logArray];
}
- (void)initVCTabs {
// instantiate NSMutableArray
vcTabs = [NSMutableArray new];
// add one object
[vcTabs addObject:#"A"];
}
- (void)btnTapped {
SomeClass *sc = [SomeClass new];
[sc moreTabs:vcTabs];
[self logArray];
}
- (void)logArray {
NSLog(#"vcTabs has %ld objects", [vcTabs count]);
for (NSString *s in vcTabs) {
NSLog(#"%#", s);
}
}
#end
When ExampleMenuViewController loads, it will add a button to the center of the view, then instantiate the vcTabs array and add one object - #"A".
We log the array to the debug console and see:
vcTabs has 1 objects
A
When you tap the button, an instance of SomeClass will be created, we call the moreTabs method in that class, passing a reference to vcTabs. That method will add 4 objects to the array - #"B" #"C" #"D" #"E".
We then log the array to the debug console and see:
vcTabs has 5 objects
A
B
C
D
E
#DonMag
It's working but I have one question to you. I added for loop to increment. When I add [additional_tabs count] is return nil. Why this method adds the same objects? My code in addMore function:
- (void)moreTabs:(NSMutableArray *)a {
for (int i = 1; i < additional_tab_count; i++) {
NSString *additionalTabId = [Tools getStringUserDefault:#"conference_additional_tab_id" :#""];
NSString *additionalTabUrl = [Tools getStringUserDefault:#"conference_additional_tab_url" :#""];
[a addObject:[[VCTab alloc] initWithIdAndTypeAndUrl:additionalTabId :VCTabAdditional :additionalTabUrl]];
}
}
Do you know how to get THIS "dictionary" or "additional_tabs". I tried but always return nil (looks like a new other instance and is not this dictionary or additional_tabs from initFromJSON). I only managed to make variable additional_tab_count and it's return 17 (correct count), but I'd rather have access to array from additional_tabs declared in if statements.
I am trying to include MWPhotoBrowser in my project
When its used as given in the sample it working fine.
But when a new viewcontroller is subclassed from MWPhotoBrowser, photos are not loaded except empty black theme.
Delegate methods are not getting called. As the controller is subclass of MWPhotoBrowser, I assume there is no need to set it explicitly.
Storyboard is used and the nib class in it is set.
.h file
#interface MDRPhotoViewerController : MWPhotoBrowser
{
NSMutableArray *_selections;
}
#property (nonatomic, strong) NSMutableArray *photos;
#property (nonatomic, strong) NSMutableArray *thumbs;
#property (nonatomic, strong) NSMutableArray *assets;
#property (nonatomic, strong) NSMutableIndexSet *optionIndices;
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, strong) ALAssetsLibrary *ALAssetsLibrary;
- (void)loadAssets;
#end
**.m file **
- (void)viewWillAppear:(BOOL)animated
{
NSMutableArray *photos = [[NSMutableArray alloc] init];
NSMutableArray *thumbs = [[NSMutableArray alloc] init];
//mwphotobrowser options setup
BOOL displayActionButton = YES;
BOOL displaySelectionButtons = NO;
BOOL displayNavArrows = NO;
BOOL enableGrid = YES;
BOOL startOnGrid = NO;
BOOL autoPlayOnAppear = NO;
//loading data
NSArray *photosDataArray = [MDRDataController GetPhotos]; //creating array
for (NSString *urlString in photosDataArray) { //Formating the data source for images
NSString *urlFullString = [NSString stringWithFormat:#"%#%#",KBASEURL,urlString];
//Photos
[photos addObject:[MWPhoto photoWithURL:[NSURL URLWithString:urlFullString]]];
//thumbs
[thumbs addObject:[MWPhoto photoWithURL:[NSURL URLWithString:urlFullString]]];
}
// Options
self.photos = photos;
self.thumbs = thumbs;
// Create browser
self.displayActionButton = displayActionButton;
self.displayNavArrows = displayNavArrows;
self.displaySelectionButtons = displaySelectionButtons;
self.alwaysShowControls = displaySelectionButtons;
self.zoomPhotosToFill = YES;
self.enableGrid = enableGrid;
self.startOnGrid = startOnGrid;
self.enableSwipeToDismiss = NO;
self.autoPlayOnAppear = autoPlayOnAppear;
[self setCurrentPhotoIndex:0];
// Test custom selection images
// browser.customImageSelectedIconName = #"ImageSelected.png";
// browser.customImageSelectedSmallIconName = #"ImageSelectedSmall.png";
// Reset selections
if (displaySelectionButtons) {
_selections = [NSMutableArray new];
for (int i = 0; i < photos.count; i++) {
[_selections addObject:[NSNumber numberWithBool:NO]];
}
}
self.title = #"Phots";
//[self reloadData];
}
Debugging performed
Considering the image template of mwphotobrowser, tried reloading the code.
Shifted the code between viewwillappear and viewdidload.
Doesn't MWPhotoBrowser support this way or am i doing it wrong ?
For those who stumble upon this later...
If you look at MWPhotoBrowser.m you'll see various initializers:
- (id)init {
if ((self = [super init])) {
[self _initialisation];
}
return self;
}
- (id)initWithDelegate:(id <MWPhotoBrowserDelegate>)delegate {
if ((self = [self init])) {
_delegate = delegate;
}
return self;
}
- (id)initWithPhotos:(NSArray *)photosArray {
if ((self = [self init])) {
_fixedPhotosArray = photosArray;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
if ((self = [super initWithCoder:decoder])) {
[self _initialisation];
}
return self;
}
The problem is there's no awakeFromNib initializer. Simplest solution is to fork the project and create the awakeFromNib initializer.
In creating a login screen with static logins I'm trying to store them privately in the following class implementation. When a button creates IONServer objects I initialize it with the function -(void)login:(NSString *)username password:(NSString *)pw and pass it two UITextField.text strings.
If you notice in the init I am testing stuff with NSLog but at every breakpoint it seems like the storedLogins NSMutable array is nil.
IONServer.m
#import "IONServer.h"
#import "IONLoginResult.h"
#interface IONServer ()
#property (nonatomic) NSMutableArray *storedLogins;
#end
#implementation IONServer
-(void)createStoredLogins
{
NSArray *firstUser = #[#"user1",#"pass1"];
NSArray *secondUser = #[#"user2",#"pass2"];
[self.storedLogins addObject:firstUser];
[self.storedLogins addObject:secondUser];
}
-(instancetype)init {
self = [super init];
if (self) {
[self createStoredLogins];
NSLog(#"Stored logins: %#", _storedLogins);
NSLog(#"Stored user: %#", _storedLogins[0][0]);
}
return self;
}
-(void)login:(NSString *)username password:(NSString *)pw
{
NSArray *logins = [[NSArray alloc]initWithArray:_storedLogins];
for (int i = 0; i < [logins count]; i++) {
if (username == logins[i][0] && pw == logins[i][1]) {
IONLoginResult *result = [[IONLoginResult alloc] initWithResult:YES errorMessage:#"Success!"];
self.result = result;
break;
} else {
IONLoginResult *result = [[IONLoginResult alloc] initWithResult:NO errorMessage:#"Error!"];
self.result = result;
}
}
}
-(void)logout
{
}
#end
You need to initialize the array:
-(instancetype)init {
self = [super init];
if (self) {
_storedLogins = [[NSMutableArray alloc] init];
[self createStoredLogins];
NSLog(#"Stored logins: %#", _storedLogins);
NSLog(#"Stored user: %#", _storedLogins[0][0]);
}
return self;
}
I've been exploring virtual card deck randomisation and drawing of cards as a little side hobby recently, and have been focussing on a great tutorial found at Ontswedder. However, I've run into a minor issue which I'm hoping you can help me with!
Below, I've included some key aspects of the code for your viewing.
In my viewController, I'm wanting to call both the shuffle and draw methods, found in Deck.m. This is possible if I do the following:
Deck *d = [[Deck alloc] init];
[d shuffle];
[d deal];
However, I need to be able to split these. For example, clicking one button initialises the deck, and shuffles it, whilst another new button draws a new card (until the deck is empty).
I am having issues with this, and I could do the following:
Deck *d = [[Deck alloc] init];
[d shuffle];
Deck *d = [[Deck alloc] init];
[d deal];
But this is useless to me, as if I call the init then a NEW, UNSHUFFLED deck is created and the card is dealt from this new deck.
I've tried declaring Deck *DeckObject in viewController.h, then simply calling [DeckObject draw];, however this provides a null value.
Ultimately, I would like to call these two methods separately. Without needing to init a new deck every time if possible!! :-)
I greatly appreciate both everyone's help on this post but also site-wide!
I hope this makes sense, too. Please let me know if you would like more information.
Also, I apologise if any of my terminology is incorrect - still a bit of a newbie!
Included code for context:
Card.h
typedef enum {
Hearts,
Diamonds,
Spades,
Clubs
} Suit;
#define Ace 1
#define Jack 11
#define Queen 12
#define King 13
#interface Card : NSObject {
NSInteger value;
Suit suit;
}
#property (nonatomic) NSInteger value;
#property (nonatomic) Suit suit;
- (id) initWithValue:(NSInteger) aValue suit:(Suit) aSuit;
#end
Card.m
#interface Card(Private)
- (NSString *) valueAsString;
- (NSString *) suitAsString;
#end
#implementation Card
#synthesize value,suit;
- (id) initWithValue:(NSInteger) aValue suit:(Suit) aSuit {
if(self = [super init]) {
self.value = aValue;
self.suit = aSuit;
}
return self;
}
- (NSString *) valueAsString {
switch (self.value) {
case Ace:
return #"Ace";
break;
case Jack:
return #"Jack";
break;
case Queen:
return #"Queen";
break;
case King:
return #"King";
break;
default:
return [NSString stringWithFormat:#"%d",self.value];
break;
}
}
- (NSString *) suitAsString {
switch (self.suit) {
case Hearts:
return #"Hearts";
break;
case Diamonds:
return #"Diamonds";
break;
case Spades:
return #"Spades";
break;
case Clubs:
return #"Clubs";
break;
default:
return nil;
break;
}
}
- (NSString *) description {
return [NSString stringWithFormat:#"%# %#",
[self valueAsString],
[self suitAsString]];
}
#end
Deck.h
#interface Deck : NSObject {
#private
NSMutableArray *cards;
}
- (void) shuffle;
- (Card *) draw;
- (NSInteger) cardsRemaining;
#end
Deck.m
#implementation Deck
- (id) init {
if(self = [super init]) {
cards = [[NSMutableArray alloc] init];
for(int suit = 0; suit <= 3; suit++) {
for(int value = 1; value <= 13; value++) {
Card *card = [[Card alloc] initWithValue:value suit:suit];
[cards addObject:card];
[card release];
}
}
}
return self;
}
int randomSort(id obj1, id obj2, void *context ) {
// returns random number -1 0 1
return (arc4random()%3 - 1);
}
- (void) shuffle {
for(int x = 0; x < 500; x++) {
[cards sortUsingFunction:randomSort context:nil];
}
}
- (Card *) draw {
if([self cardsRemaining] > 0) {
Card *card = [[cards lastObject] retain];
[cards removeLastObject];
return [card autorelease];
}
NSException* myException = [NSException
exceptionWithName:#"OutOfCardsException"
reason:#"Tried to draw a card from a deck with 0 cards." userInfo:nil]; #throw
myException;
}
- (NSInteger) cardsRemaining {
return [cards count];
}
- (NSString *) description {
NSString *desc = [NSString stringWithFormat:#"Deck with %d cards\n",[self
cardsRemaining]];
for(int x = 0; x < [self cardsRemaining]; x++) {
desc = [desc stringByAppendingFormat:#"%#\n",[[cards objectAtIndex:x] description]];
}
return desc;
}
- (void) dealloc {
[cards release];
[super dealloc];
}
#end
When you declare the property deckObject, that just creates the pointer, you still have to alloc init a Deck object to create an instance.
self.deckObject = [[Deck alloc] init];
Then, you can use [self.deckObject shuffle] and [self.deckObject deal]in different button methods.
you have to declaring Deck *DeckObject in viewController.h as below
#interface firstViewController : UIViewController {
Deck *DeckObject;
}
Now in viewController.m file's viewDidLoad method initialize it like below
Deck *DeckObject = [[Deck alloc] init];
after that you can call methods in uibutton's action method
- (IBAction)BtnShuffle:(id)sender
{
if (DeckObject) {
[DeckObject shuffle];
}
}
and
- (IBAction)BtnDraw:(id)sender
{
if (DeckObject) {
[DeckObject draw];
}
}
I am trying to create a NSMutableDictionary in my class. I have read many post in stackoverflow to understand the difference. But now i am totally confused. So any one correct me , which one is the correct way of initialing a NSMutableDictionary in my class . I have to access this dictiionary in many areas of my application .So suggest me the good way of using the variable initialization ...
/// .h file
#interface ActiveFeeds : NSObject {
}
#property (nonatomic, copy) NSMutableDictionary *invDictionary;
#property (nonatomic, retain) NSString *filePath;
#end
#implementation ActiveFeeds
#synthesize filePath;
#synthesize invDictionary;
- (id)init{
self = [super init];
if (self != nil){
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:self.filePath];
self.invDictionary = [dictionary mutableCopy];
dictionary release];
}
return self;
}
/* And use self.invDictionary all in the application */
- (void)setObjectAtKey:(NSMutableDictionary *)objectDic atKey:(NSString *)setKey{
[self.invDictionary setObject:objectDic forKey:setKey];
}
- (void)dealloc {
[self.invDictionary release];
[self.filePath release];
[super dealloc];
}
#end
or like this ....
#interface ActiveFeeds : NSObject {
NSMutableDictionary *invDictionary;
NSString *filePath;
}
#end
#implementation ActiveFeeds
- (id)init{
self = [super init];
if (self != nil){
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
invDictionary = [dictionary mutableCopy];
[dictionary release];
}
}
return self;
}
/* And use invDictionary all in the application */
- (void)setObjectAtKey:(NSMutableDictionary *)objectDic atKey:(NSString *)setKey{
[invDictionary setObject:objectDic forKey:setKey];
}
- (void)dealloc {
[invDictionary release];
[filePath release];
[super dealloc];
}
#end
Please any one help me to get the correct way of using the variables ....
- (id)initWithFilePath:(NSString *)path{
self = [super init];
if (self != nil){
self.filePath = path;
self.invDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:path];
}
return self;
}
also
- (void)dealloc {
[invDictionary release];
[filePath release];
[super dealloc];
}