So I tried to make some changes to a pod someone wrote only they did it in objective c So instead of rewriting the entire thing to swift I figured I would just make the changes in objective c since it would take less time then completely rewriting it.
However I can't seem to get one of my customisations working.
I needed to override the initWithNibName to add an additional parameter to the initialiser. Here is what it looks like now
- (id)initWithNibName:(NSString *)nibNameOrNil dayNib:(NSString *)nibDayNibOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
_calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
_allowClearDate = NO;
_allowSelectionOfSelectedDate = NO;
_clearAsToday = NO;
_daysInFuture = NO;
_daysInHistory = NO;
_historyFutureBasedOnInternal = NO;
_autoCloseCancelDelay = 1.0;
_dateTimeZone = [NSTimeZone defaultTimeZone];
_slideAnimationDuration = .5;
_selectedDates = [[NSMutableArray alloc] init];
_selectedDateViews = [[NSMutableArray alloc] init];
_allowMultiDaySelection = NO;
if(nibDayNibOrNil == nil) {
[self setDayNibName:#"MHDateDay"];
} else {
[self setDayNibName:nibDayNibOrNil];
}
}
return self;
}
However when I install the pod and try to initialise the view controller in a swift project it will give me the following suggestion
var dp = MHDatePickerViewController(nibName: <String>, bundle: <Bundle>)
so for some reason it doesn't seem to see the customisation I did to the initialiser
Does anyone happen to know where I went wrong? why it isn't showing me the correct options?
Related
I'm trying to initiate my ivar like this:
Declared like this in h-file
#interface MyClass: {
UITextView *_myTextView;
}
then created like this in the m-file
- (id)init {
self = [super init];
if(self) {
[self initTextView:_myTextView];
}
return self;
}
- (void)initTextView:(UITextView *)textView {
textView = [[UITextView alloc] init];
...
}
_myTextView will still be nil afterwards. Why is that and what should I do it to make it work? I've got ARC enabled.
[EDIT]
This works. Thanks all!
- (id)init {
self = [super init];
if (self) {
_textView1 = [self createTextView];
_textView2 = [self createTextView];
_textView3 = [self createTextView];
}
return self;
}
- (UITextView *)createTextView {
UITextView *textView = [[UITextView alloc] init];
...
return textView;
}
You need to always refer to instance variables using:
self.textView = [[UITextView alloc] init];
Also use a name other than initTextView as methods starting with init have special meaning in Objective-C.
If you want to use the same code to initialize multiple text view controls, then use code like this:
- (UITextView *)createTextView
{
UITextView *textView = [[UITextView alloc] init];
textView.something = whatever;
...
return textView;
}
And then use it like this:
- (id)init {
self = [super init];
if(self)
{
self.textView1 = [self createTextView];
self.textView2 = [self createTextView];
...
self.textViewN = [self createTextView];
}
}
In [self initTextView:_myTextView]; you pass the current value of _myTextView (which is nil) to your initTextView: method. To set the instance variable, you need a pointer to a pointer.
- (id)init {
self = [super init];
if (self) {
[self setupTextView:&_myTextView];
}
return self;
}
- (void)setupTextView:(UITextView * __strong *)textView {
*textView = [[UITextView alloc] init];
...
}
I also renamed the initTextView: method to setupTextView, as methods starting with init are expected to behave like other init methods in ARC.
- (id)init {
self = [super init];
if(self) {
[self initTextView];
}
}
- (void)initTextView{
_myTextView = [[UITextView alloc] init];
...
}
if you want to call initTextView for several text views , you can code like this :
- (id)init {
self = [super init];
if(self) {
_myTextView = [[UITextView alloc] init];
[self initTextView:_myTextView];
}
}
- (void)initTextView:(UITextView *)textView{
//setup the textView
...
}
#import "BirdsDetailViewController.h"
#import "BirdSighting.h"
#interface BirdsDetailViewController ()
- (void)configureView;
#end
#implementation BirdsDetailViewController
-(void)setSighting:(BirdSighting *)sighting
{
if (_sighting != sighting) {
_sighting = sighting;
//Update the view
[self configureView];
// Is this code[self configureView] necessary which reappears in the later viewDidLoad?
//After I deleted this line everything seems works well.
}
}
- (void)configureView
{
// Update the user interface for the detail item.
BirdSighting *theSighting = self.sighting;
static NSDateFormatter *formatter = nil;
if (formatter == nil) {
formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterMediumStyle];
}
if (theSighting) {
self.birdNameLable.text = theSighting.name;
self.locationLable.text = theSighting.location;
self.dateLable.text = [formatter stringFromDate:(NSDate *) theSighting.date];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
//You see. It reappears here.
[self configureView];
}
#end
The code above is quoted from Apple's official sample(Your Second iOS App: Storyboards ).
Is this code [self configureView] in the setSighting: necessary which reappears later ?After I deleted this line everything seems works well.
Thank you very much.
You can ommit [self configureView]; in setSighting:.
And One more thing why you are implementing setSighting: yourself, Cocoa provides you #property/#synthesize, that is trusted and will be shorter for your code as you are doing nothing specific.
I try create tab bar controller programatically, it works but I can not set title to ta bar items. I can not see title when I running my application. My code is here. Please help me, what is the problem?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
myTabBarController = [[UITabBarController alloc] init];
view2Controller = [[testView alloc] init];
view3Controller = [[testView2 alloc] init];
view4Controller = [[testView3 alloc] init];
view5Controller = [[testView4 alloc] init];
view6Controller = [[testView5 alloc] init];
myTabBarController.viewControllers = [NSArray arrayWithObjects: view2Controller, view3Controller,view4Controller,view5Controller,view6Controller,nil];
UITabBarItem *tabItem = [[[myTabBarController tabBar] items] objectAtIndex:1];
[tabItem setTitle:#"theTitle"];
[self.view addSubview:myTabBarController.view];
myTabBarController.selectedIndex=0;
}
Set the title of ur viewcontroller in side viewcontroller's viewwillappear/disappear and it will be displayed in ur tabbaritem.
You can set the title of UIViewController, which reflects when it is pushed in UINavigationController or a UITabBarController. But you should set the title before putting it inside any of them.
init is generally a good place to set the title.
- (id)init {
// ... other code including check for self
self.title = #"My Title";
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// self.title = #"My Title";
}
self.title = #"My Title";
return self;
}
Use above code in every subviews of tabbar controllers.
This may be help.
use this code
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title=#"FREE BOOKS";
self.tabBarItem.image = [UIImage imageNamed:#"first"];
}
return self;
}
Here is the tutorial from the scratch which should help you to achieve the exact functionality you want to achieve. Download the source code and run it directly and if title are correct the you can follow the tutorial to get the proper understanding of the flow of UITabBarController.
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
self.tabBar.items?[0].title = "Title"
}
}
OR
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBar.items?[0].title = "Title"
}
I have cocos2d project with custom CCSprite subclass:
MyCustomSprite.h:
#import "cocos2d.h"
#interface MyCustomSprite : CCSprite
#end
MyCustomSprite.m:
#import "MyCustomSprite.h"
#implementation MyCustomSprite
- (id)init
{
self = [super initWithFile:#"index.png"];
return self;
}
#end
For some strange reason, this code will crash with "EXC_BAD_ACCESS".
But in spite of this, if i init super as ususal and then write code from CCSprite's initWithFile and initWithTexture, it will work fine:
self = [super init];
if (self) {
// Code from CCSprite.m - initWithFile
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: #"index.png"];
CGRect rect = CGRectZero;
rect.size = texture.contentSize;
// Code from CCSprite.m - iniWithTexture
[self setTexture:texture];
[self setTextureRect:rect];
return self;
}
What's the reason that the first example crashes, and second not and what's the difference between them?
Thanks for your answers!
Ok, the reason is bad CCSprite design. If we look to CCSprite.h, we can find:
-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
{
NSAssert(texture!=nil, #"Invalid texture for sprite");
// IMPORTANT: [self init] and not [super init];
if( (self = [self init]) )
}
And thats the reason. Instead of [super init] this method calls [self init], and creates recursion ([self init]-[super InitWithFile:]-[self initWithTexture]-[self init]-...).
.
So, the simplest way to solve this problem - just re-name your init method to something else (for example "initialize") and call it instead of init: [[MyCustomSprite
alloc] initialize].
Another approach that may work is just replace your code by this one:
- (id)init
{
self = [super init];
if (self != nil)
{
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:#"my_image_name.png"];
CGRect rect = CGRectZero;
if (texture != nil)
{
rect.size = texture.contentSize;
}
[self setDisplayFrame:[CCSpriteFrame frameWithTexture:texture rect:rect]];
}
return self;
}
And a simpler way, if you are using CCSpriteFrameCache, would be just setting the display frame by
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"my_image_name.png"]
Hope to help somebody!
I essentially want to give each instance of a class a unique id.
So, I created a static integer. I increment it each time a new object is created and then assign the value of the static variable to an ivar. But clearly I don't understand something because, let's say I create three objects, "thisPageNumber" (which is the instance variable) is always 3 no matter which object I reference.
More information:
This class creates a number of "Page" objects. I'd like each page to know it's page number so that it can display the correct page art as well as perform a number of other various actions.
.h partial code:
#interface Page : UIViewController
{
NSNumber *thisPageNumber;
UIImageView *thisPageView;
UIImageView *nextPageView;
UIImageView *prevPageView;
UIImageView *pageArt;
}
.m partial code:
#implementation Page
static int pageCount = 0;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
pageCount++;
thisPageNumber = pageCount;
}
return self;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
CGRect defaultFrame = CGRectMake(0.0, 0.0, 1024.0, 768.0);
if (thisPageView == nil) {
thisPageView = [[UIImageView alloc]
initWithImage:[UIImage
imageNamed:[NSString stringWithFormat:#"Page%i.png", [thisPageNumber intValue]]]];
thisPageView.frame = defaultFrame;
[self.view addSubview:thisPageView];
}
if (nextPageView == nil && [thisPageNumber intValue] < BOOK_PAGE_COUNT) {
nextPageView = [[UIImageView alloc]
initWithImage:[UIImage
imageNamed:[NSString stringWithFormat:#"Page%i.png", [thisPageNumber intValue]+1]]];
nextPageView.frame = defaultFrame;
[self.view addSubview:nextPageView];
}
if (prevPageView == nil && [thisPageNumber intValue] > 1) {
prevPageView = [[UIImageView alloc]
initWithImage:[UIImage
imageNamed:[NSString stringWithFormat:#"Page%i.png", [thisPageNumber intValue]-1]]];
prevPageView.frame = defaultFrame;
[self.view addSubview:prevPageView];
}
}
I'm not sure why the compiler didn't complain, but part of your problem is here:
thisPageNumber = pageCount;
NSNumber is an object. To set it to the current pageCount value, use
thisPageNumber = [[NSNumber alloc] initWithInt:pageCount];
Why don't you just use self as the unique ID? It's unique.