iOS: Viewcontroller subclassed from MWPhotoBrowser-images are not loaded - ios

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.

Related

Object cannot be nil When trying to addObject

[__NSArrayM insertObject:atIndex:]: object cannot be nil
The problem is when trying to execute [_eventsArray addObject:eventModel]; error is occurred.
eventModel is nil.
How can I solve this problem ?
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) NSMutableArray *eventsArray;
#end
#interface EventsModel : NSObject
#property(nonatomic, assign) NSString *title;
#property(nonatomic, strong) NSString *details;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
EventsModel *eventModel ;
eventModel.title = #"Meeting";
eventModel.details = #"some description";
[_eventsArray addObject:eventModel];
}
#end
#pragma mark - Model Class
#implementation EventsModel
-(instancetype)init{
self = [super init];
if (self) {
self.title = nil;
self.details =nil;
}
return self;
}
#end
EventsModel *model = [EventsModel new];
model.title = #"test";
model.details = #"Detail test";
EventsModel *model2 = [EventsModel new];
model2.title = #"test2";
model2.details = #"Detail test2";
[_eventsArray addObject:model];
[_eventsArray addObject:model2];
NSLog(#"%lu elements in array",(unsigned long)_eventsArray.count);
you use EventsModel *model = [EvenntsModel new]; and create object
try this code

How to add object in singleton NSMutableArray

I used to store the array data downloaded from the server.
But I can not save them in the singleton array.
It seems without access to the object.
Why ulatitude, ulongitude, uaccuracy, uplacename is nil?...
in .h file
#import <Foundation/Foundation.h>
#interface LocationData : NSObject
{
NSMutableArray *ulatitude;
NSMutableArray *ulongitude;
NSMutableArray *uaccuracy;
NSMutableArray *uplacename;
}
#property (nonatomic, retain) NSMutableArray *ulatitude;
#property (nonatomic, retain) NSMutableArray *ulongitude;
#property (nonatomic, retain) NSMutableArray *uaccuracy;
#property (nonatomic, retain) NSMutableArray *uplacename;
+ (LocationData*) sharedStateInstance;
#end
in .m file
#import "LocationData.h"
#implementation LocationData
#synthesize uaccuracy;
#synthesize ulatitude;
#synthesize ulongitude;
+ (LocationData*) sharedStateInstance {
static LocationData *sharedStateInstance;
#synchronized(self) {
if(!sharedStateInstance) {
sharedStateInstance = [[LocationData alloc] init];
}
}
return sharedStateInstance;
}
#end
use
[manager POST:urlStr parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"%#",responseObject);
// json response array
if ([responseObject isKindOfClass:[NSArray class]]) {
NSArray *responseArray = responseObject;
NSDictionary *responseDict = [[NSDictionary alloc] init];
LocationData* sharedState = [LocationData sharedStateInstance];
for(NSUInteger i=0; i < responseArray.count; i++)
{
responseDict = [responseArray objectAtIndex:i];
double dlat = [[responseDict objectForKey:#"lat"] doubleValue];
double dlng = [[responseDict objectForKey:#"lng"] doubleValue];
[[sharedState ulatitude] addObject:[NSString stringWithFormat:#"%f",dlat]];
[[sharedState ulongitude] addObject:[NSString stringWithFormat:#"%f",dlng]];
[[sharedState uaccuracy] addObject:[responseDict objectForKey:#"rad"]];
[[sharedState uplacename] addObject:[responseDict objectForKey:#"place_name"]];
}
You always need to initialize your arrays. You should do somewhere before you try to add something to them:
arrayName = [[NSMutableArray alloc] init];
otherwise you'll always get error because they have not been initialized.
In your case you should override your LocationData init function like this:
- (instancetype)init {
self = [super init];
if (self) {
self.yourArrayName = [[NSMutableArray alloc] init];
// And so on....
}
return self;
}
You need to initialize your object properly. Basically your member variables ("ivars") are pointing to nothing ("nil").
This initializer added to your .m file code do the job.
-(instancetype)init {
if ((self = [super init])) {
self.accuracy = [NSMutableArray array];
self.latitude = [NSMutableArray array];
self.longitude = [NSMutableArray array];
self.uplacename = [NSMutableArray array];
}
return self;
}
As a singleton pattern, I'd prefer the following:
+ (LocationData*) sharedStateInstance {
static LocationData *sharedStateInstance = nil;
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
sharedStateInstance = [[LocationData alloc] init];
});
return sharedStateInstance;
}
Although singletons might not be as bad they are often said to be, I don't thing that this is a good usage for them. Your specific problem has nothing to do with that design choice, though.
Try this code. Write getters for your NSMutableArrays.
#import <Foundation/Foundation.h>
#interface LocationData : NSObject
#property (nonatomic, retain) NSMutableArray *ulatitude;
#property (nonatomic, retain) NSMutableArray *ulongitude;
#property (nonatomic, retain) NSMutableArray *uaccuracy;
#property (nonatomic, retain) NSMutableArray *uplacename;
+ (LocationData*) sharedStateInstance;
#end
#import "LocationData.h"
#implementation LocationData
#synthesize uaccuracy = _uaccuracy;
#synthesize ulatitude = _ulatitude;
#synthesize ulongitude = _ulongitude;
+ (LocationData*) sharedStateInstance {
static LocationData *sharedStateInstance;
#synchronized(self) {
if(!sharedStateInstance) {
sharedStateInstance = [[LocationData alloc] init];
}
}
return sharedStateInstance;
}
-(NSMutableArray*)uaccuracy
{
if(_uaccuracy == nil)
{
_uaccuracy = [[NSMutableArray alloc]init];
}
return uaccuracy;
}
-(NSMutableArray*)ulongitude
{
if(_ulongitude == nil)
{
_ulongitude = [[NSMutableArray alloc]init];
}
return ulongitude;
}
-(NSMutableArray*)ulatitude
{
if(_ulatitude == nil)
{
_ulatitude = [[NSMutableArray alloc]init];
}
return ulatitude;
}
-(NSMutableArray*)uplacename
{
if(_uplacename == nil)
{
_uplacename = [[NSMutableArray alloc]init];
}
return uplacename;
}
#end
you don't allocate/init any array...
you can create them in your singleton creation method
+ (LocationData*) sharedStateInstance {
static LocationData *sharedStateInstance;
#synchronized(self) {
if(!sharedStateInstance) {
sharedStateInstance = [[LocationData alloc] init];
sharedStateInstance.ulatitude = [[NSMutableArray alloc] init];
// (add others...)
}
}
return sharedStateInstance;
}
Replace your LocationData.m file with below code , this will work . As you have to alloc and init the array then only you can add object in array
+ (LocationData*) sharedStateInstance {
static LocationData *sharedStateInstance;
#synchronized(self) {
if(!sharedStateInstance) {
sharedStateInstance = [[LocationData alloc] init];
uaccuracy = [[NSMutableArray alloc]init];
ulatitude = [[NSMutableArray alloc]init];
ulongitude = [[NSMutableArray alloc]init];
uplacename = [[NSMutableArray alloc]init];
}
}
return sharedStateInstance;
}

iOS NSKeyedUnarchiver not get correct value

I simplify the code for ask question.
I want to save more class and load class model file.
But now I simplify parameters to one part (lim) in the model(FlightSettingModel.h).
In the FlightSettingModel.h I have set some parameters in here.
FlightSettingModel.h code below:
#import <Foundation/Foundation.h>
#interface FlightSettingModel : NSObject<NSCoding>
// lim property part
#property float limCurrentVal;
#property float limDefaultVal;
#property float limMaxVal;
#property float limMinVal;
// .... other property part
#end
FlightSettingModel.m code below
#import "FlightSettingModel.h"
#interface FlightSettingModel()
{
}
#end
#implementation FlightSettingModel
-(instancetype)init
{
self = [super init];
if(self)
{
self.limDefaultVal = 3.0;
self.limCurrentVal = 4.0;
self.limMaxVal = 10;
self.limMinVal = 0;
// ... other property part value init .....
}
return self;
}
- (void)setFlightSettingToDefaultValue
{
self.limCurrentVal = self.limDefaultVal;
}
- (void) encodeWithCoder: (NSCoder *)encoder
{
[encoder encodeFloat:self.limCurrentVal forKey:#"limCurrentVal"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if((self = [super init])) {
self.limCurrentVal = [decoder decodeFloatForKey:#"limCurrentVal"];
}
return self;
}
#end
Then I have set the singleton SettingData file to initial the FlightSettingModel and other model class.
The SettingData model header like below:
#import <Foundation/Foundation.h>
#import "FlightSettingModel.h"
#interface SettingData : NSObject
#property (nonatomic,strong) FlightSettingModel *flightSettingModel;
+(SettingData*) sharedInstance;
#end
SettingData.m code below:
#import "SettingData.h"
#implementation SettingData
SettingData *sharedInstance;
+(SettingData*) sharedInstance{
if( sharedInstance == nil )
{
sharedInstance = [SettingData new];
}
return sharedInstance;
}
-(id) init{
self = [super init];
if( self )
{
self.flightSettingModel = [FlightSettingModel new];
}
return self;
}
#end
In my storyboard (UI) is like below:
When I click the save button , I want to save the custom class model(FlightSettingModel.h) in the NSKeyedArchiver. When I click the load, I want to load the model from the archiver using NSKeyedUnarchiver and resetting to the slider.
But now,when I drag the slider to other value(ex:10), then I click the save, then I close the app restart the app. I click the load, the slider value will become 0.
I don't know why when I load the value the all value will become 0;
My view controller code .m below:
#import "ViewController.h"
#import "SettingData.h"
#interface ViewController ()
{
NSString *path;
NSString *fileName;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// file manage
path =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
fileName = [path stringByAppendingPathComponent:#"flightFile"];
[self setUIValue];
NSLog(#"---");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (IBAction)saveAction:(UIButton *)sender {
[NSKeyedArchiver archiveRootObject:[SettingData sharedInstance].flightSettingModel toFile:fileName];
}
- (IBAction)loadAction:(UIButton *)sender {
[SettingData sharedInstance].flightSettingModel = (FlightSettingModel*) [NSKeyedUnarchiver unarchiveObjectWithFile: fileName];
[self setUIValue];
NSLog(#"current Value:%.f",[SettingData sharedInstance].flightSettingModel.limCurrentVal);
}
- (IBAction)sliderChangedAction:(UISlider *)sender {
[SettingData sharedInstance].flightSettingModel.limCurrentVal = sender.value;
self.theTextField.text = [NSString stringWithFormat:#"%.f",self.theSlider.value];
}
-(void) setUIValue
{
// setting slider property
self.theSlider.maximumValue = [SettingData sharedInstance].flightSettingModel.limMaxVal;
self.theSlider.minimumValue = [SettingData sharedInstance].flightSettingModel.limMinVal;
self.theSlider.value = [SettingData sharedInstance].flightSettingModel.limCurrentVal;
self.theTextField.text = [NSString stringWithFormat:#"%.f",self.theSlider.value];
}
#end
Have anyone know where my problem in my code?
thank you very much.
If you want to download the complete code(the question code) , I have upload in github
This behavior happens because the [SettingData sharedInstance].flightSettingModel.limMaxVal and the [SettingData sharedInstance].flightSettingModel.limMinVal are zero:
-(void) setUIValue
{
// setting slider property
self.theSlider.maximumValue = [SettingData sharedInstance].flightSettingModel.limMaxVal;
// self.theSlider.maximumValue = 0
self.theSlider.minimumValue = [SettingData sharedInstance].flightSettingModel.limMinVal;
// self.theSlider.minimumValue = 0
self.theSlider.value = [SettingData sharedInstance].flightSettingModel.limCurrentVal;
// [SettingData sharedInstance].flightSettingModel.limCurrentVal = 10
self.theTextField.text = [NSString stringWithFormat:#"%.f",self.theSlider.value];
}
EDIT: You can fix it by adding this:
- (void) encodeWithCoder: (NSCoder *)encoder {
[encoder encodeFloat:self.limCurrentVal forKey:#"limCurrentVal"];
[encoder encodeFloat:self.limMaxVal forKey:#"limMaxVal"];
[encoder encodeFloat:self.limMinVal forKey:#"limMinVal"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if((self = [super init])) {
self.limCurrentVal = [decoder decodeFloatForKey:#"limCurrentVal"];
self.limMaxVal = [decoder decodeFloatForKey:#"limMaxVal"];
self.limMinVal = [decoder decodeFloatForKey:#"limMinVal"];
}
return self;
}

restart object in objective c - Matchismo Assignment 2 - Restart game

I was trying to solve assignment 2 from Stanford iOS7 development (Matchismo card game)
The game works fine. Now I have to add the Restart function. If the user press on the restart button, the game restarts (it deals new cards and it resets the score)
my game model is the #property (nonatomic, strong) CardMatchingGame *game;
this is the code for the CardMatchingGame.m:
#import "CardMatchingGame.h"
#import "PlayingCardDeck.h"
#interface CardMatchingGame()
#property (nonatomic, readwrite) NSInteger score;
#property (nonatomic, strong) NSMutableArray *cards;
#end
#implementation CardMatchingGame
static const int MATCH_BONUS = 4;
static const int MATCH_PENALTY = 2;
static const int COST_TO_CHOOSE = 1;
-(NSMutableArray *)cards{
if(!_cards) _cards = [[NSMutableArray alloc]init];
return _cards;
}
-(instancetype)initWithCardCount:(NSUInteger)count usingDeck:(Deck *)deck{
self = [super init];
if(self){
for(int i=0; i < count; i++){
Card *card = [deck drawRandomCard];
if(card){
[self.cards addObject:card];
} else{
self = nil;
break;
}
}
}
return self;
}
-(void)chooseCardAtIndex:(NSUInteger)index{
Card *card = [self cardAtIndex:index];
if(!card.isMatched){
if(card.isChosen){
card.chosen = NO;
} else{
for(Card *otherCard in self.cards){
if(otherCard.isChosen && !otherCard.isMatched){
int matchScore = [card match:#[otherCard]];
if(matchScore){
self.score += matchScore * MATCH_BONUS;
card.matched = YES;
otherCard.matched = YES;
} else{
self.score -= MATCH_PENALTY;
otherCard.chosen = NO;
}
break;
}
}
self.score -= COST_TO_CHOOSE;
card.chosen = YES;
}
}
}
-(Card *)cardAtIndex:(NSUInteger)index{
return (index < [self.cards count]) ? self.cards[index] : nil;
}
#end
here is my CardGameViewController.m:
#import "CardGameViewController.h"
#import "PlayingCardDeck.h"
#import "CardMatchingGame.h"
#interface CardGameViewController ()
#property (nonatomic, strong) Deck *deck;
#property (nonatomic, strong) CardMatchingGame *game;
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardsCollection;
#property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
#end
#implementation CardGameViewController
#synthesize game = _game;
-(CardMatchingGame *)game{
if(!_game) _game = [[CardMatchingGame alloc] initWithCardCount:[self.cardsCollection count]
usingDeck:self.deck];
return _game;
}
-(Deck *)deck{
if(!_deck) _deck = [[PlayingCardDeck alloc] init];
return _deck;
}
- (IBAction)touchRestartButton:(id)sender {
self.game = nil;
[self updateUI];
}
- (IBAction)touchCardButton:(UIButton *)sender {
int chosenButtonIndex = [self.cardsCollection indexOfObject:sender];
[self.game chooseCardAtIndex:chosenButtonIndex];
[self updateUI];
}
-(void)updateUI{
for(UIButton *cardButton in self.cardsCollection){
int buttonIndex = [self.cardsCollection indexOfObject:cardButton];
Card *card = [self.game cardAtIndex:buttonIndex];
[cardButton setTitle:[self titleForCard:card] forState:UIControlStateNormal];
[cardButton setBackgroundImage:[self backgroundImageForCard:card] forState:UIControlStateNormal];
cardButton.enabled = !card.isMatched;
}
self.scoreLabel.text = [NSString stringWithFormat:#"Score: %d", self.game.score];
}
-(NSString *)titleForCard:(Card *)card{
return card.isChosen ? card.contents : #"";
}
-(UIImage *)backgroundImageForCard:(Card *)card{
return [UIImage imageNamed: card.isChosen ? #"cardfront" : #"cardback"];
}
#end
In order to restart the game, I think I should simply re-initialize the property CardMatchingGame *game.
This is what I tried to do, by setting self.game = nil; Then it should automatically be re-initialized in the getter of game.
This is, indeed, the solution that I found on the internet. However, in my program it doesn't work. *game is set to nil and never restored, so the game ends when you click restart.
Could you please help me to figure out why self.game = nil doesn't work in my case?
- (IBAction)startover:(UIButton *)sender {
self.game= [[CardMatchingGame alloc] initWithCardCount:[self.cardButtons count] usingDeck:[self createDeck]];
[self updateUI];
}
If your program has the lazy init style recommended, there is no need for a new method such as start over. You are correct to set self.game to nil, now a call the the getter will start a new instance of the game. I did it by making a call to UIUpdate right after the self.game = nil. That has a call to the getter and lazily inits a new instance of the game.

Infinite loop and access error on app startup on model init

Please help....I'm losing my mind trying to figure out this problem.
I'm fairly new to iOS so don't go too hard on me if it's something obvious! ;)
I'm using xcode 4.6 and targeting iPhone6.1 Simulator.
I get the following error when starting up my app:
EXC_BAD_ACCESS code = 2
There are hundres of threads appearing in Debug Navigator which leads to to believe there is some sort of infinite loop somewhere (I just cannot see where).
The error occurs beside (id)init in PlayingCardDeck.m after entering it from ViewController.m at line:
Card *card = [self.deck drawRandonCard];
ViewConrtoller:
#import "ViewController.h"
#import "PlayingCardDeck.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UILabel *flipsLabel;
#property (nonatomic) int flipCount;
#property (strong, nonatomic) Deck *deck;
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;
#end
#implementation ViewController
#synthesize deck = _deck;
- (IBAction)flipCard:(UIButton *)sender {
sender.selected = !sender.isSelected;
self.flipCount++;
}
- (void)setFlipCount:(int)flipCount
{
_flipCount = flipCount;
self.flipsLabel.text = [NSString stringWithFormat:#"Flips: %d", self.flipCount];
}
- (Deck *)deck
{
if (!_deck) _deck = [[PlayingCardDeck alloc] init];
return _deck;
}
- (void)setCardButtons:(NSArray *)cardButtons
{
_cardButtons = cardButtons;
for (UIButton *cardButton in cardButtons)
{
Card *card = [self.deck drawRandonCard];
[cardButton setTitle:card.contents forState:UIControlStateSelected];
}
}
#end
Deck.m
#import "Deck.h"
#interface Deck()
#property (strong, nonatomic) NSMutableArray *cards;
#end
#implementation Deck
- (NSMutableArray *)cards
{
if (!_cards) _cards = [[NSMutableArray alloc] init];
return _cards;
}
- (void)addCard:(Card *)card atTop:(BOOL)atTop
{
if (atTop)
{
[self.cards insertObject:card atIndex:0];
}
else
{
[self.cards addObject:card];
}
}
- (Card *)drawRandonCard
{
Card *randomCard = nil;
if (self.cards.count)
{
unsigned index = arc4random() % self.cards.count;
randomCard = self.cards[index];
[self.cards removeObjectAtIndex:index];
}
return randomCard;
}
#end
PlayingCardDeck.m
#import "PlayingCardDeck.h"
#import "PlayingCard.h"
#implementation PlayingCardDeck
- (id)init
{
self = [self init];
if (self)
{
for (NSString *suit in [PlayingCard validSuits])
{
for (NSUInteger rank=1; rank <= [PlayingCard maxRank]; rank++)
{
PlayingCard *card = [[PlayingCard alloc] init];
card.suit = suit;
card.rank = rank;
[self addCard:card atTop:YES];
}
}
}
return self;
}
#end
In PlayerCardDeck.m self = [self init] should be self = [super init]. That's causing the infinite loop.

Resources